php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80100 heap-use-after-free in zval_undefined_cv (zend_execute.c:274)
Submitted: 2020-09-13 19:49 UTC Modified: 2020-09-14 19:33 UTC
From: sig dot run at yandex dot ru Assigned:
Status: Verified Package: Unknown/Other Function
PHP Version: 7.4Git-2020-09-13 (Git) OS: Linux (Ubuntu 18.04.2)
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: sig dot run at yandex dot ru
New email:
PHP Version: OS:

 

 [2020-09-13 19:49 UTC] sig dot run at yandex dot ru
Description:
------------
...
static zend_never_inline ZEND_COLD zval* ZEND_FASTCALL _zval_undefined_op1(EXECUTE_DATA_D)
{
        return zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
}
...

phpinfo()
PHP Version => 7.4.6

System => Linux ... 5.4.0-45-generic #49~18.04.2-Ubuntu SMP Wed Aug 26 16:29:02 UTC 2020 x86_64
Build Date => Sep 1 2020 20:17:31
Configure Command => './configure' '--prefix=/home/sigrun/fuzz_php/php_debug_clean' '--disable-all' '--enable-debug'
Server API => Command Line Interface
Virtual Directory Support => disabled
Configuration File (php.ini) Path => /home/sigrun/fuzz_php/php_debug_clean/lib
Loaded Configuration File => (none)
Scan this dir for additional .ini files => (none)
Additional .ini files parsed => (none)
PHP API => 20190902
PHP Extension => 20190902
Zend Extension => 320190902
Zend Extension Build => API320190902,NTS,debug
PHP Extension Build => API20190902,NTS,debug
Debug Build => yes
Thread Safety => disabled
Zend Signal Handling => enabled
Zend Memory Manager => disabled
Zend Multibyte Support => disabled
IPv6 Support => enabled
DTrace Support => disabled

Test script:
---------------
<?php
class test
{
        protected $_id;
        static $instances;

        public function __construct($id) {
                $this->_id = $id;- self::$instances[$this->_id] = $this;
        }

        function __destruct() {
                unset(self::$instances[$this->_id]);
        }
}
$test = new test(2);
$test = new test(1);
$test = new test(2);
$test = new test(3);
echo "ok\n";
?>

Expected result:
----------------
Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:120
120 ../sysdeps/x86_64/multiarch/../strlen.S
(gdb) exploitable
Description: Access violation near NULL on source operand
Short description: SourceAvNearNull (16/22)
Hash: 3f2ecb1de40c521e20f764eb3551e1b0.f3549e7dacb77ae6d2a607a1895c79ee
Exploitability Classification: PROBABLY_NOT_EXPLOITABLE
Explanation: The target crashed on an access violation at an address matching the source operand of the current instruction. This likely indicates a read access violation, which may mean the application crashed on a simple NULL dereference to data structure that has no immediate effect on control of the processor.
Other tags: AccessViolation (21/22)

