php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #74103 heap-use-after-free when unserializing invalid array size
Submitted: 2017-02-15 19:06 UTC Modified: 2017-08-18 17:18 UTC
From: cyoung at tripwire dot com Assigned: nikic (profile)
Status: Closed Package: *Data Exchange functions
PHP Version: 7.1.2RC1 OS: Linux (4.4.0-59-generic)
Private report: No CVE-ID: 2017-12932
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: cyoung at tripwire dot com
New email:
PHP Version: OS:

 

 [2017-02-15 19:06 UTC] cyoung at tripwire dot com
Description:
------------
Fuzzing var_dump(unserialize(<<data>>)) with various instrumentations and USE_ZEND_ALLOC=0 has revealed a possible security flaw in PHP.
From ASAN:
==14786==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000024855 at pc 0x0000015fad75 bp 0x7ffefa744310 sp 0x7ffefa744308
READ of size 1 at 0x603000024855 thread T0
    #0 0x15fad74 in zend_string_release /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_string.h:270:7
    #1 0x15fad74 in zend_array_destroy /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_hash.c:1312
    #2 0x1591132 in _zval_dtor_func /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_variables.c:43:5
    #3 0x1546489 in i_zval_ptr_dtor /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_variables.h:48:4
    #4 0x1546489 in _zval_ptr_dtor /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_execute_API.c:550
    #5 0x133d550 in var_destroy /home/cyoung/php/afl/php-src-php-7.1.2RC1/ext/standard/var_unserializer.re:233:4
    #6 0x133cd61 in php_var_unserialize_destroy /home/cyoung/php/afl/php-src-php-7.1.2RC1/ext/standard/var_unserializer.re:52:3
    #7 0x13016c4 in zif_unserialize /home/cyoung/php/afl/php-src-php-7.1.2RC1/ext/standard/var.c:1131:2
    #8 0x1831ce2 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_vm_execute.h:675:2
    #9 0x16eeff5 in execute_ex /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_vm_execute.h:432:7
    #10 0x16efda6 in zend_execute /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_vm_execute.h:474:2
    #11 0x15519cd in zend_eval_stringl /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_execute_API.c:1093:4
    #12 0x1552343 in zend_eval_stringl_ex /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_execute_API.c:1134:11
    #13 0x1552343 in zend_eval_string_ex /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_execute_API.c:1145
    #14 0x193b0aa in do_cli /home/cyoung/php/afl/php-src-php-7.1.2RC1/sapi/cli/php_cli.c:1024:8
    #15 0x1938dd4 in main /home/cyoung/php/afl/php-src-php-7.1.2RC1/sapi/cli/php_cli.c:1381:18
    #16 0x7ff566fd682f in __libc_start_main /build/glibc-t3gR2i/glibc-2.23/csu/../csu/libc-start.c:291
    #17 0x4809c8 in _start (/home/cyoung/php/afl/php-src-php-7.1.2RC1/sapi/cli/php+0x4809c8)

0x603000024855 is located 5 bytes inside of 32-byte region [0x603000024850,0x603000024870)
freed by thread T0 here:
    #0 0x5076b2 in free (/home/cyoung/php/afl/php-src-php-7.1.2RC1/sapi/cli/php+0x5076b2)
    #1 0x14af197 in _efree /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_alloc.c:2428:4

previously allocated by thread T0 here:
    #0 0x507992 in __interceptor_malloc (/home/cyoung/php/afl/php-src-php-7.1.2RC1/sapi/cli/php+0x507992)
    #1 0x14b03ca in __zend_malloc /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_alloc.c:2820:14
    #2 0x1342e0b in process_nested_data /home/cyoung/php/afl/php-src-php-7.1.2RC1/ext/standard/var_unserializer.re:396:8
    #3 0x1342e0b in php_var_unserialize_internal /home/cyoung/php/afl/php-src-php-7.1.2RC1/ext/standard/var_unserializer.re:822
    #4 0x133e3ba in php_var_unserialize /home/cyoung/php/afl/php-src-php-7.1.2RC1/ext/standard/var_unserializer.re:584:11
    #5 0x1831ce2 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_vm_execute.h:675:2

SUMMARY: AddressSanitizer: heap-use-after-free /home/cyoung/php/afl/php-src-php-7.1.2RC1/Zend/zend_string.h:270 zend_string_release
Shadow bytes around the buggy address:
  0x0c067fffc8b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffc8c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffc8d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffc8e0: fa fa fa fa fa fa fa fa fa fa fa fa 00 00 02 fa
  0x0c067fffc8f0: fa fa fd fd fd fd fa fa fd fd fd fd fa fa fd fd
