高级PHP应用程序漏洞审核技术(3) - 变量的编码与解码和引用

5.3.3 变量的编码与解码

    一个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()等
     
    目前很多漏洞挖掘者开始注意这一类型的漏洞了,如典型的urldecode:

--code-------------------------------------------------------------------------
$sql = "SELECT * FROM article WHERE articleid='".urldecode($_GET[id])."'";
-------------------------------------------------------------------------------

    当magic_quotes_gpc=on时,我们提交?id=%2527,得到sql语句为:

--code-------------------------------------------------------------------------
SELECT * FROM article WHERE articleid='''
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求:无
系统要求:无
审计策略:查找对应的编码函数
+++++++++++++++++++++++++


5.3.4 二次攻击(详细见附录[1])

1) 数据库出来的变量没有进行过滤

2) 数据库的转义符号:

  * mysql/oracle转义符号同样是\(我们提交'通过魔术引号变化为\',当我们update进入数
据库时,通过转义变为')

  * mssql的转义字符为'(所以我们提交'通过魔术引号变化为\',mssql会把它当为一个字符
串直接处理,所以魔术引号对于mssql的注射没有任何意义)
   
    从这里我们可以思考得到一个结论:一切进入函数的变量都是有害的,另外利用二次攻击
我们可以实现一个webrootkit,把我们的恶意构造直接放到数据库里。我们应当把这样的代
码看成一个vul?

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


5.3.5 魔术引号带来的新的安全问题

    首先我们看下魔术引号的处理机制:

[\-->\\,'-->\',"-->\",null-->\0]

    这给我们引进了一个非常有用的符号“\”,“\”符号不仅仅是转义符号,在WIN系统下也是
目录转跳的符号。这个特点可能导致php应用程序里产生非常有意思的漏洞:

1) 得到原字符(',\,",null])

--code-------------------------------------------------------------------------
$order_sn=substr($_GET['order_sn'], 1);

//提交                 '
//魔术引号处理         \'
//substr               '

$sql = "SELECT order_id, order_status, shipping_status, pay_status, ".
   " shipping_time, shipping_id, invoice_no, user_id ".
   " FROM " . $ecs->table('order_info').
   " WHERE order_sn = '$order_sn' LIMIT 1";
-------------------------------------------------------------------------------

2) 得到“\”字符

--code-------------------------------------------------------------------------
$order_sn=substr($_GET['order_sn'], 0,1);

//提交                 '
//魔术引号处理         \'
//substr               \   

$sql = "SELECT order_id, order_status, shipping_status, pay_status, ".
   " shipping_time, shipping_id, invoice_no, user_id ".
   " FROM " . $ecs->table('order_info').
   " WHERE order_sn = '$order_sn' and order_tn='".$_GET['order_tn']."'";
-------------------------------------------------------------------------------
  
    提交内容:

--code-------------------------------------------------------------------------
?order_sn='&order_tn=%20and%201=1/*
-------------------------------------------------------------------------------

    执行的SQL语句为:

--code-------------------------------------------------------------------------
SELECT order_id, order_status, shipping_status, pay_status, shipping_time,
shipping_id, invoice_no, user_id FROM order_info WHERE order_sn = '\' and
order_tn=' and 1=1/*'
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求:无
系统要求:无
审计策略:查找字符串处理函数如substr或者通读代码
+++++++++++++++++++++++++


5.3.6 变量key与魔术引号
   
    我们最在这一节的开头就提到了变量key,PHP的魔术引号对它有什么影响呢?

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

1) 当magic_quotes_gpc = On时,在php5.24下测试显示:
 
aaaa\'aaa
bb\'b

    从上面结果可以看出来,在设置了magic_quotes_gpc = On下,变量key受魔术引号影响。
但是在php4和php<5.2.1的版本中,不处理数组第一维变量的key,测试代码如下:

--code-------------------------------------------------------------------------
<?php
//key.php?aaaa'aaa[bb']=1
print_R($_GET);
?>
-------------------------------------------------------------------------------

    结果显示:

Array ( [aaaa'aaa] => Array ( [bb\'] => 1 ) )  

    数组第一维变量的key不受魔术引号的影响。

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


2) 当magic_quotes_gpc = Off时,在php5.24下测试显示:

aaaa'aaa
bb'b

    对于magic_quotes_gpc = Off时所有的变量都是不安全的,考虑到这个,很多程序都通过
addslashes等函数来实现魔术引号对变量的过滤,示例代码如下:

--code-------------------------------------------------------------------------
<?php
//keyvul.php?aaa'aa=1'
//magic_quotes_gpc = Off
if (!get_magic_quotes_gpc())
{
$_GET  = addslashes_array($_GET);
}

function addslashes_array($value)
{
        return is_array($value) ? array_map('addslashes_array', $value) : addslashes($value);
}
print_R($_GET);
foreach ($_GET AS $key => $value)
{
print $key;
}
?>
-------------------------------------------------------------------------------

    以上的代码看上去很完美,但是他这个代码里addslashes($value)只处理了变量的具体
的值,但是没有处理变量本身的key,上面的代码显示结果如下:
 
Array
(
    [aaa'aa] => 1\'
)
aaa'aa

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


5.4 代码注射

5.4.1 PHP中可能导致代码注射的函数

    很多人都知道eval、preg_replace+/e可以执行代码,但是不知道php还有很多的函数可
以执行代码如:

assert()
call_user_func()
call_user_func_array()
create_function()
变量函数
...

    这里我们看看最近出现的几个关于create_function()代码执行漏洞的代码:

--code-------------------------------------------------------------------------
<?php
//how to exp this code
$sort_by=$_GET['sort_by'];
$sorter='strnatcasecmp';
$databases=array('test','test');
$sort_function = '  return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);
      ';
usort($databases, create_function('$a, $b', $sort_function));
-------------------------------------------------------------------------------

+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求:无
系统要求:无
审计策略:查找对应函数(assert,call_user_func,call_user_func_array,create_function等)
+++++++++++++++++++++++++


5.4.2 变量函数与双引号
    
    对于单引号和双引号的区别,很多程序员深有体会,示例代码:

--code-------------------------------------------------------------------------
echo "$a\n";
echo '$a\n';
-------------------------------------------------------------------------------

    我们再看如下代码:

--code-------------------------------------------------------------------------
//how to exp this code
if($globals['bbc_email']){

$text = preg_replace(
array("/\[email=(.*?)\](.*?)\[\/email\]/ies",
"/\[email\](.*?)\[\/email\]/ies"),
array('check_email("$1", "$2")',
'check_email("$1", "$1")'), $text);
-------------------------------------------------------------------------------

    另外很多的应用程序都把变量用""存放在缓存文件或者config或者data文件里,这样很
容易被人注射变量函数。
  
+++++++++++++++++++++++++
漏洞审计策略
-------------------------
PHP版本要求:无
系统要求:无
审计策略:通读代码
+++++++++++++++++++++++++