php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72859 Heap Use-After Free from bug64896 test case
Submitted: 2016-08-16 20:55 UTC Modified: 2017-01-01 19:25 UTC
From: vuln-report at secur3 dot us Assigned: laruence (profile)
Status: Duplicate Package: Class/Object related
PHP Version: 5.6.25RC1 OS: Linux (4.2.0-18)
Private report: No CVE-ID: None
 [2016-08-16 20:55 UTC] vuln-report at secur3 dot us
Description:
------------
Using ASAN reveals a heap use-after-free of READ 1 involving a circular reference.  My PHP CLI was built with clang version 4.0.0 (trunk 277962) and CFLAGS=-fsanitize-coverage=edge -fsanitize=address

Test script:
---------------
<?php
$bar = NULL;
class bad
{
        private $_private = array();
        public function __destruct()
        {
                global $bar;
                $bar = $this;
        }
}
$foo = new stdclass;
$foo->foo = $foo;
$foo->bad = new bad;

unserialize(serialize($foo));
gc_collect_cycles();
?>

Actual result:
--------------
$ ../../sapi/cli/php ./heap-uaf.phpt
=================================================================
==21365==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000000fb0 at pc 0x00000158bbda bp 0x7ffdea3d9ca0 sp 0x7ffdea3d9c98
READ of size 4 at 0x603000000fb0 thread T0
    #0 0x158bbd9 in _zval_ptr_dtor (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x158bbd9)
    #1 0x1661960 in zend_hash_destroy (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1661960)
    #2 0x170fefe in zend_object_std_dtor (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x170fefe)
    #3 0x171183f in zend_objects_free_object_storage (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x171183f)
    #4 0x174afbc in zend_objects_store_del_ref_by_handle_ex (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x174afbc)
    #5 0x1749eb3 in zend_objects_store_del_ref (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1749eb3)
    #6 0x15f6130 in _zval_dtor_func (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x15f6130)
    #7 0x158bd26 in _zval_ptr_dtor (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x158bd26)
    #8 0x166313a in zend_hash_bucket_delete (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x166313a)
    #9 0x1664b62 in zend_hash_reverse_apply (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1664b62)
    #10 0x158c1e0 in shutdown_destructors (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x158c1e0)
    #11 0x1604bb4 in zend_call_destructors (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1604bb4)
    #12 0x134903e in php_request_shutdown (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x134903e)
    #13 0x1bc7158 in do_cli (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1bc7158)
    #14 0x1bc10c1 in main (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1bc10c1)
    #15 0x7fd345aada3f in __libc_start_main /build/buildd/glibc-2.21/csu/libc-start.c:289
    #16 0x4371a8 in _start (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x4371a8)

0x603000000fb0 is located 16 bytes inside of 32-byte region [0x603000000fa0,0x603000000fc0)
freed by thread T0 here:
    #0 0x4d5f5b in free (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x4d5f5b)
    #1 0x14d4b2b in _efree (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x14d4b2b)
    #2 0x16de539 in gc_collect_cycles (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x16de539)
    #3 0x1695d3e in zif_gc_collect_cycles (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1695d3e)
    #4 0x1a7b631 in zend_do_fcall_common_helper_SPEC (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1a7b631)
    #5 0x185e984 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x185e984)
    #6 0x1755292 in execute_ex (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1755292)
    #7 0x1757996 in zend_execute (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1757996)
    #8 0x1605fa8 in zend_execute_scripts (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1605fa8)
    #9 0x1352fb1 in php_execute_script (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1352fb1)
    #10 0x1bc49a1 in do_cli (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1bc49a1)
    #11 0x1bc10c1 in main (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1bc10c1)
    #12 0x7fd345aada3f in __libc_start_main /build/buildd/glibc-2.21/csu/libc-start.c:289

previously allocated by thread T0 here:
    #0 0x4d62ac in __interceptor_malloc (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x4d62ac)
    #1 0x14d49db in _emalloc (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x14d49db)
    #2 0x129b84a in process_nested_data (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x129b84a)
    #3 0x129acbb in object_common2 (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x129acbb)
    #4 0x1292fa0 in php_var_unserialize (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1292fa0)
    #5 0x129b92e in process_nested_data (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x129b92e)
    #6 0x129acbb in object_common2 (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x129acbb)
    #7 0x1292fa0 in php_var_unserialize (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1292fa0)
    #8 0x1236b7b in zif_unserialize (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1236b7b)
    #9 0x1a7b631 in zend_do_fcall_common_helper_SPEC (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1a7b631)
    #10 0x185e984 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x185e984)
    #11 0x1755292 in execute_ex (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1755292)
    #12 0x1757996 in zend_execute (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1757996)
    #13 0x1605fa8 in zend_execute_scripts (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1605fa8)
    #14 0x1352fb1 in php_execute_script (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1352fb1)
    #15 0x1bc49a1 in do_cli (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1bc49a1)
    #16 0x1bc10c1 in main (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x1bc10c1)
    #17 0x7fd345aada3f in __libc_start_main /build/buildd/glibc-2.21/csu/libc-start.c:289

SUMMARY: AddressSanitizer: heap-use-after-free (/home/libfuzzer/php/php-src-php-5.6.25RC1/sapi/cli/php+0x158bbd9) in _zval_ptr_dtor
Shadow bytes around the buggy address:
  0x0c067fff81a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff81b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff81c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff81d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff81e0: fa fa fd fd fd fd fa fa fd fd fd fd fa fa fd fd
=>0x0c067fff81f0: fd fd fa fa fd fd[fd]fd fa fa fd fd fd fd fa fa
  0x0c067fff8200: 00 00 00 00 fa fa fd fd fd fd fa fa fd fd fd fd
  0x0c067fff8210: fa fa fd fd fd fd fa fa fd fd fd fd fa fa fd fd
  0x0c067fff8220: fd fd fa fa fd fd fd fd fa fa fd fd fd fd fa fa
  0x0c067fff8230: fd fd fd fd fa fa 00 00 00 00 fa fa 00 00 00 00
  0x0c067fff8240: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa 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 right 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
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==21365==ABORTING

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-08-16 21:19 UTC] stas@php.net
-Type: Security +Type: Bug -Assigned To: +Assigned To: laruence
 [2016-08-19 14:18 UTC] laruence@php.net
actually this is a knew issue, like:
<?php
class bad
{
    public function __construct() {
        $this->_private = array();
    }
    public function __destruct()
    {
        global $bar;
        $bar = $this;
        var_dump($this->_private);
    }
}
$foo = array();
$foo[] = &$foo;
$foo[] = new Bad;

unset($foo);
gc_collect_cycles();


?>

the problem here is, we don't know which zval's refcount is changed after an object's destructor is called in GC.

I don't see a good way to fix this.
 [2017-01-01 19:25 UTC] nikic@php.net
-Status: Assigned +Status: Duplicate
 [2017-01-01 19:25 UTC] nikic@php.net
Closing as duplicate of bug #64896 (which has been fixed in PHP 7.0).
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Thu Dec 02 18:03:35 2021 UTC