|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2015-10-14 16:38 UTC] stas@php.net
-Type: Security
+Type: Bug
[2020-06-10 11:01 UTC] nikic@php.net
-Status: Open
+Status: Verified
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Oct 28 22:00:01 2025 UTC |
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); ```