Description
The following code:
<?php
$source = new DOMDocument('1.0', 'UTF-8');
$root = $source->createElement('root');
$source->appendChild($root);
$first = $source->createElement('first');
$first->appendChild($source->createTextNode('first'));
$root->appendChild($first);
$later = $source->createElement('later');
$victim = $source->createTextNode('victim');
$later->appendChild($victim);
$root->appendChild($later);
$destination = new DOMDocument('1.0', 'UTF-8');
$destination->appendChild($destination->adoptNode($root));
unset($destination, $root, $first, $later);
gc_collect_cycles();
echo $victim->data, "\n";
Produces a UAF.
When a subtree is adopted into another document, php_dom_transfer_document_ref() updates the document reference of every live PHP wrapper in that subtree, but it visits only the xmlAttr
nodes and never the value nodes under attr->children.
It is already fixed in 8.5 and above by c77a129.
ASan trace:
==35309==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c000019c08 at pc 0x000104ca23e8 bp 0x00016b3d9510 sp 0x00016b3d9508
READ of size 4 at 0x60c000019c08 thread T0
#0 0x000104ca23e4 in php_dom_get_content_into_zval php_dom.c:2360
#1 0x000104c2c360 in dom_characterdata_data_read characterdata.c:58
#2 0x000104c74bbc in dom_read_property php_dom.c:395
#3 0x00010573ee20 in ZEND_FETCH_OBJ_R_SPEC_CV_CONST_TAILCALL_HANDLER zend_vm_execute.h:95143
#4 0x00010556d7c8 in execute_ex zend_vm_execute.h:110551
#5 0x00010556df24 in zend_execute zend_vm_execute.h:115989
#6 0x00010591ca14 in zend_execute_script zend.c:1980
#7 0x00010532ed5c in php_execute_script_ex main.c:2589
#8 0x000105921df8 in do_cli php_cli.c:933
#9 0x00010591f820 in do_php_cli php_cli.c:1346
#10 0x0001864504e0 in start+0x1b4c (dyld:arm64e+0x204e0)
0x60c000019c08 is located 8 bytes inside of 120-byte region [0x60c000019c00,0x60c000019c78)
freed by thread T0 here:
#0 0x0001070dd258 in free+0x7c (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x41258)
#1 0x000191105048 in xmlFreeNodeList+0x1e4 (libxml2.2.dylib:arm64e+0x11048)
#2 0x000191105120 in xmlFreeProp+0x80 (libxml2.2.dylib:arm64e+0x11120)
#3 0x000191104fc0 in xmlFreeNodeList+0x15c (libxml2.2.dylib:arm64e+0x10fc0)
#4 0x000191104a50 in xmlFreeDoc+0xac (libxml2.2.dylib:arm64e+0x10a50)
#5 0x000104aada14 in php_libxml_decrement_doc_ref_directly libxml.c:1395
#6 0x000104aae2cc in php_libxml_node_decrement_resource libxml.c:1471
#7 0x000104c9be3c in dom_objects_free_storage php_dom.c:1497
#8 0x0001058c2578 in zend_objects_store_del zend_objects_API.c:193
#9 0x000105799760 in ZEND_UNSET_CV_SPEC_CV_UNUSED_TAILCALL_HANDLER zend_vm_execute.h:102283
#10 0x00010556d7c8 in execute_ex zend_vm_execute.h:110551
#11 0x00010556df24 in zend_execute zend_vm_execute.h:115989
#12 0x00010591ca14 in zend_execute_script zend.c:1980
#13 0x00010532ed5c in php_execute_script_ex main.c:2589
#14 0x000105921df8 in do_cli php_cli.c:933
#15 0x00010591f820 in do_php_cli php_cli.c:1346
#16 0x0001864504e0 in start+0x1b4c (dyld:arm64e+0x204e0)
previously allocated by thread T0 here:
#0 0x0001070dd164 in malloc+0x78 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x41164)
#1 0x00018662b6a4 in _malloc_type_malloc_outlined+0x40 (libsystem_malloc.dylib:arm64e+0x1e6a4)
#2 0x000191157fb4 in xmlNewText+0x28 (libxml2.2.dylib:arm64e+0x63fb4)
#3 0x000191102b44 in xmlNewPropInternal+0x140 (libxml2.2.dylib:arm64e+0xeb44)
#4 0x000104c3ffec in zim_DOMElement_setAttribute element.c:473
#5 0x000105715fc4 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_TAILCALL_HANDLER zend_vm_execute.h
#6 0x00010556d7c8 in execute_ex zend_vm_execute.h:110551
#7 0x00010556df24 in zend_execute zend_vm_execute.h:115989
#8 0x00010591ca14 in zend_execute_script zend.c:1980
#9 0x00010532ed5c in php_execute_script_ex main.c:2589
#10 0x000105921df8 in do_cli php_cli.c:933
#11 0x00010591f820 in do_php_cli php_cli.c:1346
#12 0x0001864504e0 in start+0x1b4c (dyld:arm64e+0x204e0)
SUMMARY: AddressSanitizer: heap-use-after-free php_dom.c:2360 in php_dom_get_content_into_zval
PHP Version
Operating System
No response
Description
The following code:
Produces a UAF.
When a subtree is adopted into another document,
php_dom_transfer_document_ref()updates the document reference of every live PHP wrapper in that subtree, but it visits only thexmlAttrnodes and never the value nodes under
attr->children.It is already fixed in 8.5 and above by c77a129.
ASan trace:
PHP Version
Operating System
No response