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
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: vuln-report at secur3 dot us
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2025 The PHP Group
All rights reserved.
Last updated: Thu Apr 24 16:01:28 2025 UTC