2012-12-02 02:59:06
By Tim Brown
Background: A colleague asked me about fuzzing PHP. Verbatim from my email to security@php.net back in 2007:
I've been doing some work on fuzzing the PHP 4 and PHP 5 parsers and wanted to share my results with you. I know PHP 4 won't be supported for much longer and I have no idea whether any of these examples are directly exploitable however before I make them public I thought it was only right to give you a chance to comment. Feel free to ignore me if you so choose, but I'll be putting them up on my blog in 14 days unless I hear otherwise. Although I'm reporting them against the CGI binary, I've had similar results running these snippets against the module too. In each case, I can cause the process (either the CGI binary or the module) to crash. The fuzzers I've written are also available if you so wish.
I never did do anything with them but they're all dead now.
PHP 4 (PHP 4.4.4-9+lenny1 (cgi-fcgi) (built: May 24 2007 20:14:24))
Program received signal SIGFPE, Arithmetic exception. 0x08122ab0 in zif_wordwrap () (gdb) bt #0 0x08122ab0 in zif_wordwrap () #1 0x081a8304 in execute () #2 0x0818dfc6 in zend_execute_scripts () #3 0x0815bd8e in php_execute_script () #4 0x081b3094 in main () (gdb) i r eax 0x2 2 ecx 0x0 0 edx 0x0 0 ebx 0x8323014 137506836 esp 0xbf9fb4c0 0xbf9fb4c0 ebp 0xbf9fb558 0xbf9fb558 esi 0x0 0 edi 0x0 0 eip 0x8122ab0 0x8122ab0 <zif_wordwrap+928> eflags 0x210202 [ IF RF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
Program received signal SIGSEGV, Segmentation fault. 0x0817dc40 in _efree () (gdb) bt #0 0x0817dc40 in _efree () #1 0x0817109b in php_end_ob_buffer () #2 0x0817169e in php_end_ob_buffers () #3 0x0815c592 in php_request_shutdown () #4 0x081b255a in main () (gdb) i r eax 0x0 0 ecx 0x0 0 edx 0x0 0 ebx 0x8323014 137506836 esp 0xbfdb5410 0xbfdb5410 ebp 0xbfdb5428 0xbfdb5428 esi 0xfffffff4 -12 edi 0x8332ec0 137572032 eip 0x817dc40 0x817dc40 <_efree+32> eflags 0x210293 [ CF AF SF IF RF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
Program received signal SIGSEGV, Segmentation fault. 0x080a377d in zif_dcngettext () (gdb) bt #0 0x080a377d in zif_dcngettext () #1 0x081a8304 in execute () #2 0x0818dfc6 in zend_execute_scripts () #3 0x0815bd8e in php_execute_script () #4 0x081b3094 in main () (gdb) i r eax 0x1 1 ecx 0x31 49 edx 0xa 10 ebx 0x8323014 137506836 esp 0xbfef5190 0xbfef5190 ebp 0xbfef51d8 0xbfef51d8 esi 0xbfef52c4 -1074834748 edi 0x839864c 137987660 eip 0x80a377d 0x80a377d <zif_dcngettext+621> eflags 0x210286 [ PF SF IF RF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
PHP 5 (PHP 5.2.4-1+b1 with Suhosin-Patch 0.9.6.2 (cgi-fcgi) (built: Oct 1 2007 10:29:46))
Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0xb78dd8c0 (LWP 16731)] 0xb7aa4503 in strlen () from /lib/i686/cmov/libc.so.6 (gdb) bt #0 0xb7aa4503 in strlen () from /lib/i686/cmov/libc.so.6 #1 0x080aecdf in zif_jdmonthname () #2 0x082e8f5b in ?? () #3 0x00000002 in ?? () #4 0x086923a0 in ?? () #5 0x00000000 in ?? () (gdb) i r eax 0x0 0 ecx 0x0 0 edx 0xfffffffe -2 ebx 0x855a20c 139829772 esp 0xbfb0175c 0xbfb0175c ebp 0xbfb017a8 0xbfb017a8 esi 0x0 0 edi 0x86923a0 141108128 eip 0xb7aa4503 0xb7aa4503 <strlen+51> eflags 0x210246 [ PF ZF IF RF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0xb78a78c0 (LWP 23742)] 0xb7a6e503 in strlen () from /lib/i686/cmov/libc.so.6 (gdb) bt #0 0xb7a6e503 in strlen () from /lib/i686/cmov/libc.so.6 #1 0x082c25bb in add_assoc_string_ex () #2 0x080afc0c in zif_cal_from_jd () #3 0x082e8f5b in ?? () #4 0x00000002 in ?? () #5 0x08692408 in ?? () #6 0x00000000 in ?? () (gdb) i r eax 0x0 0 ecx 0x0 0 edx 0x8581b44 139991876 ebx 0x855a20c 139829772 esp 0xbf9b9dac 0xbf9b9dac ebp 0xbf9b9df8 0xbf9b9df8 esi 0x8692890 141109392 edi 0x0 0 eip 0xb7a6e503 0xb7a6e503 <strlen+51> eflags 0x210246 [ PF ZF IF RF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
The fuzzer code can be found below, although it doesn't seem to trigger any bugs in recent releases of PHP:
# The following can be used to fingerprint what functions are available # for ($arraycounter = 0; $arraycounter < count($function); $arraycounter ++) { # if (function_exists($function[$arraycounter])) { # echi $function[$arraycounter] . " OK\n"; # } # } # What shall we fuzz today? $function = array(<list of PHPfunctions to fuzz>); # Mmm, input :) $data = array("\"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP\"", "-1", "0xd34adb33f", "0", "1", "true", "false", "undef", "\"%1000n\"", "$dummyvariable", "\"\x00\"", "0xd34db33f"); # Operations to perform $uoperator = array("++", "--"); $doperator = array("+", "-", "+=", "-=", "/", "*", "&&", "||", ".", "!=", "&", "^", "<=", ">=", "==", "xor", "and", "or"); set_time_limit(0); # Seed the fuzzer and it will bear fruit $seed = time(); srand($seed); echo "seed was: " . $seed . "\n"; while (1) { # getting deep and meaningful $maxdepth = 5; $expression = makeExpression(); echo $expression . "\n"; eval($expression); } function makeExpression() { $expression = makeFunction() . ";"; return $expression; } function makeFunction() { global $function; do { $rndfunction = rand(0, count($function) - 1); if (function_exists($function[$rndfunction])) { $expression = $function[$rndfunction]; } else { $function = array_remove($function, $rndfunction); } } while ($expression == ""); $expression = $expression . "("; $maxparameter = rand(1, 10); for ($parameter = 1; $parameter < $maxparameter; $parameter ++) { $expression = $expression . makeParameter() . ", "; } $expression = $expression . makeParameter() . ")"; return $expression; } function makeParameter() { global $data, $uoperator, $doperator, $maxdepth; if ($maxdepth > 0) { $operator = rand(1, 4); } else { $operator = rand(1, 3); } switch ($operator) { case 1: $rnddata = rand(0, count($data) - 1); $parameter = $data[$rnddata]; break; case 2: $rnddata = rand(0, count($data) - 1); $parameter = $data[$rnddata]; $rnduoperator = rand(0, count($uoperator) - 1); $parameter = $parameter . " " . $uoperator[$rnduoperator]; break; case 3: $rnddata = rand(0, count($data) - 1); $parameter = $data[$rnddata]; $rnddoperator = rand(0, count($doperator) - 1); $parameter = $parameter . " " . $doperator[$rnddoperator]; $rnddata = rand(0, count($data) - 1); $parameter = $parameter . " " . $data[$rnddata]; break; case 4: $maxdepth --; $parameter = makeFunction(); break; } return $parameter; } function array_remove($array, $arrayindex) { $newarray = array(); $arraycounter = 0; for ($arraycounter = 0; $arraycounter < count($array); $arraycounter ++) { if ($arraycounter != $arrayindex) { $newarray[] = $array[$arraycounter]; } } return $newarray; }
Mood: Relaxed
Music: Nothing playing right now
You are unknown, comment