关于PHP代码审计和漏洞挖掘的一点思考

这里对PHP的代码审计和漏洞挖掘的思路做一下总结,都是个人观点,有不对的地方请多多指出。

PHP的漏洞有很大一部分是来自于程序员本身的经验不足,当然和服务器的配置有关,但那属于系统安全范畴了,我不太懂,今天我想主要谈谈关于PHP代码审计和漏洞挖掘的一些思路和理解。

PHP的漏洞发掘,其实就是web的渗透测试,和客户端的fuzzing测试一样,web的渗透测试也可以使用类似的技术,web fuzzing,即基于web的动态扫描。

这类软件国内外有很多,如WVS,Lan Guard,SSS等。这类扫描器的共同特点都是基于蜘蛛引擎对我们给出的URL地址进行遍历搜索,对得到的URL和参数进行记录,然后使用本地或者web端的script脚本攻击语句进行攻击测试。

如:

WVS使用本地的脚本攻击数据库对这些参数进行交叉替换和填充,构造出新的URL,然后用GET或者POST的方式向服务器发出请求,并对返回的结果进行正则判断。如是否出现:” You have an error in your SQL syntax”等字样。如果出现,则记录下来,说明这个脚本页面”可能”存在漏洞。

1

 

WVS把攻击分成了很多模块:

每种攻击测试方式都对应着一类scripts,里面包含了攻击语句。

用WVS扫描完之后,如果能发现一些sql注入点的提示,这个时候可以先用sqlmap进行注入尝试,进一步判断注入点的情况。

(小编插句话:WVS查找的漏洞提示分两种,一种是启发式测试,就是作者说的“可能”。另外一种是带(verify)字样的,如果看到这个字样就恭喜你了,这是一个被证实的漏洞。小编就曾经利用这个方法发掘过漏洞,效果不错。另外作者说的使用sqlmap进行测试,小编这里不太推荐。对于漏洞挖掘来说,最好使用手工注入的方式来测试漏洞是否存在,毕竟现在只是挖掘漏洞,还不是在利用漏洞。我相信很多人都遇到过手工能测试成功,但是用sqlmap测试不出来的时候。)

如果这两步都不能成功,说明基于fuzz的动态扫描不能继续下去了,这个时候,我们应该想办法进行静态的代码审计,从源代码的角度分析和挖掘漏洞的成因和利用方式。这块可以使用RIPS这样的软件,RIPS是一款专门用来进行静态PHP代码审计的工具,能够帮助我们定位到可能存在漏洞的代码区域。

2

RIPS对代码进行静态漏洞扫描的基本思想有两条:

1.       对容易产生漏洞的函数进行跟踪(例如:mysql_query())

RIPS认为,所有的注入漏洞最终都要经过一些特定的数据库操作函数,mysql_query()或程序自定义的类函数,这些函数是产生漏洞的导火索,只要对这些函数的控制流和参数流进行回溯扫描,就可以发现大部分的代码漏洞。

2.       对产生注入漏洞的源头即用户传输过来的数据流进行跟踪($_GET,$_POST,$_COOKIE)

“用户输入的一切数据都有害”,大部分的注入漏洞,包括二次注入,究其原因都是因为对用户的输入数据没有做好过滤,RIPS对这些敏感数据进行跟踪,并判断其在进入敏感函数(mysql_query())之前有没有对其进行有效处理(addslashes())来判断这条数据流是否存在漏洞。

动态扫描加上静态定位,最终使我们能更容易的发现一些漏洞并及时使其得到修补。

接下来,我们来针对一个已知的漏洞进行一次分析。

DedeCms V5 orderby参数注射漏洞

SSV-ID3824

SSV-AppDir织梦

URLhttp://sebug.net/vuldb/ssvid-3824

1.       动态扫描

架设好服务器和网站后,我们使用WVS对网站的根目录进行扫描,因为我们现在是黑盒测试,所以直接从网站根目录开始扫描。

3

 

(91ri.org:图片中显示的就是带verify字样的,代表存在漏洞了,这时候我们只需要使用WVS自带的HTTP EDITOR来测试语句即可,重点测试应该在不带verify字样的可能注入点。)

等待一段时间后,扫描结果出来了,得到一些疑似SQL注入的URL。这里研究一下WVS的注入测试原理是什么,通过查看apache的access.log。我们发现了一下请求(无关部分已经删除)。

可以看到,WVS采用的是一种基于时间延迟的盲注入测试技术。

91ri.org:WVS利用了各种注入测试语句,不仅仅包括延时注入,对于显错,bool值盲注都有测试payload,有兴趣的人可以看安装目录下的自带脚本。)

