Fork me on GitHub
秋染蒹葭

做懂安全的前端之三:XXE攻击

现在越来越多主要的web程序被发现和报告存在XXE(XML External Entity attack)漏洞,比如说facebook、paypal等等。 举个例子,我们扫一眼这些网站最近奖励的漏洞,充分证实了前面的说法。尽管XXE漏洞已经存在了很多年,但是它从来没有获得它应得的关注度。很多XML的解析器默认是含有XXE漏洞的,这意味着开发人员有责任确保这些程序不受此漏洞的影响。

xml基础

要了解xxe漏洞,那么一定得先明白基础知识,了解xml文档的基础组成。

XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。

xml文档的构建模块

所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:

元素

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

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

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

属性

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

1
<img src="computer.gif" />

实体

实体是用来定义普通文本的变量。实体引用是对实体的引用。

PCDATA

PCDATA 的意思是被解析的字符数据(parsed character data)。
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。

CDATA

CDATA 的意思是字符数据(character data)。
CDATA 是不会被解析器解析的文本。

DTD(文档类型定义)

DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。

DTD 可以在 XML 文档内声明,也可以外部引用。

内部声明

eg:

1
<!DOCTYOE test any>

完整实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>

外部声明(引用外部DTD)

eg:

1
<!DOCTYPE test SYSTEM 'http://www.test.com/evil.dtd'>

完整实例:

1
2
3
4
5
6
7
8
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>

而note.dtd的内容为:

1
2
3
4
5
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

DTD实体

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

实体又分为一般实体和参数实体

  • 一般实体的声明语法:<!ENTITY 实体名 "实体内容“>
    引用实体的方式:&实体名;
  • 参数实体只能在DTD中使用,参数实体的声明格式: <!ENTITY % 实体名 "实体内容“>
    引用实体的方式:%实体名

内部实体声明

eg:

1
<!ENTITY eviltest "eviltest">

完整实例:

1
2
3
4
5
6
7
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "Copyright W3School.com.cn">
]>
<test>&writer;&copyright;</test>

外部实体声明

1
2
3
4
5
6
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
]>
<author>&writer;&copyright;</author>

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

xxe也就是xml外部实体注入。也就是上文中加粗的那一部分。

攻击方式

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

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

XML内容

DTD文件内容:

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

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

dtd文件内容:

支持的协议有哪些?

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

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

产生哪些危害?

XXE危害1:读取任意文件


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

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

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

XXE危害2:执行系统命令


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

XXE危害3:探测内网端口

该CASE是探测192.168.1.1的80、81端口,通过返回的“Connection refused”可以知道该81端口是closed的,而80端口是open的。

XXE危害4:攻击内网网站

该CASE是攻击内网struts2网站,远程执行系统命令。

防御XXE攻击

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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。

微信支付的案例

微信支付官方SDK被曝严重漏洞,目前还未修复

总结

无论是WEB程序,还是PC程序,只要处理用户可控的XML都可能存在危害极大的XXE漏洞,开发人员在处理XML时需谨慎,在用户可控的XML数据里禁止引用外部实体。

参考资料
未知攻焉知防——XXE漏洞攻防
XXE漏洞的学习与利用总结

本文标题:做懂安全的前端之三:XXE攻击

文章作者:zhyjor

发布时间:2018年07月04日 - 15:07

最后更新:2023年10月11日 - 02:10

原始链接:https://zhyjor.github.io/2018/07/04/做懂安全的前端之三:XXE攻击/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

🐶 您的支持将鼓励我继续创作 🐶

热评文章