安全研究

安全漏洞
PHP mbstring扩展堆溢出漏洞

发布日期:2008-12-21
更新日期:2008-12-24

受影响系统:
PHP PHP 4.3.0 - 5.2.6
描述:
BUGTRAQ  ID: 32948
CVE(CAN) ID: CVE-2008-5557

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

PHP的mbstring扩展的ext/mbstring/libmbfl/filters/mbfilter_htmlent.c文件中存在堆溢出漏洞,远程攻击者可以通过包含有HTML实体的特制字符串来触发这个溢出,导致执行任意代码。

以下是mbfilter_htmlent.c中有问题的HTML实体解码器,这里解码器实现为一个回调函数,输入字符串中的每个字符都会用包含有解码器状态的结构(mbfl_convert_filter)顺序调用该回调函数。

mbfl_convert_filter中的output_function字段指向一个函数,解码后的数据逐字符的传送给该函数,在出现错误的时候函数应返回负值,但如果参数是没有分配给任何字符的Unicode值时就可能失效。具体来说,由于output_function的符号是int(*)(int, void *)而缓冲区是无符字符数组,因此任何大于127的字符代码都会在将其值取反后传送给该函数,导致无条件的失效。

------------------------------------------------------------------------------

#define CK(statement)   do { if ((statement) < 0) return (-1); } while (0)

...

int mbfl_filt_conv_html_dec(int c, mbfl_convert_filter *filter)
{
    if (!filter->status) {
        ...
    } else {
        if (c == ';') {
            ...
        } else {
           /* add character */
            buffer[filter->status++] = c;
            /* add character and check */
            if (!strchr(html_entity_chars, c) ||
filter->status+1==html_enc_buffer_size || (c=='#' && filter->status>2))
            {
                /* illegal character or end of buffer */
                if (c=='&')
                    filter->status--;
                buffer[filter->status] = 0;
                /* php_error_docref("ref.mbstring" TSRMLS_CC, E_WARNING,
"mbstring cannot decode '%s'", buffer)l */
                mbfl_filt_conv_html_dec_flush(filter);
                if (c=='&')
                {
                    filter->status = 1;
                    buffer[0] = '&';
                }
            }
        }
    }
}

int mbfl_filt_conv_html_dec_flush(mbfl_convert_filter *filter)
{
    int status, pos = 0;
    char *buffer;

    buffer = (char*)filter->opaque;
    status = filter->status;
    /* flush fragments */
    while (status--) {
        CK((*filter->output_function)(buffer[pos++], filter->data));
    }
    filter->status = 0;
    /*filter->buffer = 0; of cause NOT*/
    return 0;
}

-
------------------------------------------------------------------------------

如果用户输入中的字符序列包含有一个或多个不属于html_entity_chars的字符,在mbfl_filt_conv_html_dec_flush()中调用输出函数就会失败。由于CK()宏中的返回语句,这可能导致未经重置filter->status就回到调用函数,最终允许随意的访问mbfl_filt_conv_html_dec()中的缓冲区。

<*来源:Moriyoshi Koizumi (mozo@mozo.jp
  
  链接:http://marc.info/?l=full-disclosure&m=122984001319432&w=2
        http://bugs.php.net/bug.php?id=45722
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

$text = "&· ASDF ASDF ASDF ASDF ASDF ASDF ASDF";
if( !mb_check_encoding($text,'HTML-ENTITIES') ) {
     $text = htmlentities($text);
}
echo $text;

建议:
厂商补丁:

PHP
---
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:

http://cvs.php.net/viewvc.cgi/php-src/ext/mbstring/libmbfl/filters/mbfilter_htmlent.c?r1=1.7&r2=1.8

浏览次数:3226
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障