高级PHP应用程序漏洞审核技术(2) - 超全局变量

五、扩展我们的字典

下面将详细介绍一些非传统PHP应用代码审计一些漏洞类型和利用技巧。

5.1 变量本身的key

    说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值,但是忘记了有的
程序把变量本身的key也当变量提取给函数处理。

--code-------------------------------------------------------------------------
<?php
//key.php?aaaa'aaa=1&bb'b=2
//print_R($_GET);
foreach ($_GET AS $key => $value)
{
print $key."\n";
}
?>
-------------------------------------------------------------------------------

    上面的代码就提取了变量本身的key显示出来,单纯对于上面的代码,如果我们提交URL:

--code-------------------------------------------------------------------------
key.php?<script>alert(1);</script>=1&bbb=2
-------------------------------------------------------------------------------

    那么就导致一个xss的漏洞,扩展一下如果这个key提交给include()等函数或者sql查询
呢?:)

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求:无
系统要求:无
审计策略:通读代码
+++++++++++++++++++++++++


5.2 变量覆盖(variable-overwrite)

    很多的漏洞查找者都知道extract()这个函数在指定参数为EXTR_OVERWRITE或者没有指
定函数可以导致变量覆盖,但是还有很多其他情况导致变量覆盖的如:

5.2.1 遍历初始化变量

请看如下代码:

--code-------------------------------------------------------------------------
<?php
//var.php?a=fuck
$a='hi';
foreach($_GET as $key => $value) {
$$key = $value;
}
print $a;
?>
-------------------------------------------------------------------------------

    很多的WEB应用都使用上面的方式(注意循环不一定是foreach),如Discuz!4.1的WAP部分
的代码:

--code-------------------------------------------------------------------------
$chs = '';
if($_POST && $charset != 'utf-8') {
$chs = new Chinese('UTF-8', $charset);
foreach($_POST as $key => $value) {
$$key = $chs->Convert($value);
}
unset($chs);
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求:无
系统要求:无
审计策略:通读代码
+++++++++++++++++++++++++


5.2.2 parse_str()变量覆盖漏洞(CVE-2007-3205)、mb_parse_str()

--code-------------------------------------------------------------------------
//var.php?var=new
$var = 'init';                    
parse_str($_SERVER['QUERY_STRING']);
print $var;
-------------------------------------------------------------------------------

    该函数一样可以覆盖数组变量,上面的代码是通过$_SERVER['QUERY_STRING']来提取变
量的,对于指定了变量名的我们可以通过注射“=”来实现覆盖其他的变量:

--code-------------------------------------------------------------------------
//var.php?var=1&a[1]=var1%3d222
$var1 = 'init';
parse_str($a[$_GET['var']]);
print $var1;
-------------------------------------------------------------------------------

上面的代码通过提交$var来实现对$var1的覆盖。

+++++++++++++++++++++++++
漏洞审计策略(parse_str)
-------------------------
PHP版本要求:无
系统要求:无
审计策略:查找字符parse_str
+++++++++++++++++++++++++

+++++++++++++++++++++++++
漏洞审计策略(mb_parse_str)
-------------------------
PHP版本要求:php4<4.4.7 php5<5.2.2
系统要求:无
审计策略:查找字符mb_parse_str
+++++++++++++++++++++++++


5.2.3 import_request_variables()变量覆盖漏洞(CVE-2007-1396)

--code-------------------------------------------------------------------------
//var.php?_SERVER[REMOTE_ADDR]=10.1.1.1
echo 'GLOBALS '.(int)ini_get("register_globals")."n";
import_request_variables('GPC');
if ($_SERVER['REMOTE_ADDR'] != '10.1.1.1') die('Go away!');
echo 'Hello admin!';
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略(import_request_variables)
-------------------------
PHP版本要求:php4<4.4.1 php5<5.2.2
系统要求:无
审计策略:查找字符import_request_variables
+++++++++++++++++++++++++


5.2.4 PHP5 Globals

    从严格意义上来说这个不可以算是PHP的漏洞,只能算是一个特性,测试代码:

--code-------------------------------------------------------------------------
<?
// register_globals =ON
//foo.php?GLOBALS[foobar]=HELLO
php echo $foobar;
?>
-------------------------------------------------------------------------------

    但是很多的程序没有考虑到这点,请看如下代码:

--code-------------------------------------------------------------------------
//为了安全取消全局变量
//var.php?GLOBALS[a]=aaaa&b=111
if (ini_get('register_globals')) foreach($_REQUEST as $k=>$v) unset(${$k});
print $a;
print $_GET[b];
-------------------------------------------------------------------------------

    如果熟悉WEB2.0的攻击的同学,很容易想到上面的代码我们可以利用这个特性进行crsf
攻击。

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求:无
系统要求:无
审计策略:通读代码
+++++++++++++++++++++++++


5.3 magic_quotes_gpc与代码安全

5.3.1 什么是magic_quotes_gpc

    当打开时,所有的 '(单引号),"(双引号),\(反斜线)和 NULL 字符都会被自动加上一个
反斜线进行转义。还有很多函数有类似的作用 如:addslashes()、mysql_escape_string()、
mysql_real_escape_string()等,另外还有parse_str()后的变量也受magic_quotes_gpc的影
响。目前大多数的主机都打开了这个选项,并且很多程序员也注意使用上面那些函数去过滤
变量,这看上去很安全。很多漏洞查找者或者工具遇到些函数过滤后的变量直接就放弃,但是
就在他们放弃的同时也放过很多致命的安全漏洞。 :)

5.3.2 哪些地方没有魔术引号的保护
   
1) $_SERVER变量

    PHP5的$_SERVER变量缺少magic_quotes_gpc的保护,导致近年来X-Forwarded-For的漏洞
猛暴,所以很多程序员考虑过滤X-Forwarded-For,但是其他的变量呢?

+++++++++++++++++++++++++
漏洞审计策略($_SERVER变量)
-------------------------
PHP版本要求:无
系统要求:无
审计策略:查找字符_SERVER
+++++++++++++++++++++++++


2) getenv()得到的变量(使用类似$_SERVER变量)
  
+++++++++++++++++++++++++
漏洞审计策略(getenv())
-------------------------
PHP版本要求:无
系统要求:无
审计策略:查找字符getenv
+++++++++++++++++++++++++


3) $HTTP_RAW_POST_DATA与PHP输入、输出流

    主要应用与soap/xmlrpc/webpublish功能里,请看如下代码:

--code-------------------------------------------------------------------------
if ( !isset( $HTTP_RAW_POST_DATA ) ) {
$HTTP_RAW_POST_DATA = file_get_contents( 'php://input' );
}
if ( isset($HTTP_RAW_POST_DATA) )
$HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);
-------------------------------------------------------------------------------
       
+++++++++++++++++++++++++
漏洞审计策略(数据流)
-------------------------
PHP版本要求:无
系统要求:无
审计策略:查找字符HTTP_RAW_POST_DATA或者php://input
+++++++++++++++++++++++++


4) 数据库操作容易忘记'的地方如:in()/limit/order by/group by
    
    如Discuz!<5.0的pm.php:
    