=>0x0c067fffc900: fd fd fa fa fd fd fd fd fa fa[fd]fd fd fd fa fa
  0x0c067fffc910: fd fd fd fa fa fa 00 00 00 fa fa fa 00 00 00 00
  0x0c067fffc920: fa fa 00 00 00 fa fa fa 00 00 00 00 fa fa 00 00
  0x0c067fffc930: 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa
  0x0c067fffc940: 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00 00 fa
  0x0c067fffc950: fa fa 00 00 00 fa fa fa 00 00 00 fa 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
==14786==ABORTING

From a partially MSAN instrumented PHP CLI:
==14802==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x5636d9634089 in zend_array_destroy (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x20b3089)
    #1 0x5636d94f43d4 in _zval_dtor_func (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x1f733d4)
    #2 0x5636d94276db in _zval_ptr_dtor (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x1ea66db)
    #3 0x5636d8f7eeff in var_destroy (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x19fdeff)
    #4 0x5636d8f7d9a1 in php_var_unserialize_destroy (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x19fc9a1)
    #5 0x5636d8ec42b0 in zif_unserialize (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x19432b0)
    #6 0x5636d9d4b367 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x27ca367)
    #7 0x5636d98c4bbb in execute_ex (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x2343bbb)
    #8 0x5636d98c869e in zend_execute (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x234769e)
    #9 0x5636d9441c0e in zend_eval_stringl (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x1ec0c0e)
    #10 0x5636d9442718 in zend_eval_stringl_ex (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x1ec1718)
    #11 0x5636d94429a8 in zend_eval_string_ex (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x1ec19a8)
    #12 0x5636da1042e5 in do_cli (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x2b832e5)
    #13 0x5636da0fec9b in main (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x2b7dc9b)
    #14 0x7f4df5c0382f in __libc_start_main /build/glibc-t3gR2i/glibc-2.23/csu/../csu/libc-start.c:291
    #15 0x5636d7679658 in _start (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0xf8658)

SUMMARY: MemorySanitizer: use-of-uninitialized-value (/home/cyoung/php/MSAN/php-src-php-7.1.2RC1/sapi/cli/php+0x20b3089) in zend_array_destroy

Test script:
---------------
<?php
unserialize('a:7:{i:0;i:04;s:1:"a";i:2;i:00009617006;i:4;s:1:"a";i:4;s:1:"a";R:5;s:1:"7";R:3;s:1:"a";R:5;;s:18;}}');
?>


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-02-20 11:46 UTC] laruence@php.net
USE_ZEND_ALLOC=0 is usually used for debug purpose..
 [2017-02-20 15:22 UTC] cyoung at tripwire dot com
I understand that USE_ZEND_ALLOC=0 is intended for debugging.  I am using this option to disable the ZEND allocator so that I can instead use the instrumentation provided by ASAN which is able to catch memory safety issues that might not cause a crash otherwise.  It is my understanding that many of the security bugs found in PHP through fuzzing are identified with this option.  Hanno Böck notes it here: https://fuzzing-project.org/tutorial-tips.html 

There are also many other bug reports in PHP where this option is referenced.  As some examples from a Google search:
https://bugs.php.net/bug.php?id=71527
https://bugs.php.net/bug.php?id=72227
https://bugs.php.net/bug.php?id=72241
https://bugs.php.net/bug.php?id=73825
 [2017-07-02 20:39 UTC] stas@php.net
-Summary: heap-use-after-free zend_string.h:270 zend_string_release (READ of 1) +Summary: heap-use-after-free when unserializing invalid array size
 [2017-07-07 21:15 UTC] nikic@php.net
I believe this has been introduced by https://github.com/php/php-src/commit/fd545f4f44ff44bba9f75ae3f044dc2ba9c61083, which is a followup to https://github.com/php/php-src/commit/91fb1edbbffe106d02929fe554ecbd1e5e33f5d1. zend_hash_index_del in unserialize is a very bad idea :/
 [2017-08-12 11:43 UTC] nikic@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: nikic
 [2017-08-14 13:16 UTC] cyoung at tripwire dot com
Can someone assign a CVE to this issue?
 [2017-08-18 11:11 UTC] henri at nerv dot fi
Please use CVE-2017-12932 for this issue.
 [2017-08-18 17:18 UTC] kaplan@php.net
-CVE-ID: +CVE-ID: 2017-12932
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 10:01:29 2024 UTC