[译]修复PHP HashTable碰撞DOS 引入新的远程访问漏洞

原文:http://thexploit.com/sec/critical-php-remote-vulnerability-introduced-in-fix-for-php-hashtable-collision-dos/

(初步练习翻译,各种不当求大神指出~)

Stefan Esser (@i0n1c)

一个安全修复引入另外的漏洞

今天, Stefan Esser (@i0n1c) 提交了一个 PHP 5.3.9 (updateassigned CVE-2012-0830) 版本下重要的远程利用漏洞。有趣的是,这个漏洞是为了修复十二月提交的哈希碰撞导致拒绝服务 DOS (CVE-2011-4885) 的漏洞而引入的。

关于漏洞的修复

为了防止哈希碰撞这个修复在 php.ini 配置文件中引入了一个新的参数:
max_input_vars

这个配置参数限制了请求提交的变量的数量(e.g. http://request.com/foo.php?a=1&b=2&c=3)。默认值是1000。

这个修改在文件 php_variables.c 的方法 php_register_variable_ex 中。

通过这个方法,PHP会“注册”所有提交过来的变量。

if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) {
    php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
}

调用了一个脆弱的方法 :

PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array TSRMLS_DC)
{
 
...tons of code removed...
 
if (is_array) {
 
... code removed ...
 
        if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) {
            if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
            }
            MAKE_STD_ZVAL(gpc_element);
            array_init(gpc_element);
            zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
        }
         
        ... some code removed...
         
        symtable1 = Z_ARRVAL_PP(gpc_element_p);
         
... tons more code removed ...
 
}

 这个漏洞发生在当提交的变量的数量超过 max_input_vars 设置的数量并且这个变量是一个数组 (if (*p == ‘[‘)) 。这种情况下代码不会停止并返回,而是代码继续执行。

当代码继续执行到207行(本文上图代码21行)。它调用了一个宏 Z_ARRVAL_PP 得到一个参考来更新哈希表。这是内部被执行的代码。

我们继续往下多看一点,gpc_element 最终被赋的值。

plain_var:
    MAKE_STD_ZVAL(gpc_element);
    gpc_element->value = val->value;

 当代码执行到这里时,变量的数量大于最大变量数量限制,gpc_element_p 将指向以前的变量值。Z_ARRVAL_PP 的期望值将是一个 ZVAL 结构体的哈希表(通常是初始化 array_init(…)) ,但是在之前还没初始化内存的情况下是一个非数组的普通变量。

搞笑的是

最搞笑的是这都是因为修复了一个安全漏洞导致的,这更像是一个移植应用和向后兼容,而非常规的修复和更新。(这后半句翻的好像有问题啊,不太会翻啊~~求大神留言啊)

更新修复版本

PHP 5.3.10 released – 立即更新