Skip to content

ext/dom: UAF reading an attribute value node retained across DOMDocument::adoptNode() #23352

Description

@alexandre-daubois

Description

The following code:

<?php

$source = new DOMDocument();
$element = $source->appendChild($source->createElement('element'));
$element->setAttribute('attribute', 'victim');
$victim = $element->getAttributeNode('attribute')->firstChild;

$destination = new DOMDocument();
$destination->appendChild($destination->adoptNode($element));
unset($destination, $source, $element);

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. So that wrapper keeps referencing the source document while its native node has moved to the destination, and releasing the destination frees it.

Asan trace :

==43592==ERROR: AddressSanitizer: heap-use-after-free on address 0x60c000019cc8 at pc 0x0001011263e8 bp 0x00016ef54e70 sp 0x00016ef54e68
READ of size 4 at 0x60c000019cc8 thread T0
    #0 0x0001011263e4 in php_dom_get_content_into_zval php_dom.c:2360
    #1 0x0001010b0360 in dom_characterdata_data_read characterdata.c:58
    #2 0x0001010f8bbc in dom_read_property php_dom.c:395
    #3 0x000101bc2e20 in ZEND_FETCH_OBJ_R_SPEC_CV_CONST_TAILCALL_HANDLER zend_vm_execute.h:95143
    #4 0x0001019f17c8 in execute_ex zend_vm_execute.h:110551
    #5 0x0001019f1f24 in zend_execute zend_vm_execute.h:115989
    #6 0x000101da0a14 in zend_execute_script zend.c:1980
    #7 0x0001017b2d5c in php_execute_script_ex main.c:2589
    #8 0x000101da5df8 in do_cli php_cli.c:933
    #9 0x000101da3820 in do_php_cli php_cli.c:1346

0x60c000019cc8 is located 8 bytes inside of 120-byte region [0x60c000019cc0,0x60c000019d38)
freed by thread T0 here:
    #0 0x00010343d258 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 0x000100f31a14 in php_libxml_decrement_doc_ref_directly libxml.c:1395
    #6 0x000100f322cc in php_libxml_node_decrement_resource libxml.c:1471
    #7 0x00010111fe3c in dom_objects_free_storage php_dom.c:1497
    #8 0x000101d46578 in zend_objects_store_del zend_objects_API.c:193
    #9 0x000101c1d760 in ZEND_UNSET_CV_SPEC_CV_UNUSED_TAILCALL_HANDLER zend_vm_execute.h:102283
    #10 0x0001019f17c8 in execute_ex zend_vm_execute.h:110551
    #11 0x0001019f1f24 in zend_execute zend_vm_execute.h:115989
    #12 0x000101da0a14 in zend_execute_script zend.c:1980
    #13 0x0001017b2d5c in php_execute_script_ex main.c:2589

previously allocated by thread T0 here:
    #0 0x00010343d164 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 0x0001010c3fec in zim_DOMElement_setAttribute element.c:473
    #5 0x000101b99fc4 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_TAILCALL_HANDLER zend_vm_execute.h
    #6 0x0001019f17c8 in execute_ex zend_vm_execute.h:110551
    #7 0x0001019f1f24 in zend_execute zend_vm_execute.h:115989
    #8 0x000101da0a14 in zend_execute_script zend.c:1980
    #9 0x0001017b2d5c in php_execute_script_ex main.c:2589

SUMMARY: AddressSanitizer: heap-use-after-free php_dom.c:2360 in php_dom_get_content_into_zval

PHP Version

8.3-master

Operating System

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions