PHP php_dechunk() HTTP分块编码整数溢出漏洞
发布日期:2010-05-02
更新日期:2010-05-04
受影响系统:
PHP PHP <= 5.3.2
描述:
--------------------------------------------------------------------------------
BUGTRAQ ID: 39877
PHP是广泛使用的通用目的脚本语言,特别适合于Web开发,可嵌入到HTML中。
PHP的ext/standard/filters.c文件中的php_dechunk()函数在处理HTTP流时存在符号错误,通过dechunk过滤器处理超大的HTTP块时可以触发内存破坏。
新的PHP dechunk过滤器中的状态机使用以下结构记忆当前的状态:
typedef struct _php_chunked_filter_data {
php_chunked_filter_state state;
int chunk_size;
int persistent;
} php_chunked_filter_data;
chunk_size存储为有符整形,由于使用了块大小解码器,这可能导致问题:
case CHUNK_SIZE:
while (p < end) {
if (*p >= '0' && *p <= '9') {
data->chunk_size = (data->chunk_size * 16) + (*p - '0');
} else if (*p >= 'A' && *p <= 'F') {
data->chunk_size = (data->chunk_size * 16) + (*p - 'A' + 10);
} else if (*p >= 'a' && *p <= 'f') {
data->chunk_size = (data->chunk_size * 16) + (*p - 'a' + 10);
} else if (data->state == CHUNK_SIZE_START) {
data->state = CHUNK_ERROR;
break;
} else {
data->state = CHUNK_SIZE_EXT_START;
break;
}
data->state = CHUNK_SIZE;
p++;
}
块大小解码器没有防范整数溢出,正的32位块大小会导致在chunk_size状态变量中存储负整数,之后将块大小与剩余的缓冲区空间做比较时会触发溢出:
case CHUNK_BODY:
if (end - p >= data->chunk_size) {
if (p != out) {
memmove(out, p, data->chunk_size);
}
out += data->chunk_size;
out_len += data->chunk_size;
p += data->chunk_size;
在chunk_size有符整形变量中存储负的块大小会绕过检查,导致在两个堆缓冲区之间拷贝2GB到4GB。通常这仅能导致崩溃,但在多线程Web服务器中也可能导致可利用的内存破坏。不过PHP很少在多线程环境中使用。
<*来源:Stefan Esser ([email protected])
链接:http://secunia.com/advisories/39573/
http://php-security.org/2010/05/02/mops-2010-003-php-dechunk-filter-signed-comparison-vulnerability/index.html
*>
测试方法:
--------------------------------------------------------------------------------
警 告
以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!
<?php
$x = '0fffffffe
XXX';
file_put_contents("file:///tmp/test.dat",$x);
$y = file_get_contents('php://filter/read=dechunk/resource=file:///tmp/test.dat');
echo "here";
?>
建议:
--------------------------------------------------------------------------------
厂商补丁:
PHP
---
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本: