XXE漏洞——XML实体定义引起的兼容性问题

XXE漏洞——XML实体定义引起的兼容性问题


一、XML基础知识

XML指可扩展的标记语言(Extensible Markup Language),类似于HTML(超文本标记语言);

XML被设计用来结构化、存储以及传输信息,其焦点是数据的内容;

XML没有任何预定义的标签,所有标签均由开发者自定义,开发者可以依据需要定制与业务匹配的结构化标签;

XML是对HTML的补充,在大多数WEB应用中,XML用于传输数据,HTML用于格式化并显示数据(XML是独立于软件和硬件的信息传输工具);

XML文档结构树包括XML声明、DTD文档类型定义(可选)、文档元素,这种树结构必须包含根节点,该节点是所有其他元素的父元素。

<?xml version="1.0" encoding="UTF-8"?><!--XML声明-->
<!--文档类型定义-->
<!DOCTYPE book [
    <!ELEMENT book (bId, bName)>
    <!ELEMENT bId (#PCDATA)>
    <!ELEMENT bName (#PCDATA)>
]>
<!--文档元素-->
<books>
    <book>
        <bId>1</bId>
        <bName>Java编程思想</bName>
    </book>
    <book>
        <bId>2</bId>
        <bName>Python实战</bName>
    </book>
</books>

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

内部声明DTD

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

引用外部DTD

<!DOCTYPE 根元素 SYSTEM "文件名">

or

<!DOCTYPE 根元素 PUBLIC "PUBLIC_ID" "文件名">

内部声明实体

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

引用外部实体

<!ENTITY 实体名称 SYSTEM "URI“>

or

<!ENTITY 实体名称 PUBLIC "PUBLIC_ID" "URI">

二、XML外部实体注入(XML External Entity)

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

引用外部实体的方式有多种,比如下面这种引用方式可以读取任意文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book [
    <!ENTITY book SYSTEM "F:///etc/passwd">
]>
<books>
    <book>
        <bId>1</bId>
        <bName>&book;</bName>
    </book>
</books>

实体注入除了可以读取文件之外,还可以将文件内容发送到攻击者网站、执行系统命令、探测内网端口、攻击内网网站等。

三、防御XXE攻击

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

Java:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

dbf.setExpandEntityReferences(true);

Python:

from lxml import etree

xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
 

方案二:过滤用户提交的XML数据

关键词:<!DOCTYPE、<!ENTITI、SYSTEM、PUBLIC等

四、在浏览器中的体现

使用XML传输数据时,当数据中含有实体时,需要在文档定义中声明实体XML解析器才能正确的解析数据。

当数据中可能出现实体时,需要在文档声明中定义好实体内容;

这种处理比较简便,在大多数浏览器中也都可以正确解析数据,然而如果需要支持低版本的浏览器,那么这样处理去含有实体定义的XML数据就显得有点危险了。

例如,在IE9、IE8上,当浏览器试着去解析一个含有实体定义的XML数据时,由于该浏览器内部会将定义的实体当作实体注入攻击,因此数据解析遇到实体定义时,浏览器直接抛出异常。

解决方案:

方案一:

更换高版本浏览器,高版本浏览器不会对内部实体定义做处理。

方案二:

改用其他方式传输数据,如JSON。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值