--code-------------------------------------------------------------------------
if(is_array($msgtobuddys)) {
$msgto = array_merge($msgtobuddys, array($msgtoid));
......
foreach($msgto as $uid) {
$uids .= $comma.$uid;
$comma = ',';
}
......
$query = $db->query("SELECT m.username, mf.ignorepm FROM {$tablepre}members m
LEFT JOIN {$tablepre}memberfields mf USING(uid)
WHERE m.uid IN ($uids)");
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求:无
系统要求:无
审计策略:查找数据库操作字符(select,update,insert等等)
+++++++++++++++++++++++++

Pader 2009-8-21 0

高级PHP应用程序漏洞审核技术(1) - 前言

一、前言

    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,使用比例大致如下:

php4 68%
2000-2007,No security fixes after 2008/08,最终版本是php4.4.9

php5 32%
2004-present,Now at version 5.2.6(PHP 5.3 alpha1 released!)

php6
目前还在测试阶段,变化很多做了大量的修改,取消了很多安全选项如magic_quotes_gpc。
(这个不是今天讨论的范围)

    由于php缺少自动升级的机制,导致目前PHP版本并存,也导致很多存在漏洞没有被修补。
这些有漏洞的函数也是我们进行WEB应用程序代码审计的重点对象,也是我们字典重要来源。


四、其他的因素与应用代码审计

    很多代码审计者拿到代码就看,他们忽视了“安全是一个整体”,代码安全很多的其他因素
有关系,比如上面我们谈到的PHP版本的问题,比较重要的还有操作系统类型(主要是两大阵营
win/*nix),WEB服务端软件(主要是iis/apache两大类型)等因素。这是由于不同的系统不同
的WEB SERVER有着不同的安全特点或特性,下文有些部分会涉及。

    所以我们在做某个公司WEB应用代码审计时,应该了解他们使用的系统,WEB服务端软件,
PHP版本等信息。

Pader 2009-8-21 0

男女间喜欢和爱的区别

也许你们并不是很明白喜欢和爱是不一样的呢?喜欢和爱是不同的,有区别的……
  喜欢是在深夜看书时突然想起他,想象他现在做什么,心里漾起一阵轻飘飘的温暖,却从不主动给他打电话。几分钟后,注意力又重新被书中的情节吸引。
  爱是在寂寞的夜里,思念如潮水般涌来,手里捧着书却怎么也看不进去,心里惦记着他此时是否还在加班,吃没吃晚饭,是不是如自己想着他一般想着自己。
  喜欢是和他讨论问题争的面红耳赤,各不相让,在他面前像个刺猬一样从不认输,但在心里却早已暗暗佩服他的见地他的才华。
  爱是希望他和自己步调一致,和自己心灵相通,他无心说的一句玩笑话也能让自己顷刻情绪低落甚至眼泪汪汪。在他面前,自己是从不设防的。
  喜欢是出门在外给他发个短信,告诉他这边的天气很好,然后把手机关掉,独自在异地疯玩一个星期,晒成一个黑人后突然出现在他面前吓他一跳。
  爱是无论到哪都希望有他陪伴。可以站在海边给他打手机,让他听听海浪的声音;也可以因为在异乡的街道上看到一个酷似他的背影而愣在原地久久不动。
  喜欢是他出差前简单的道一声“一路平安”,看着他离去的背影,心中有一点不舍,却什么也不说,只是默默等待他归来的消息。
  爱是他临出差前千叮咛万嘱咐,往他的背包里塞满衣服和食物,在车站要等到火车开走才肯离开。并且在他走后的日子里天天心神不定,一遍遍的祈祷他能够平安归来。
  喜欢是在受伤的时候,不想让他看到自己脆弱的一面,在他面前把眼泪悄悄抹掉,转过头依然是一副快乐坚强的模样。
  爱是在受委屈的时候,爬在他的胸前痛哭,没有伪装没有顾虑,把所有的烦恼统统告诉他,并渴望从他的怀抱中得到安慰。
  喜欢是和他周末逛街逛累了一起吃肯德基;是在寒冷的冬天和他抢一杯热咖啡;是和他并肩走在街上中间始终隔着半米的距离;是陪他一起在电脑前打游戏两个人笑的像个孩子。
  爱是周末利用半天时间亲手做出几道好菜满足的看他吃下去;是在寒冷的冬天不断为他的咖啡杯里续上热水;是和他走在街上任由他紧紧挽着自己的手;是在他旁边安静着做着,幸福地看着他在电脑前工作时专心的样子。
  喜欢是听他讲自己童年的趣事,然后哈哈大笑,心中涌起一阵莫名的感动。
  爱是听他将自己童年的趣事,然后微微一笑,心中更加怜惜眼前这个曾经如此调皮捣蛋的男人。
  喜欢是在楼道里碰上他,愉快的和他打声招呼,再简单寒暄几句,擦肩而过的时候看见了窗外明媚的阳光,心情无端好了起来。
  爱是在楼道了看见他,脸上装出一副毫不在乎的表情,但在擦肩而过时细心感受身边颤动的空气,于是忍不住回头望一眼。
  喜欢是看到他和另一个女孩牵手走过,心里有一点点疼,但很快会冲着朝阳重新扬起笑脸。
  爱是输不起的游戏,付出全部后,留下的可能仅仅是刻在心底的一道伤痕。
  喜欢一个人是想要他是自己的,所以,可以喜欢很多人,想要很多人都是自己的。
  爱是明明离不开他,却要不得不放弃他,因为他要的幸福,也许我给不了。不敢霸占他,希望看他找到幸福,即使那份幸福不是跟我分享的。
  喜欢是,希望寂寞的时候,无聊的时候,伤感的时候,找个人说说话。
  爱是,在任何时候都想跟他分享,快乐的时候甚至希望把所有快乐都给了他。是他在的时候,眼睛里只有他一人;他不在的时候,一切都带有他的影子。

Pader 2009-8-21 0

交警在堵车上发挥的效率还是不错滴

今天早上睡的非常迟,醒来的时候都8:57了,于是下午下班回来的时候就得坐车了,结果在一个十字路口,..哦不对, 是丁字路口堵了N长时间,红绿灯出毛病了,哎,现在啊,红绿灯一出问题就得大大的乱,在车上等的急死人了,只见这车子开两步停个十分钟,等了老半天,终于来了两个交警,哇,这交警的作用非常大呀,只见交警一来,那车子就哗哗的过去,说实话,平时没见这么多车,今天一堵车,这条路上车就N多,哗哗的老半天还有那么密的车哗哗的,不过也没多长时间,路就通畅啦,交警叔叔的作用真的不可小视,那效率,哗哗的

Pader 2009-8-20 0

form.reset() 失效,对象不支持此属性或方法的原因

今天在做一个 ajax 的 form 的时候,在提交完执行 reset() 函数重置该表单,结果浏览器总是提示对象不支持此属性或方法,我使用 document.forms['form1'].reset(); 和 document.getElementById('form1').reset(); 都不行,查了 id 和 name 都是对的,哎,废话不多说了,后来我把表单独立拿出来试终于找到原来在 form1 里我给一个重置按钮设置了 id="reset" 导致和 reset() 冲突,于是去掉这个 id 就OK了,OK,Thank you!

Pader 2009-8-19 0