Bug #71220 [Opn]: Null pointer deref (segfault) in compact via ob_start
[email protected] ("hugh at allthethings dot co dot nz")
| Newsgroups | php.bugs |
|---|---|
| Message-ID | <[email protected]> |
Edit report at https://bugs.php.net/bug.php?id=71220&edit=1
ID: 71220
User updated by: hugh at allthethings dot co dot nz
Reported by: hugh at allthethings dot co dot nz
Summary: Null pointer deref (segfault) in compact via
ob_start
Status: Open
Type: Bug
Package: Reproducible crash
Operating System: Linux
PHP Version: 7.0.1
Block user comment: N
Private report: Y
New Comment:
Hi,
This is a null pointer deference, which is described on the common weakness enumeration (CWE) list as CWE-476 [1]. It can cause a denial of service, by causing the PHP process to crash unexpectedly (segmentation fault on linux systems).
It is similar to bug #70290 which you fixed promptly, and to earlier bugs I filed such as bug #70183 where ab said that similar bugs (null pointer derefence causing crashes) would count as security after PHP 7 was released, which it has.
If you would like me to label null pointer derefences as non security issues in future, let me know.
Cheers,
Hugh
[1] - https://cwe.mitre.org/data/definitions/476.html
Previous Comments:
------------------------------------------------------------------------
[2015-12-26 05:21:44] [email protected]
I think this is not a security issue, public it.
------------------------------------------------------------------------
[2015-12-26 05:12:57] [email protected]
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