Sec Bug->Bug #71220 [Opn]: Null pointer deref (segfault) in compact via ob_start

From: Date: Sat, 26 Dec 2015 05:21:44 +0000
Subject: Sec Bug->Bug #71220 [Opn]: Null pointer deref (segfault) in compact via ob_start
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-198232@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=71220&edit=1 ID: 71220 Updated by: laruence@php.net Reported by: hugh at allthethings dot co dot nz Summary: Null pointer deref (segfault) in compact via ob_start Status: Open -Type: Security +Type: Bug Package: Reproducible crash Operating System: Linux PHP Version: 7.0.1 Block user comment: N Private report: Y New Comment: I think this is not a security issue, public it. Previous Comments: ------------------------------------------------------------------------ [2015-12-26 05:12:57] laruence@php.net I don't understand why this is a security problem? ------------------------------------------------------------------------ [2015-12-25 20:03:09] hugh at allthethings dot co dot nz Description: ------------ Found this using afl-fuzz, see http://lcamtuf.coredump.cx/afl/ Affects 7.0.0, 7.0.1, 7.0.2, but none of the 5.6 series or before. To reproduce, compile PHP normally, then run ./sapi/cli/php with the test script <?php ob_start( compact ); ?> You should get a segfault. The test case is similar to a bug I filed for 5.6, bug #70290, where ob_start can call Zend functions instead of just PHP userland functions. What is happening is the call to compact actually goes to the function zif_compact in ext/standard/array.c, where the symbol table created on line 1977 with zend_rebuild_symbol_table() returns null, and is then passed into php_compact_var on line 1989, which produces the stack trace below. A patch to fix would be: diff --git a/ext/standard/array.c b/ext/standard/array.c index 79c9ab6..a2be69b 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1976,6 +1976,10 @@ PHP_FUNCTION(compact) symbol_table = zend_rebuild_symbol_table(); + if (symbol_table == NULL) { + return; + } + /* compact() is probably most used with a single array of var_names or multiple string names, rather than a combination of both. So quickly guess a minimum result size based on that */ Test script: --------------- <?php ob_start( compact ); ?> Expected result: ---------------- No crash Actual result: -------------- When compiled with ASAN, get this backtrace: $ ./php-7.0.2-asan ~/php-crash-7.0-compact ASAN:SIGSEGV ================================================================= ==21914== ERROR: AddressSanitizer: SEGV on unknown address 0x000000000010 (pc 0x00000138e715 sp 0x7ffd5189a610 bp 0x8000000000001505 T0) AddressSanitizer can not provide additional info. #0 0x138e714 in zend_hash_find_bucket /root/php-src/Zend/zend_hash.c:492 #1 0x138e714 in zend_hash_find /root/php-src/Zend/zend_hash.c:1947 #2 0xb52c0d in zend_hash_find_ind /root/php-src/Zend/zend_hash.h:278 #3 0xb52c0d in php_compact_var /root/php-src/ext/standard/array.c:1942 #4 0xb52c0d in zif_compact /root/php-src/ext/standard/array.c:1989 #5 0x11e8793 in zend_call_function /root/php-src/Zend/zend_execute_API.c:881 #6 0x12f28ba in zend_fcall_info_call /root/php-src/Zend/zend_API.c:3574 #7 0xf5f746 in php_output_handler_op /root/php-src/main/output.c:960 #8 0xf5f746 in php_output_stack_pop /root/php-src/main/output.c:1221 #9 0xf5f746 in php_output_end_all /root/php-src/main/output.c:341 #10 0xeb5014 in php_request_shutdown /root/php-src/main/main.c:1777 #11 0x19bd1a2 in do_cli /root/php-src/sapi/cli/php_cli.c:1142 #12 0x472e0a in main /root/php-src/sapi/cli/php_cli.c:1345 #13 0x7f8960f2cec4 (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4) #14 0x473ed1 in _start (/root/php-src/php-7.0.2-asan+0x473ed1) SUMMARY: AddressSanitizer: SEGV /root/php-src/Zend/zend_hash.c:491 zend_hash_find_bucket ==21914== ABORTING Aborted When compiled without ASAN, it Segmentation Fault's, and running under gdb gives this: $ gdb -ex r -ex 'x/i $rip' -ex bt -ex c -ex quit --args ./php-7.0.2-noasan ~/php-crash-7.0-compact <snip> Starting program: /root/php-src/php-7.0.2-noasan /root/php-crash-7.0-compact Program received signal SIGSEGV, Segmentation fault. 0x0000000000e6e5f8 in zend_hash_find_bucket (ht=0x0, ht=0x0, key=0x7ffff7003580) at /root/php-src/Zend/zend_hash.c:492 492 nIndex = h | ht->nTableMask; => 0xe6e5f8 <zend_hash_find+216>: mov 0xc(%r12),%eax #0 0x0000000000e6e5f8 in zend_hash_find_bucket (ht=0x0, ht=0x0, key=0x7ffff7003580) at /root/php-src/Zend/zend_hash.c:492 #1 zend_hash_find (ht=ht@entry=0x0, key=0x7ffff7003580) at /root/php-src/Zend/zend_hash.c:1947 #2 0x00000000008d2c6b in zend_hash_find_ind (key=<optimized out>, ht=0x0) at /root/php-src/Zend/zend_hash.h:278 #3 php_compact_var (entry=0x7ffff7014090, return_value=<optimized out>, eg_active_symbol_table=<optimized out>) at /root/php-src/ext/standard/array.c:1942 #4 zif_compact (execute_data=0x7ffff7014030, return_value=0x7fffffffd230) at /root/php-src/ext/standard/array.c:1989 #5 0x0000000000d568b3 in zend_call_function (fci=fci@entry=0x7ffff7072000, fci_cache=fci_cache@entry=0x7ffff7072048) at /root/php-src/Zend/zend_execute_API.c:879 #6 0x0000000000e071bb in zend_fcall_info_call (fci=0x7ffff7072000, fcc=0x7ffff7072048, retval_ptr=retval_ptr@entry=0x7fffffffd230, args=args@entry=0x0) at /root/php-src/Zend/zend_API.c:3574 #7 0x0000000000bbda34 in php_output_handler_op (context=0x7fffffffd260, handler=0x7ffff707f050) at /root/php-src/main/output.c:960 #8 php_output_stack_pop (flags=1) at /root/php-src/main/output.c:1221 #9 php_output_end_all () at /root/php-src/main/output.c:341 #10 0x0000000000b47335 in php_request_shutdown (dummy=dummy@entry=0x0) at /root/php-src/main/main.c:1777 #11 0x00000000011bdb9b in do_cli (argc=2, argv=0x18e38b0) at /root/php-src/sapi/cli/php_cli.c:1142 #12 0x00000000004473b9 in main (argc=2, argv=0x18e38b0) at /root/php-src/sapi/cli/php_cli.c:1345 Continuing. Program terminated with signal SIGSEGV, Segmentation fault. The program no longer exists. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=71220&edit=1

« previous php.bugs (#198232) next »