PHP会话序列化程序数据注入漏洞

受影响系统:

PHP PHP <= 5.3.2
PHP PHP <= 5.2.13

描述:

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

默认的会话还原序列化程序知道两个特殊字符:PS_DELIMITER和PS_UNDEF_MARKER。前者用于分隔所存储的会话变量,后者用于标记未定义的会话变量。以下代码实现上述功能:

    while (p < endptr) {
        zval **tmp;
        q = p;
        while (*q != PS_DELIMITER) {
            if (++q >= endptr) goto break_outer_loop;
        }
        if (p[0] == PS_UNDEF_MARKER) {
            p++;
            has_value = 0;
        } else {
            has_value = 1;
        }

        namelen = q – p;
        name = estrndup(p, namelen);
        q++;

        if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) {
            if ((Z_TYPE_PP(tmp) == IS_ARRAY && Z_ARRVAL_PP(tmp) == &EG(symbol_table)) || *tmp == PS(http_session_vars)) {
                goto skip;
            }
        }

        if (has_value) {
            ALLOC_INIT_ZVAL(current);
            if (php_var_unserialize(&current, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
                php_set_session_var(name, namelen, current, &var_hash  TSRMLS_CC);
            }
            zval_ptr_dtor(&current);
        }
        PS_ADD_VARL(name, namelen);
skip:
        efree(name);

        p = q;
    }

问题是会话序列化程序仅正确处理了PS_DELIMITER,根本没有处理PS_UNDEF_MARKER:

PS_ENCODE_LOOP(
        smart_str_appendl(&buf, key, key_length);
        if (memchr(key, PS_DELIMITER, key_length)) {
            PHP_VAR_SERIALIZE_DESTROY(var_hash);
            smart_str_free(&buf);
            return FAILURE;
        }
        smart_str_appendc(&buf, PS_DELIMITER);

        php_var_serialize(&buf, struc, &var_hash TSRMLS_CC);
    } else {
        smart_str_appendc(&buf, PS_UNDEF_MARKER);
        smart_str_appendl(&buf, key, key_length);
        smart_str_appendc(&buf, PS_DELIMITER);
);

以PS_UNDEF_MARKER开始的会话变量名称会迷惑会话还原序列化程序。也就是任何允许向会话中写入任意变量的PHP代码可以向会话中注入任意序列化的值,且类似于以下的代码等同于还原序列化用户输入。

<?php
   session_start();
   $_SESSION[$_POST[‘prefix’] . ‘bla’] = $_POST[‘data’];
?>

<*来源:Stefan Esser (s.esser@ematters.de
  
  链接:
http://php-security.org/2010/05/31/mops-2010-060-php-session-serializer-session-data-injection-vulnerability/index.html
*>

测试方法:
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
<?php
   session_start();
   $_SESSION[$_POST[‘prefix’] . ‘bla’] = $_POST[‘data’];
?>

或:

<?php
   session_start();
   $_SESSION = array_merge($_SESSION, $_POST);
?>

通过提交prefix=!和data=|xxx|O:10:"evilObject":0:{}的POST请求,就可以向会话中注入任意序列化的数据。

建议:

 

厂商补丁:

PHP

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

http://www.php.net

发表评论?

0 条评论。

发表评论