mysql延时使用:《通过BENCHMARK函数延迟爆路径

盲注的利用关键是要找到一个二值逻辑的判断,即需要对不同的输入有不同的返回结果,我们才能借助推理得到一些信息,但是有时候,盲注入得到的结果并不会在UI上显示出来,这样就回导致我们注入失败,但是采用时间延迟的思想就可以很好的避免这个问题,从而能够对不同的程序具有很好的适应性。

(小编插句话:其实延时盲注的成本很高,需要很好的带宽并且需要测试人员有极好的耐心,试想测一个32位的密码,一个延时10S,这是要测试到天荒地老的节奏啊!)

1.       注入点探测

得到WVS的扫描结果后,我们需要对可能存在注入的URL进行注意排查,以确定是否真的存在注入漏洞。

我们选取:

 

这是dedecms的一个留言板的脚本页面:

4

使用sqlmap对疑似注入点进行探测:

5

扫描的结果没有成功,又手工尝试了union selct和order by1,2,3..等注入方式,貌似不能获得盲注入、的效果。

不成功的原因有很多,我自己根据经验总结了几点:

触发实际的sql注入漏洞之前要

(小编插句话:这里其实可以利用WVS中HTTP EDITOR的功能将HTTP数据包复制出来,使用sqlmap -r 选项直接测试post的数据包,再将–level 设置成2来测试COOKIE变量,另外测试数据是可以通过sqlmap的设置进行自动编码的,这样就免除了上面说到的几种情况。)

这些先验条件有时候就会称为漏洞触发和利用的关键。

这个时候用自动化工具进行测试的工作基本做完了,我们接下来要使用RIPS来对源代码进行白盒分析,因为目标系统是开源的cms系统,我们可以很容易的从网上下载到全部源代码。

使用RIPS对cms的整站源代码进行扫描

6

RIPS扫描出了很多文件,有些是因为交叉引用,有些是真正存在漏洞的代码的。

我们来到:

 

 

 

可以看到,代码在编写的时候,并没有对orderby这个参数进行过滤。导致了注入和畸形数据报错,接下来,我们的任务就是要利用这个漏洞进行有效的注入,获得数据。

我们手工构造一个SQL注入:

对应的sql语句:

这样不能成功,因为sql语句的语法是这样的:

而我们在能控制的参数是order by参数,在where后面,我发现这个时候不管and逻辑的true or false都不影响sql的查询结果。

转换一下思路:

对应的sql语句:

这个语句貌似可以利用,因为在标准的sql语法中。在order by后面再加and是没有用的。但是这里用了逗,也就是if后面的语句也属于order by的一部分了。再在最后加上一个asc,盲注入就成功了。

7

8

 

在+asc后面加上–注释号,来屏蔽掉后面的desc limit
0,5,整个语句就能跑通了。根据返回的结果的不一致,利用正则判断一下,就可以利用盲注入进行帐号和密码的猜测。从而获得后台权限。然后dede的密码存放机制是产生32位的MD5后,截断前24位,所以得到的hash只有24位,没法用cmd5.com直接破解。698d51a19d8a121ce581499d,去掉前8位9d8a121ce581499d转换成16位MD5,再用cmd5.com来解密,成功。

9

总结:

Web渗透和代码审计的第一步是对网站的fuzz测试,这可以从整体上对网站的漏洞情况进行扫描,缩小范围。

对漏洞的具体挖掘和利用还是要使用白盒分析,即源代码分析,这样才能更有效的针对不同的代码情况指定出漏洞利用方案。

介绍一些web fuzzing的工具:

小编语:作者要说的是对于一个php的web应用的盲测和代码审计,不过具体代码审计的部分并没有提及太多。其实盲测就相当于web的fuzz,本文作者说到的方法对于一些小的开源程序还是有用的,而一些成熟的cms,发开公司本身在发布之前一定是经过内部的测试工具扫描的,这样想要挖掘到漏洞,更多的是需要像RIPS这样的代码审计工具去辅助。开源的程序看代码是必须的,而漏洞的挖掘简而言之就是对代码的认知度问题,越熟悉这门语言越能发掘出它存在的问题。其实代码审计并没有那么困难,在掌握基本方法后,拼的其实是审计人员的体力,面对大量的代码逻辑看的眼晕哦!

另外对于PHP代码审计来说,通晓漏洞成因是必不可少的部分,

这里推荐当初黑哥写的php代码审计文章:《高级PHP应用程序漏洞审核技术》(相当具有参考价值)

日币奖励:

本文为转载文,根据本站积分规则给予日币奖励共1枚。

AD:本站开放投稿及积分(日币),日币可兑换实物奖励,每月top3可获得礼品一份。

[via@freebuf]