首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>漏洞资料>文章内容
当magic_quotes_gpc=off
来源:http://www.80vul.com 作者:ryat 发布时间:2010-05-17  

当magic_quotes_gpc=off

author: ryat#www.wolvez.org
team:http://www.80vul.com
date:2009-04-10

一、综述

magic_quotes_gpc是php中的一个安全选项,在php manual中对此有如下描述:

When on, all ' (single-quote), " (double quote), \ (backslash) and NULL characters are escaped with a backslash automatically. This is identical to what addslashes() does

虽然magic_quotes_gpc有助于提升程序的安全性并且在php中默认开启,但同时也带来了其他的一些问题,因此在php6中将去掉此选项。


二、当magic_quotes_gpc=off

考虑到部分服务器关闭了magic_quotes_gpc或者其他的一些原因[如影响功能等],很多程序在如magic_quotes_gpc=off下自己实现一个代码来模拟magic_quotes_gpc=on的情况. 如下面的一段代码:

define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
...
foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
 foreach($$_request as $_key => $_value) {
  $_key{0} != '_' && $$_key = daddslashes($_value);
 }
}
...
function daddslashes($string, $force = 0) {
 !defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
 if(!MAGIC_QUOTES_GPC || $force) {
  if(is_array($string)) {
   foreach($string as $key => $val) {
    $string[$key] = daddslashes($val, $force);
   }
  } else {
   $string = addslashes($string);
  }
 }
 return $string;
}

利用addslashes()函数模拟了magic_quotes_gpc=on时的效果,看上去很完美,其实是有缺陷的或者说只是模拟了magic_quotes_gpc的部分功能.

三、magic_quotes_gpc的代码分析

php在注册$_GET/$_POST等超全局变量时magic_quotes_gpc部分的代码:

// php_variables.c
PHPAPI void php_register_variable_safe(char *var, char *strval, int str_len, zval *track_vars_array TSRMLS_DC)
{
// 对变量值的处理
...
 if (PG(magic_quotes_gpc)) {
  Z_STRVAL(new_entry) = php_addslashes(strval, Z_STRLEN(new_entry), &Z_STRLEN(new_entry), 0 TSRMLS_CC);
 } else {
  Z_STRVAL(new_entry) = estrndup(strval, Z_STRLEN(new_entry));
 }
...
PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array TSRMLS_DC)
{
// 对变量名的处理
...
zend_bool is_array = 0;
...
 for (p = var; *p; p++) {
  if (*p == ' ' || *p == '.') {
   *p='_';
  } else if (*p == '[') {
   is_array = 1;
   ip = p;
   *p = 0;
   break;
  }
 }
 var_len = p - var;
// 上面这段代码没有考虑变量名的原始长度,所以这里是not binary safe
// 也就是说,提交 test.php?ryat%00wst=1 将会生成$_GET['ryat']=1
...
 if (is_array) {
// 如果变量名是数组的形式
...
   } else {
// php > 5.2.1
    if (PG(magic_quotes_gpc)) {
// php = 4.x && php <= 5.2.1
// if (PG(magic_quotes_gpc) && (index!=var)) {
     escaped_index = php_addslashes(index, index_len, &index_len, 0 TSRMLS_CC);
    } else {
     escaped_index = index;
    }
...
 } else {
// 这部分的magic_quotes_gpc处理和上面一样
...

由上面的代码可以看到,magic_quotes_gpc=on时不仅仅用addslashes处理了变量值,而且处理了变量名[既$_GET/$_POST等超全局变量的key,另外要注意的是:[1]在php4和php<5.2.1的版本中,不处理第一维的key:)]

而前面那段模拟magic_quotes_gpc的代码仅仅处理了数组的值,因此是存在安全隐患的。

四、实例[ECShop SQL injection 漏洞分析]

文件includes/init.php判断get_magic_quotes_gpc(),如果为off则调用addslashes_deep():

// includes/init.php
if (!get_magic_quotes_gpc())
{
    if (!empty($_GET))
    {
        $_GET  = addslashes_deep($_GET);
    }
    if (!empty($_POST))
    {
        $_POST = addslashes_deep($_POST);
    }

    $_COOKIE   = addslashes_deep($_COOKIE);
    $_REQUEST  = addslashes_deep($_REQUEST);
}

addslashes_deep()在文件includes/lib_base.php里最后通过addslashes()处理

// includes/lib_base.php
function addslashes_deep($value)
{
    if (empty($value))
    {
        return $value;
    }
    else
    {
        return is_array($value) ? array_map('addslashes_deep', $value) : addslashes($value);
    // 只处理了数组的值:)
    }
}

下面看下具体的导致漏洞的代码,文件 pick_out.php里:

// pick_out.php
if (!empty($_GET['attr']))
{
    foreach($_GET['attr'] as $key => $value)
    {
        $key = intval($key);
        $_GET['attr'][$key] = htmlspecialchars($value);
        // foreach处理的是指定数组的拷贝,所以这里的处理并不影响数组原先的key和value
        // 因此可以引入任意的key:)
        // 程序员的逻辑出了问题?
    }
}
...
        foreach ($_GET['attr'] AS $key => $value)
        {
            $attr_url .= '&attr[' . $key . ']=' . $value;

            $attr_picks[] = $key;
            if ($i > 0)
            {
                if (empty($goods_result))
                {
                    break;
                }
                // 利用key进行注射:)
                $goods_result = $db->getCol("SELECT goods_id FROM " . $ecs->table("goods_attr") . " WHERE goods_id IN (" . implode(',' , $goods_result) . ") AND attr_id='$key' AND attr_value='$value'");
               
由于magic_quotes_gpc=off时没有对$key处理,同时在数组赋值时存在逻辑问题,最终导致了注射漏洞:)

EXP:

http://www.80vul.com/exp/ecshop-pch-005.txt

update 2010年5月15日

http://www.80vul.com/exp/ecshop2-pch-005.txt

五、参考:

http://bugs.php.net/bug.php?id=41093


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·XSOK环境变量本地命令执行漏洞
·N点虚拟主机管理系统 致命漏洞。
·南方数据企业网站管理系统V10.0
·动网(DVBBS)Version 8.2.0 后
·Solaris 10 telnet漏洞及解决
·破解无线路由器密码,常见无线密
·Nginx %00空字节执行php漏洞
·WinWebMail、7I24提权漏洞
·XPCD xpcd-svga本地缓冲区溢出漏
·Struts2多个漏洞简要分析
·ecshop2.72 api.php 文件鸡肋注
·Discuz!后台拿Webshell 0day
  相关文章
·关于magic_quotes_sybase
·New Includes Function -- spl_a
·Discuz! 6.x/7.x 全局变量防御绕
·ZIP 文件溢出漏洞
·[CAL-20100204-3]Adobe Shockwav
·[CAL-20100204-2]Adobe Shockwav
·[CAL-20100204-1]Adobe Shockwav
·nginx文件类型错误解析漏洞
·IIS源码泄露及文件类型解析错误
·DEDECMS v5.5 GBK Final 的一个
·Php168一个即将被补的代码执行?
·php168 获取管理员0day
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved