前言PHP是一种被广泛使用的脚本语言,尤其适合于web开发。具有跨平台,容易学习,功能强大等特点,据统计全世界有超过34%的网站有php的应用,包括Yahoo、sina、163、sohu等大型门户网站。而且很多具名的web应用系统(包括bbs,blog,wiki,cms等等)都是使用php开发的,Discuz、phpwind、phpbb、vbb、wordpress、boblog等等。随着web安全的热点升级,php应用程序的代码安全问题也逐步兴盛起来,越来越多的安全人员投入到这个领域,越来越多的应用程序代码漏洞被披露。针对这样一个状况,很多应用程序的官方都成立了安全部门,或者雇佣安全人员进行代码审计,因此出现了很多自动化商业化的代码审计工具。也就是这样的形势导致了一个局面:大公司的产品安全系数大大的提高,那些很明显的漏洞基本灭绝了,那些大家都知道的审计技术都无用武之地了。我们面对很多工具以及大牛扫描过n遍的代码,有很多的安全人员有点悲观,而有的官方安全人员也非常的放心自己的代码,但是不要忘记了“没有绝对的安全”,我们应该去寻找新的途径挖掘新的漏洞。本文就给介绍了一些非传统的技术经验和大家分享。 另外在这里特别说明一下本文里面很多漏洞都是来源于网络上牛人和朋友们的分享,在这里需要感谢他们 :) 传统的代码审计技术WEB应用程序漏洞查找基本上是围绕两个元素展开:变量与函数。也就是说一漏洞的利用必须把你提交的恶意代码通过变量经过n次变量转换传递,最终传递给目标函数执行,还记得MS那句经典的名言吗?“一切输入都是有害的”。这句话只强调了变量输入,很多程序员把“输入”理解为只是gpc[$_GET,$_POST,$_COOKIE],但是变量在传递过程产生了n多的变化。导致很多过滤只是个“纸老虎”!我们换句话来描叙下代码安全:“一切进入函数的变量是有害的”。 PHP代码审计技术用的最多也是目前的主力方法:静态分析,主要也是通过查找容易导致安全漏洞的危险函数,常用的如grep,findstr等搜索工具,很多自动化工具也是使用正则来搜索这些函数。下面列举一些常用的函数,也就是下文说的字典(暂略)。但是目前基本已有的字典很难找到漏洞,所以我们需要扩展我们的字典,这些字典也是本文主要探讨的。 其他的方法有:通过修改PHP源代码来分析变量流程,或者hook危险的函数来实现对应用程序代码的审核,但是这些也依靠了我们上面提到的字典。 PHP版本与应用代码审计到目前为止,PHP主要有3个版本:php4、php5、php6,使用比例大致如下:
由于php缺少自动升级的机制,导致目前PHP版本并存,也导致很多存在漏洞没有被修补。这些有漏洞的函数也是我们进行WEB应用程序代码审计的重点对象,也是我们字典重要来源。 其他的因素与应用代码审计很多代码审计者拿到代码就看,他们忽视了“安全是一个整体”,代码安全很多的其他因素有关系,比如上面我们谈到的PHP版本的问题,比较重要的还有操作系统类型(主要是两大阵营win/*nix),WEB服务端软件(主要是iis/apache两大类型)等因素。这是由于不同的系统不同的WEB SERVER有着不同的安全特点或特性,下文有些部分会涉及。 所以我们在做某个公司WEB应用代码审计时,应该了解他们使用的系统,WEB服务端软件,PHP版本等信息。 扩展我们的字典下面将详细介绍一些非传统PHP应用代码审计一些漏洞类型和利用技巧。 变量本身的key说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值,但是忘记了有的程序把变量本身的key也当变量提取给函数处理。 <?php 上面的代码就提取了变量本身的key显示出来,单纯对于上面的代码,如果我们提交URL: key.php?<script>alert(1);</script>=1&bbb=2 那么就导致一个xss的漏洞,扩展一下如果这个key提交给include()等函数或者sql查询呢?:)
变量覆盖很多的漏洞查找者都知道extract()这个函数在指定参数为EXTR_OVERWRITE或者没有指定函数可以导致变量覆盖,但是还有很多其他情况导致变量覆盖的如: 遍历初始化变量请看如下代码: <?php 很多的WEB应用都使用上面的方式(注意循环不一定是foreach),如Discuz!4.1的WAP部分的代码: $chs ='';
parse_str()变量覆盖漏洞//var.php?var=new 该函数一样可以覆盖数组变量,上面的代码是通过$_SERVER['QUERY_STRING']来提取变量的,对于指定了变量名的我们可以通过注射“=”来实现覆盖其他的变量: //var.php?var=1&a[1]=var1%3d222 上面的代码通过提交$var来实现对$var1的覆盖。
import_request_variables()变量覆盖漏洞//var.php?_SERVER[REMOTE_ADDR]=10.1.1.1
PHP5 Globals从严格意义上来说这个不可以算是PHP的漏洞,只能算是一个特性,测试代码: <? 但是很多的程序没有考虑到这点,请看如下代码: //为了安全取消全局变量 如果熟悉WEB2.0的攻击的同学,很容易想到上面的代码我们可以利用这个特性进行crsf攻击。
magic_quotes_gpc与代码安全什么是magic_quotes_gpc当打开时,所有的 '(单引号),"(双引号),\(反斜线)和 NULL 字符都会被自动加上一个反斜线进行转义。还有很多函数有类似的作用 如:addslashes()、mysql_escape_string()、mysql_real_escape_string()等,另外还有parse_str()后的变量也受magic_quotes_gpc的影响。目前大多数的主机都打开了这个选项,并且很多程序员也注意使用上面那些函数去过滤变量,这看上去很安全。很多漏洞查找者或者工具遇到些函数过滤后的变量直接就放弃,但是就在他们放弃的同时也放过很多致命的安全漏洞。 :) 哪些地方没有魔术引号的保护1) $_SERVER变量 PHP5的$_SERVER变量缺少magic_quotes_gpc的保护,导致近年来X-Forwarded-For的漏洞猛暴,所以很多程序员考虑过滤X-Forwarded-For,但是其他的变量呢?
2) getenv()得到的变量(使用类似$_SERVER变量)
3) $HTTP_RAW_POST_DATA与PHP输入、输出流 主要应用与soap/xmlrpc/webpublish功能里,请看如下代码: if(!isset( $HTTP_RAW_POST_DATA )){
4) 数据库操作容易忘记'的地方如:in()/limit/order by/group by 如Discuz!<5.0的pm.php: if(is_array($msgtobuddys)){
变量的编码与解码一个WEB程序很多功能的实现都需要变量的编码解码,而且就在这一转一解的传递过程中就悄悄的绕过你的过滤的安全防线。 这个类型的主要函数有: 1) stripslashes() 这个其实就是一个decode-addslashes() 2) 其他字符串转换函数:
另外一个 unserialize/serialize 3) 字符集函数(GKB,UTF7/8...)如iconv()/mb_convert_encoding()等 目前很多漏洞挖掘者开始注意这一类型的漏洞了,如典型的urldecode: $sql ="SELECT * FROM article WHERE articleid='".urldecode($_GET[id])."'"; 当magic_quotes_gpc=on时,我们提交?id=%2527,得到sql语句为: SELECT * FROM article WHERE articleid='''
二次攻击详细见附录[1] 1)数据库出来的变量没有进行过滤 2)数据库的转义符号:
从这里我们可以思考得到一个结论:一切进入函数的变量都是有害的,另外利用二次攻击我们可以实现一个webrootkit,把我们的恶意构造直接放到数据库里。我们应当把这样的代码看成一个vul?
魔术引号带来的新的安全问题首先我们看下魔术引号的处理机制: [\-->\\,'-->\',"-->\",null-->\0] 这给我们引进了一个非常有用的符号“\”,“\”符号不仅仅是转义符号,在WIN系统下也是目录转跳的符号。这个特点可能导致php应用程序里产生非常有意思的漏洞: 1)得到原字符(',\,",null]) $order_sn=substr($_GET['order_sn'],1); 2)得到“\”字符 $order_sn=substr($_GET['order_sn'],0,1); 提交内容: ?order_sn='&order_tn=%20and%201=1/* 执行的SQL语句为: SELECT order_id, order_status, shipping_status, pay_status, shipping_time,
变量key与魔术引号我们最在这一节的开头就提到了变量key,PHP的魔术引号对它有什么影响呢? <?php 1)当magic_quotes_gpc = On时,在php5.24下测试显示: aaaa\'aaa 从上面结果可以看出来,在设置了magic_quotes_gpc = On下,变量key受魔术引号影响。但是在php4和php<5.2.1的版本中,不处理数组第一维变量的key,测试代码如下: <?php 结果显示: Array([aaaa'aaa] => Array ( [bb\'] => 1 ) ) 数组第一维变量的key不受魔术引号的影响。
2)当magic_quotes_gpc = Off时,在php5.24下测试显示: aaaa'aaa 对于magic_quotes_gpc = Off时所有的变量都是不安全的,考虑到这个,很多程序都通过addslashes等函数来实现魔术引号对变量的过滤,示例代码如下: <?php 以上的代码看上去很完美,但是他这个代码里addslashes($value)只处理了变量的具体的值,但是没有处理变量本身的key,上面的代码显示结果如下: Array
代码注射PHP中可能导致代码注射的函数很多人都知道eval、preg_replace+/e可以执行代码,但是不知道php还有很多的函数可以执行代码如:
这里我们看看最近出现的几个关于create_function()代码执行漏洞的代码: <?php
变量函数与双引号对于单引号和双引号的区别,很多程序员深有体会,示例代码: echo "$a\n"; 我们再看如下代码: //how to exp this code 另外很多的应用程序都把变量用""存放在缓存文件或者config或者data文件里,这样很容易被人注射变量函数。
PHP自身函数漏洞及缺陷PHP函数的溢出漏洞大家还记得Stefan Esser大牛的Month of PHP Bugs(MOPB见附录2)项目么,其中比较有名的要算是unserialize(),代码如下: unserialize(stripslashes($HTTP_COOKIE_VARS[$cookiename .'_data']); 在以往的PHP版本里,很多函数都曾经出现过溢出漏洞,所以我们在审计应用程序漏洞的时候不要忘记了测试目标使用的PHP版本信息。
PHP函数的其他漏洞Stefan Esser大牛发现的漏洞:unset()--Zend_Hash_Del_Key_Or_Index Vulnerability 比如phpwind早期的serarch.php里的代码: unset($uids);
session_destroy()删除文件漏洞测试PHP版本:5.1.2 这个漏洞是几年前朋友saiy发现的,session_destroy()函数的功能是删除session文件,很多web应用程序的logout的功能都直接调用这个函数删除session,但是这个函数在一些老的版本中缺少过滤导致可以删除任意文件。测试代码如下: <?php 当我们提交构造cookie:PHPSESSID=/../1.php,相当于unlink('sess_/../1.php')这样就通过注射../转跳目录删除任意文件了。很多著名的程序某些版本都受影响如phpmyadmin,sablog,phpwind3等等。
随机函数1) rand() VS mt_rand() <?php 可以看出rand()最大的随机数是32767,这个很容易被我们暴力破解。 <?php 当我们的程序使用rand处理session时,攻击者很容易暴力破解出你的session,但是对于mt_rand是很难单纯的暴力的。
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||