Actual result:
--------------
=============================== Result without USE_ZEND_ALLOC ===============
==14661==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000398 (pc 0x7f3a92ea96b6 bp 0x7fff8ac6d640 sp 0x7fff8ac6cdb8 T0)
==14661==The signal is caused by a READ memory access.
==14661==Hint: address points to the zero page.
    #0 0x7f3a92ea96b5 (/lib/x86_64-linux-gnu/libc.so.6+0xb16b5)
    #1 0x7f3a940e157b (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5157b)
    #2 0x5631bf5df12a in xbuf_format_converter /home/sigrun/fuzz_php/src_php_asan/main/spprintf.c:596
    #3 0x5631bf5e0d0c in php_printf_to_smart_string /home/sigrun/fuzz_php/src_php_asan/main/spprintf.c:820
    #4 0x5631bf72ada8 in zend_vspprintf /home/sigrun/fuzz_php/src_php_asan/Zend/zend.c:197
    #5 0x5631bf5cac55 in php_error_cb /home/sigrun/fuzz_php/src_php_asan/main/main.c:1211
    #6 0x5631bf72ffe9 in zend_error_va_list /home/sigrun/fuzz_php/src_php_asan/Zend/zend.c:1317
    #7 0x5631bf731c4f in zend_error /home/sigrun/fuzz_php/src_php_asan/Zend/zend.c:1487
    #8 0x5631bf825b1e in zval_undefined_cv /home/sigrun/fuzz_php/src_php_asan/Zend/zend_execute.c:275
    #9 0x5631bf825b8d in _zval_undefined_op1 /home/sigrun/fuzz_php/src_php_asan/Zend/zend_execute.c:282
    #10 0x5631bf844dd0 in zend_mul_helper_SPEC /home/sigrun/fuzz_php/src_php_asan/Zend/zend_vm_execute.h:491
    #11 0x5631bf885962 in ZEND_MUL_SPEC_TMPVARCV_CONST_HANDLER /home/sigrun/fuzz_php/src_php_asan/Zend/zend_vm_execute.h:11327
    #12 0x5631bf97f22c in execute_ex /home/sigrun/fuzz_php/src_php_asan/Zend/zend_vm_execute.h:54662
    #13 0x5631bf988b25 in zend_execute /home/sigrun/fuzz_php/src_php_asan/Zend/zend_vm_execute.h:57856
    #14 0x5631bf73354f in zend_execute_scripts /home/sigrun/fuzz_php/src_php_asan/Zend/zend.c:1672
    #15 0x5631bf5d11fa in php_execute_script /home/sigrun/fuzz_php/src_php_asan/main/main.c:2621
    #16 0x5631bf98f126 in do_cli /home/sigrun/fuzz_php/src_php_asan/sapi/cli/php_cli.c:964
    #17 0x5631bf991376 in main /home/sigrun/fuzz_php/src_php_asan/sapi/cli/php_cli.c:1359
    #18 0x7f3a92e19b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #19 0x5631bee20b39 in _start (/home/sigrun/fuzz_php/php_asan/bin/php+0x37cb39)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/lib/x86_64-linux-gnu/libc.so.6+0xb16b5)
==14661==ABORTING
================================ Result with USE_ZEND_ALLOC=0 ============================
==14675==ERROR: AddressSanitizer: heap-use-after-free on address 0x6020000047d0 at pc 0x556cb8ef4af7 bp 0x7ffd38059360 sp 0x7ffd38059350
READ of size 8 at 0x6020000047d0 thread T0
    #0 0x556cb8ef4af6 in zval_undefined_cv /home/sigrun/fuzz_php/src_php_asan/Zend/zend_execute.c:274
    #1 0x556cb8ef4b8d in _zval_undefined_op1 /home/sigrun/fuzz_php/src_php_asan/Zend/zend_execute.c:282
    #2 0x556cb8f13dd0 in zend_mul_helper_SPEC /home/sigrun/fuzz_php/src_php_asan/Zend/zend_vm_execute.h:491
    #3 0x556cb8f54962 in ZEND_MUL_SPEC_TMPVARCV_CONST_HANDLER /home/sigrun/fuzz_php/src_php_asan/Zend/zend_vm_execute.h:11327
    #4 0x556cb904e22c in execute_ex /home/sigrun/fuzz_php/src_php_asan/Zend/zend_vm_execute.h:54662
    #5 0x556cb9057b25 in zend_execute /home/sigrun/fuzz_php/src_php_asan/Zend/zend_vm_execute.h:57856
    #6 0x556cb8e0254f in zend_execute_scripts /home/sigrun/fuzz_php/src_php_asan/Zend/zend.c:1672
    #7 0x556cb8ca01fa in php_execute_script /home/sigrun/fuzz_php/src_php_asan/main/main.c:2621
    #8 0x556cb905e126 in do_cli /home/sigrun/fuzz_php/src_php_asan/sapi/cli/php_cli.c:964
    #9 0x556cb9060376 in main /home/sigrun/fuzz_php/src_php_asan/sapi/cli/php_cli.c:1359
    #10 0x7f9976e11b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #11 0x556cb84efb39 in _start (/home/sigrun/fuzz_php/php_asan/bin/php+0x37cb39)

