发布日期:2010-05-31
更新日期:2010-06-01
受影响系统:
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(¤t, (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(¤t);
}
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)
链接:
*>
测试方法:
--------------------------------------------------------------------------------
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
<?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
---
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本: