zoukankan      html  css  js  c++  java
  • PHP之is_a()函数执行代码之总结

    今天看到云舒在群里贴的漏洞公告,原始的文章在

    http://www.byte.nl/blog/2011/09/23/security-bug-in-is_a-function-in-php-5-3-7-5-3-8/

    后来查了下PHP官方的手册,这个问题是在PHP 5.3.7中更新了is_a()函数的功能。is_a()经常被用于条件判断。

        在此前版本的is_a() 的第一个参数如果不是object,则会返回false,现在变成了如果不是object ,则会去执行 __autoload()函数。PHP为此还开了一个bug,但对此bug仍然有争议,部分开发人员认为这个功能是正常的。

    Aron Budinszky 07-Sep-2011 11:21

    Be careful! Starting in PHP 5.3.7 the behavior of is_a() has changed slightly: when calling is_a() with a first argument that is not an object, __autoload() is triggered!

    In practice, this means that calling is_a('23', 'User'); will trigger __autoload() on "23". Previously, the above statement simply returned 'false'.

    More info can be found here:
    https://bugs.php.net/bug.php?id=55475

    Whether this change is considered a bug and whether it will be reverted or kept in future versions is yet to be determined, but nevertheless it is how it is, for now...

        但是需要注意的是,PHP是否会对这个问题做出修补仍属未知!在昨天发布的PHP 5.4 beta1 中,并未见到修复了此问题。

        这是一个类似于PHP的unserialize()函数可以执行__destruct()/__wakeup()中代码的问题

        漏洞的触发是控制 is_a()函数的第一个参数,该参数会被当做输入传入__autoload()函数,并自动执行__autoload()函数中的代码。能够执行什么功能,取决于__autoload()函数的功能。

        验证此问题如下:

    测试代码:

    <?php

    function __autoload($classname){

      include_once $classname;

    }

    function test($str){

      print "this is a test<br>";

      $object = $str;

      if (!is_a($object, 'SAFE')){

        die("not safe!<br>");

      }

    }

    test($_GET["a"]);

    ?>

    测试结果:

        但是一般来说,__autoload()函数的功能会用于加载一个文件,比如在DEDECMS中的用法:

    //自动加载类库处理

    function __autoload($classname)

    {

        global $cfg_soft_lang;

        $classname = preg_replace("/[^0-9a-z_]/i", '', $classname);

        if( class_exists ( $classname ) )

        {

            return TRUE;

        }

        $classfile = $classname.'.php';

        $libclassfile = $classname.'.class.php';

            if ( is_file ( DEDEINC.'/'.$libclassfile ) )

            {

                require DEDEINC.'/'.$libclassfile;

            }

            else if( is_file ( DEDEMODEL.'/'.$classfile ) ) 

            {

                require DEDEMODEL.'/'.$classfile;

            }

            else

            {

                if (DEBUG_LEVEL === TRUE)

                {

                    echo '<pre>';

    echo $classname.'类找不到';

    echo '</pre>';

    exit ();

                }

                else

                {

                    header ( "location:/404.html" );

                    die ();

                }

            }

    }

        此处在加载文件前判断了文件名只能为/[^0-9a-z_]/i 中的字符,相对较为安全。

        但在另外某知名CMS中,则没有做任何判断:

    function __autoload($class) {

        include_once $class.'.php';

        if(!class_exists($class,false)) exit('系统加载类失败,类'.$class.'不存在!');

    }

        由于这个漏洞是需要is_a()函数配合 __autoload() 才能利用,且对PHP版本有要求,因此实际中能够找到利用的地方相对较少。但若是PHP官方坚持不认为这是个漏洞,在未来可能会成为一个一直可以利用的弱点。在PHP5.4中is_a()可能会支持string类型参数,同时此漏洞应该已经上报给了CVE。

  • 相关阅读:
    记录java设计模式中适配器模式和装饰器模式和代理模式的区别
    excel工具类记录
    docker搭建图床 chevereto 非常方便
    docker 安装mysql
    rabbitmq学习之路(八)
    理解js中的作用域,作用域链以及闭包
    浏览器解析js的顺序
    javacript 组合使用构造函数模式和原型模式
    js垃圾回收机制与深拷贝和浅拷贝
    ES6 变量的解构赋值
  • 原文地址:https://www.cnblogs.com/milantgh/p/3633485.html
Copyright © 2011-2022 走看看