0x6020000047d0 is located 0 bytes inside of 12-byte region [0x6020000047d0,0x6020000047dc)
freed by thread T0 here:
    #0 0x7f9978166f30 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef30)
    #1 0x556cb8d71ab8 in __zend_realloc /home/sigrun/fuzz_php/src_php_asan/Zend/zend_alloc.c:2995
    #2 0x556cb8d6f9bd in _realloc_custom /home/sigrun/fuzz_php/src_php_asan/Zend/zend_alloc.c:2435
    #3 0x556cb8d6fba0 in _erealloc /home/sigrun/fuzz_php/src_php_asan/Zend/zend_alloc.c:2557
    #4 0x556cb8dd180f in emit_live_range_raw /home/sigrun/fuzz_php/src_php_asan/Zend/zend_opcode.c:581
    #5 0x556cb8dd1fb5 in emit_live_range /home/sigrun/fuzz_php/src_php_asan/Zend/zend_opcode.c:723
    #6 0x556cb8dd28a4 in zend_calc_live_ranges /home/sigrun/fuzz_php/src_php_asan/Zend/zend_opcode.c:803
    #7 0x556cb8dd4d94 in pass_two /home/sigrun/fuzz_php/src_php_asan/Zend/zend_opcode.c:1042
    #8 0x556cb8d9f99c in zend_compile_func_decl /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:6074
    #9 0x556cb8db3b15 in zend_compile_stmt /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:8545
    #10 0x556cb8d9977f in zend_compile_stmt_list /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:5266
    #11 0x556cb8db39a3 in zend_compile_stmt /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:8489
    #12 0x556cb8da2653 in zend_compile_class_decl /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:6477
    #13 0x556cb8db35ff in zend_compile_top_stmt /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:8464
    #14 0x556cb8db3425 in zend_compile_top_stmt /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:8453
    #15 0x556cb8d29166 in zend_compile Zend/zend_language_scanner.l:614
    #16 0x556cb8d2962f in compile_file Zend/zend_language_scanner.l:650
    #17 0x556cb890aabb in phar_compile_file /home/sigrun/fuzz_php/src_php_asan/ext/phar/phar.c:3299
    #18 0x556cb8e024b9 in zend_execute_scripts /home/sigrun/fuzz_php/src_php_asan/Zend/zend.c:1666
    #19 0x556cb8ca01fa in php_execute_script /home/sigrun/fuzz_php/src_php_asan/main/main.c:2621
    #20 0x556cb905e126 in do_cli /home/sigrun/fuzz_php/src_php_asan/sapi/cli/php_cli.c:964
    #21 0x556cb9060376 in main /home/sigrun/fuzz_php/src_php_asan/sapi/cli/php_cli.c:1359
    #22 0x7f9976e11b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

previously allocated by thread T0 here:
    #0 0x7f9978166f30 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef30)
    #1 0x556cb8d71ab8 in __zend_realloc /home/sigrun/fuzz_php/src_php_asan/Zend/zend_alloc.c:2995
    #2 0x556cb8d6f9bd in _realloc_custom /home/sigrun/fuzz_php/src_php_asan/Zend/zend_alloc.c:2435
    #3 0x556cb8d6fba0 in _erealloc /home/sigrun/fuzz_php/src_php_asan/Zend/zend_alloc.c:2557
    #4 0x556cb8dd180f in emit_live_range_raw /home/sigrun/fuzz_php/src_php_asan/Zend/zend_opcode.c:581
    #5 0x556cb8dd1fb5 in emit_live_range /home/sigrun/fuzz_php/src_php_asan/Zend/zend_opcode.c:723
    #6 0x556cb8dd28a4 in zend_calc_live_ranges /home/sigrun/fuzz_php/src_php_asan/Zend/zend_opcode.c:803
    #7 0x556cb8dd4d94 in pass_two /home/sigrun/fuzz_php/src_php_asan/Zend/zend_opcode.c:1042
    #8 0x556cb8d9f99c in zend_compile_func_decl /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:6074
    #9 0x556cb8db3b15 in zend_compile_stmt /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:8545
    #10 0x556cb8d9977f in zend_compile_stmt_list /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:5266
    #11 0x556cb8db39a3 in zend_compile_stmt /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:8489
    #12 0x556cb8da2653 in zend_compile_class_decl /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:6477
    #13 0x556cb8db35ff in zend_compile_top_stmt /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:8464
    #14 0x556cb8db3425 in zend_compile_top_stmt /home/sigrun/fuzz_php/src_php_asan/Zend/zend_compile.c:8453
    #15 0x556cb8d29166 in zend_compile Zend/zend_language_scanner.l:614
    #16 0x556cb8d2962f in compile_file Zend/zend_language_scanner.l:650
    #17 0x556cb890aabb in phar_compile_file /home/sigrun/fuzz_php/src_php_asan/ext/phar/phar.c:3299
    #18 0x556cb8e024b9 in zend_execute_scripts /home/sigrun/fuzz_php/src_php_asan/Zend/zend.c:1666
    #19 0x556cb8ca01fa in php_execute_script /home/sigrun/fuzz_php/src_php_asan/main/main.c:2621
    #20 0x556cb905e126 in do_cli /home/sigrun/fuzz_php/src_php_asan/sapi/cli/php_cli.c:964
    #21 0x556cb9060376 in main /home/sigrun/fuzz_php/src_php_asan/sapi/cli/php_cli.c:1359
    #22 0x7f9976e11b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

SUMMARY: AddressSanitizer: heap-use-after-free /home/sigrun/fuzz_php/src_php_asan/Zend/zend_execute.c:274 in zval_undefined_cv
Shadow bytes around the buggy address:
  0x0c047fff88a0: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
  0x0c047fff88b0: fa fa 00 00 fa fa 00 00 fa fa fd fd fa fa 00 fa
  0x0c047fff88c0: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fd
  0x0c047fff88d0: fa fa fd fd fa fa 00 fa fa fa 00 04 fa fa 00 05
  0x0c047fff88e0: fa fa 00 05 fa fa 04 fa fa fa 00 00 fa fa 00 00
=>0x0c047fff88f0: fa fa 04 fa fa fa 00 fa fa fa[fd]fd fa fa 04 fa
  0x0c047fff8900: fa fa 00 04 fa fa 00 fa fa fa fd fd fa fa fa fa
  0x0c047fff8910: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8920: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8930: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8940: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
  Freed heap region: fd
  Stack left redzone: f1
  Stack mid redzone: f2
  Stack right redzone: f3
  Stack after return: f5
  Stack use after scope: f8
  Global redzone: f9
  Global init order: f6
  Poisoned by user: f7
  Container overflow: fc
  Array cookie: ac
  Intra object redzone: bb
  ASan internal: fe
  Left alloca redzone: ca
  Right alloca redzone: cb

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-09-14 14:15 UTC] nikic@php.net
-Status: Open +Status: Verified
 [2020-09-14 14:15 UTC] nikic@php.net
Reduced a bit:

<?php
class test
{
    protected $_id;
    static $instances;

    public function __construct($id) {
        $this->_id = $id;
        var_dump(self::$instances[$id] = $this);
    }

    function __destruct() {
        unset(self::$instances[$this->_id]);
    }
}

new test(2);
new test(2);
echo "ok\n";

This is a non-crashing case that prints UNKNOWN:0.

What I assume is happening here is that we replace the array element, destroy the old value, the old value destruction sets the array element to UNDEF, and then we return the array element.

A corollary to this is that we can also free the whole array, in which case we'll return a dangling pointer:

<?php
class test
{
    protected $_id;
    static $instances;

    public function __construct($id) {
        $this->_id = $id;
        var_dump(self::$instances[$id] = $this);
    }

    function __destruct() {
        self::$instances = [];
    }
}

new test(2);
new test(2);
echo "ok\n";

Probably fairly hard to fix.
 [2020-09-14 18:20 UTC] sig dot run at yandex dot ru
Nikita can this type of error be attributed to vulnerability or not? The dangling pointer refers to a software defect: CWE-404 https://cwe.mitre.org/data/definitions/404.html and is considered a vulnerability. Or, in this case, you cannot assign an identifier CVE.
 [2020-09-14 19:19 UTC] sig dot run at yandex dot ru
-Type: Bug +Type: Security -Private report: No +Private report: Yes
 [2020-09-14 19:19 UTC] sig dot run at yandex dot ru
Most likely it was necessary to change the error type to security.
 [2020-09-14 19:33 UTC] nikic@php.net
-Type: Security +Type: Bug
 [2020-09-14 19:33 UTC] nikic@php.net
As there is no possibility of remote exploitation, it's not considered a security issue from our side (per https://wiki.php.net/security).
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Mon Oct 26 05:01:24 2020 UTC