实验基本原理&目的

Sql 注入攻击是通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击,它目前黑客对数据库进行攻击的最常用手段之一。

参考blog:SQL注入基本原理

实验过程

猜解数据库

Step1:理解PHP页面通过get方法传递参数

当我们的sercurity level为low的时候,分析网页的html源码会发现是php的参数通过get方法来进行获取的

1-2

而当时medium的时候,是通过POST来获取的,用户不再输入,而是仅能通过选择来进行

1-3

Step 2:查看source code

当安全级别为medium的时候,我们可以看到source code中的SQL查询语句为

1-1

那么当我们输入id(例如:1)之后,所构造的SQL的完整语句就是

SELECT first_name, last_name FROM users WHERE user_id = '1';

意思是在名为users的表中找到user_id这个列中内容为"1"的那一条数据的first_name以及last_name的值

所以之后我们可以通过控制输入的参数id的值来调整执行的SQL语句

Step 3:猜解SQL查询语句当中的字段数

  • (可能是在这里有输入的提示才不进行SQL注入类型的判断,但是正常情况下要实现判断注入的类型时字符型还是数字型)

在这里通过Burp Suit输入1' order by 1#,此时php所要执行的SQL语句就变为了

SELECT first_name, last_name FROM users WHERE user_id = '1' order by 1#';

此时SQL会把#后面内容屏蔽来避免语句错误,但是此时会发现提示语法错误

1-6

在这里,根据参考渗透学习笔记–基础篇–sql注入(数字型)会发现是由于’ 被转义为了\,之后注入的时候只需要输入1 order by 1#即可

1-4

结果为

1-7

同时测试1 order by 2#,发现也成功,但是到了order by 3#的时候,会发现出现错误,说明这个名为users的表应该是2列

1-8

Step 4:获取数据库名等信息

在这里,我们构造1 union select database(),user()

  • database()会返回当前网站所使用的数据库的名字
  • user()会返回执行当前查询的用户的名字

此时,SQL实际执行的语句应该为

SELECT first_name, last_name FROM users WHERE user_id = '1'
union
select database(),user()#;

意思为,首先在user这个表中找到user_id 为1的first_name和last name两列,之后再select database(), user(),最后将两个select出的表格合并,之后返回html页面,如图显示,所以数据库名为dvwa,执行当前查询的用户的名字为root@localhost

1-9

Step 5:获取数据库版本以及操作系统信息

在这里,我们输入的是1 union select version(),@@version_compile_os#

  • version()获取当前数据库的版本信息
  • @@version_compile_os获取当前操作系统信息

此时,实际执行的SQL语句为

SELECT first_name, last_name FROM users WHERE user_id = '1' 
union 
select version(),@@version_compile_os#;

具体的意思可结合上面step和函数作用了解,执行结果为下图,我们可以了解当前数据库版本为5.5.53,操作系统为win32

2-1

Step 6:获取数据库中的表名

information_schema 是 mysql 自带的一张表,这张数据表保存了 Mysql 服务器所有数据库的信息,如数据库名,数据库的表,表栏的数据类型与访问权限等。该数据库拥有一个名为 tables 的数据表,该表包含两个字段 table_name 和 table_schema,分别记录 DBMS 中的存储的表名和表名所在的数据库

我们输入的内容为 1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#,但是由于存在转义字符,所以可以采用16进制来写dvwa或者database()来代替,实际所执行的SQL语句为

SELECT first_name, last_name FROM users WHERE user_id = '1' 
union
select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#;

结果如下

2-2

所以此时我们可以得到dvwa这个数据库下面有两个表,分别名为guestbookusers

验证绕过,级别为medium

首先来看能够正确验证,我们在userpassword直接输入123,会发现提示此时账户/密码不正确

2-3

之后来看后台的php代码的具体运行情况,发现比较重要的是SQL的select语句以及后面呢条件判断,而当我们输入123的时候,实际执行的SQL语句为

select * from users where username='123' and password='123'

在这里好像有转义字符的限制,我们通过将捕获的包Intruder模块来实现,可以用暴力破解来实现,可以看到password的字段长度和其他的明显不一样(因为返回的正确信息的长度和错误信息的长度不一样),所以密码可能就是password,试验后发现成功login

2-6

2-7

判断注入点

4.1 判断是否存在注入漏洞

一般我们进行判断的时候,在输入的参数后面加一个单引号,比如

http://xxx/abc.php?id=1'

当页面返回错误的时候,说明是存在SQL注入的,因为无论字符型还是整型都会因为单引号个数不匹配而报错(比如在安全级别为low的时候,当我们输入1’的时候,会报语法错误)。

3-1

而如果未报错,不代表不存在 Sql 注入,因为有可能页面对单引号做了过滤/转义,这时可以使用判断语句进行注入(比如在安全级别为medium的时候进行了转义)

*4.2 判断注入类型是字符型还是数字型 *

当输入and 1=1,此时执行的SQL语句就是

select * from <表名> where id = x and 1=1

如果此时成功,试验and 1=2

select * from <表名> where id = x and 1=2

如果此时失败,则综合上面的,说明类型为数字型,因为如果注入类型为字符型,就会出现,此时并没有执行and语句后面的判断,所以不会出现上面一正一负的结果

select * from <表名> where id = 'x and 1=1' 
select * from <表名> where id = 'x and 1=2'

而当注入类型为字符型的时候,一般SQL语句为

select * from <表名> where id = 'x'

此时通过 and '1'='1and '1'='2来判断,因为此时的执行的SQL语句为(一正一负的结果)

select * from <表名> where id = 'x' and '1'='1'
select * from <表名> where id = 'x' and '1'='2'

如果假设为数字型,则会变为下面的SQL语句,此时都会是语法错误

select * from <表名> where id = x and '1'='1
select * from <表名> where id = x and '1'='2

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

VPN 上一篇
爬虫PJ 下一篇