WEB应用程序漏洞查找基本上是围绕两个元素展开:变量与函数。也就是说一漏洞的利用必须把你提交的恶意代码通过变量经过n次变量转换传递,最终传递给目 标函数执行,还记得MS那句经典的名言吗?“一切输入都是有害的”。这句话只强调了变量输入,很多程序员把“输入”理解为只是 gpc[$_GET,$_POST,$_COOKIE],但是变量在传递过程产生了n多的变化。导致很多过滤只是个“纸老虎”!我们换句话来描叙下代码安 全:“一切进入函数的变量
PHP代码审计技术用的最多也是目前的主力方法:静态分析,主要也是通过查找容易导致安全漏洞的危险函数,常用的如grep,findstr等搜索工具, 很多自动化工具也是使用正则来搜索这些函数。下面列举一些常用的函数,也就是下文说的字典(暂略)。但是目前基本已有的字典很难找到漏洞,所以我们需要扩 展我们的字典,这些字典也是本文主要探讨的。
其他的方法有:通过修改PHP源代码来分析变量流程,或者hook危险的函数来实现对应用程序代码的审核,但是这些也依靠了我们上面提到的字典。
下面将详细介绍一些非传统PHP应用代码审计一些漏洞类型和利用技巧。
1,变量本身的key
说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值,但是忘记了有的程序把变量本身的key也当变量提取给函数处理。
上面的代码就提取了变量本身的key显示出来,单纯对于上面的代码,如果我们提交URL:"key.php?<script>alert(1);</script>=1&bbb=2
"那么就导致一个xss的漏洞,扩展一下如果这个key提交给include()等函数或者sql查询呢?:)
2.变量覆盖(variable-overwrite)
很多的漏洞查找者都知道extract()这个函数在指定参数为EXTR_OVERWRITE或者没有指定函数可以导致变量覆盖,但是还有很多其他情况导致变量覆盖的如:
2.1 遍历初始化变量
请看如下代码
很多的WEB应用都使用上面的方式(注意循环不一定是foreach),如Discuz!4.1的WAP部分
的代码:
2.2 parse_str()变量覆盖漏洞(CVE-2007-3205)、mb_parse_str()
该函数一样可以覆盖数组变量,上面的代码是通过$_SERVER['QUERY_STRING']来提取变量的,对于指定了变量名的我们可以通过注射“=”来实现覆盖其他的变量:
上面的代码通过提交$var来实现对$var1的覆盖。
2.3 import_request_variables()变量覆盖漏洞(CVE-2007-1396)
2.4 PHP5 Globals
从严格意义上来说这个不可以算是PHP的漏洞,只能算是一个特性,测试代码:
但是很多的程序没有考虑到这点,请看如下代码:
如果熟悉WEB2.0的攻击的同学,很容易想到上面的代码我们可以利用这个特性进行crsf攻击。
3 magic_quotes_gpc与代码安全
当打开时,所有的 '(单引号),"(双引号),/(反斜线)和 NULL 字符都会被自动加上一个
反斜线进行转义。还有很多函数有类似的作用 如:addslashes()、mysql_escape_string()、
mysql_real_escape_string()等,另外还有parse_str()后的变量也受magic_quotes_gpc的影
响。目前大多数的主机都打开了这个选项,并且很多程序员也注意使用上面那些函数去过滤
变量,这看上去很安全。很多漏洞查找者或者工具遇到些函数过滤后的变量直接就放弃,但是
就在他们放弃的同时也放过很多致命的安全漏洞。
3.1 哪些地方没有魔术引号的保护
$_SERVER变量。PHP5的$_SERVER变量缺少magic_quotes_gpc的保护,导致近年来X-Forwarded-For的漏洞
猛暴,所以很多程序员考虑过滤X-Forwarded-For,但是其他的变量呢?
3.2 getenv()得到的变量(使用类似$_SERVER变量)
3.3 $HTTP_RAW_POST_DATA与PHP输入、输出流
主要应用与soap/xmlrpc/webpublish功能里,请看如下代码:
3.4 数据库操作容易忘记'的地方如:in()/limit/order by/group by
如Discuz!<5.0的pm.php:
4 变量的编码与解码
一个WEB程序很多功能的实现都需要变量的编码解码,而且就在这一转一解的传递过程中
就悄悄的绕过你的过滤的安全防线。
这个类型的主要函数有
1) stripslashes() 这个其实就是一个decode-addslashes()
2) 其他字符串转换函数:
base64_decode -- 对使用 MIME base64 编码的数据进行解码
base64_encode -- 使用 MIME base64 对数据进行编码
rawurldecode -- 对已编码的 URL 字符串进行解码
rawurlencode -- 按照 RFC 1738 对 URL 进行编码
urldecode -- 解码已编码的 URL 字符串
urlencode -- 编码 URL 字符串
......
(另外一个 unserialize/serialize)
3) 字符集函数(GKB,UTF7/8...)如iconv()/mb_convert_encoding()等
$sql = "SELECT * FROM article WHERE articleid='".urldecode($_GET[id])."'";
当magic_quotes_gpc=on时,我们提交?id=%2527,得到sql语句为:
SELECT * FROM article WHERE articleid='''
5 二次攻击
1) 数据库出来的变量没有进行过滤
2) 数据库的转义符号:
* mysql/oracle转义符号同样是/(我们提交'通过魔术引号变化为/',当我们update进入数
据库时,通过转义变为')
* mssql的转义字符为'(所以我们提交'通过魔术引号变化为/',mssql会把它当为一个字符
串直接处理,所以魔术引号对于mssql的注射没有任何意义)
从这里我们可以思考得到一个结论:一切进入函数的变量都是有害的,另外利用二次攻击
我们可以实现一个webrootkit,把我们的恶意构造直接放到数据库里。我们应当把这样的代
码看成一个vul?
6 魔术引号带来的新的安全问题
首先我们看下魔术引号的处理机制:
[/-->//,'-->/',"-->/",null-->/0]
这给我们引进了一个非常有用的符号“/”,“/”符号不仅仅是转义符号,在WIN系统下也是
目录转跳的符号。这个特点可能导致php应用程序里产生非常有意思的漏洞:
1) 得到原字符(',/,",null])
2) 得到“/”字符
提交内容:
?order_sn='&order_tn=%20and%201=1/*
7 变量key与魔术引号
我们最在这一节的开头就提到了变量key,PHP的魔术引号对它有什么影响呢?
1) 当magic_quotes_gpc = On时,在php5.24下测试显示:
aaaa/'aaa
bb/'b
从上面结果可以看出来,在设置了magic_quotes_gpc = On下,变量key受魔术引号影响。
但是在php4和php<5.2.1的版本中,不处理数组第一维变量的key,测试代码如下:
结果显示:
Array ( [aaaa'aaa] => Array ( [bb/'] => 1 ) )
数组第一维变量的key不受魔术引号的影响。