php / php/php-src

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

未关闭
#23,352 0 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

@devnexen 已经在做这个了。

开始于 2026年8月18日。

  • #23358 来自 @devnexen —— 未关闭
Bug Extension: dom Status: Verified
主要语言
C
星标
40.4k
派生
8.2k
平均合并
2 天 13 小时
30 天内合并 PR
96

描述

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

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。