亚马逊EC2主机环境:挖掘Node/Express应用上的SSRF漏洞

0

20160112205850

笔者最近在挖某应用的漏洞时,恰好遇到了一个SSRF(Server Side Request Forgery)。该应用被托管在Amazon EC2上,项目里使用了Node.js和Express.js,后来我甚至还在上面发现了Needle.js。

手动发掘

在测试过程中,我注意到了该应用的某个函数。它会获取用户指定的URL,然后将该URL链接到的内容的第一段展示到当前页。这里讲一下,用户可以使用该应用分享一个URL给朋友们,这个小特性相当于预览文章的功能。

那么问题来了,当我查看Burp历史时,我找不到日志里指定的URL请求。我非常惊讶,因为这意味着服务器获取了我指定的URL,然后代我发请求,再返回结果给我,这儿恰巧有个SSRF。然而,最终我们还是看看风险点的确认。

自动化发掘

自2015年4月开始,如果你使用了Burp Collaborator,且把漏洞请求发送给主动扫描器,你应该就可以检测到SSRF。下图显示了几种Burp Collaborator甄别SSRF的不同方法(外部资源加载和扩展服务交互)。

攻击演示

我想证明该SSRF漏洞,但不能泄露关于该应用评测的详细信息。为了重现这个漏洞,我制作搭建了首个Node.js应用,关键是这玩意儿确实能用啊,应用地址如下:

https://github.com/sethsec/Nodejs-SSRF-App

我的demo应用托管在了Amazon EC2 micro instance上,在上面运行了Node.js,并且使用了Express.js和Needle.js。(这是SSRF请求的祸首)。

如真实环境那般,我的演示demo应用获取了用户指定的URL,然后由Needle.js发出请求。而真正的应用,则是通过检测请求包body里的JSON参数,从里面接收了用户指定的URL。然而我的Node代码水平有点着急,所以在演示时,我是通过GET请求发送数据的。

它看起来像个iframe,不是么?但如果它是个普通的iframe的话,你的浏览器会请求ethsec.blogspot.com,该应用就不会有SSRF漏洞了。

当我尝试用存在漏洞的服务器去请求ifconfig.pro(查IP和User_Agent的网站)时,就可以确认SSRF漏洞的存在了:

这里最有意思的点还是源IP和User_Agent,来自ifconfig.pro的响应结果展示了来自EC2的请求,特别是来自Node.js的HTTP客户端Needle的。

风险点的所在

如上所述,让漏洞服务器帮你发送一个请求,就可以取到一些你没有能力直接获取的东西。

访问Amazon EC2元数据服务

比如你的应用在Amazon EC2上跑着,你可以通过它查询169.254.169.254(外部主机不可达)上的元数据服务。这台服务器只能通过该实例自己才能访问,所有没有SSRF、命令注入或者其他类似的漏洞,你是没可能接触到这个服务的。

这只是元数据对象的一个例子,Erik Peterson (@silvexis)发现了更多可从元数据服务里挖掘出的敏感信息,他的演讲视频如下《Bringing a Machete to the Amazon》

比如,下面的请求就能让黑客临时获取admin权限的安全认证凭据,进而获取你的AWS资源。

访问你的Amazon EC2用户数据对象

另一个地方你可能也感兴趣,那就是用户数据容器,它位于http://169.254.169.254/latest/user-data,亚马逊给予了开发者警告:

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html instancedata-add-user-data

但我们都知道,如果存储某些密码和其他敏感信息在用户数据里很方便的话,大家都会这样做。所以你可以从这方面下手,下面是我的漏洞实验EC2的请求:

如果你有权限去查询EC2元数据服务,这里给你提供一个完整的列表,请看下面这篇文档:《Instance Metadata and User Data》

扫描和访问后端基础设施

除了检测元数据服务和用户数据外,你还应该利用SSRF寻找漏洞服务器所能直达的那些服务、主机和资源,而Burp Intruder对于这类攻击的实现非常有效。

Demo设置

为了设置demo,我又使用了一个EC2来跑kali,其内网IP为172.31.40.122并且监听8080端口,该主机上的WEB服务在公网是不可达的。事实上,它只有内网主机可达,也就是说我们需要SSRF去请求它的8080端口。

这里是EC2那台kali主机(172.31.40.122)的安全策略(上面运行了apache):

扫描端口(XSPA)

1.通过Burp发出初始请求,在这个案例中,我试图访问了TCP端口1。

2.发送初始请求到Burp Intruder。

3.设置payload位置(这里设定是端口)。

4.设置payload的内容,这个demo里我选择了连续的11个端口,但你可以设置nmap的前N个端口,或者常见的WEB服务端口。

5.启动攻击,你可以在下面的截图中看到。我们有一些法子可以推断哪些端口、哪些端口关闭。在这种情况下,你可以使用响应状态码或者响应包长度进行判断。

好吧,其实我这里只是为了证明172.31.40.122开着8080端口,而且正在运行WEB服务。

扫描主机

这里的步骤与上面的大概相同,只是这里不是把端口设定为payload,而是将想要扫描的IP地址制成一个列表。然后,用请求包里IP地址作为payload,固定请求80端口或者443端口进行扫描。

但是这里我就不扫描其他EC2的IP了,举个例子就行了。然而其实回到第四步,你会发现都差不多。

你可以使用Burp的Cluster Bomb选项,同时扫描端口和服务。

扫描内网WEB服务器

接下来,我将再次展示类似的流程。但这一次,我们要扫描的是服务器上的文件或者目录。

因为是演示嘛,所有我知道上面存在users.txt文件,所以直接把它放进了字典。当然,我还在里面填充了一些不相关的文件名,在实际场景中,你可能会使用如fuzzdb之类的资源。

如先前的例子那般,你可以通过匹配差异化的结果进行扫描。在这个例子中,所有的页面都会给你返回200的状态码。但是,访问user.txt的返回包长度比其他的都要短,这就是我们要寻找的差异化标志。

与上述的类似,你也可以用Cluster Bomb选项同时扫描多个WEB服务器的文件和目录。

修复建议

该应用需要检测用户输入的所有信息,而不是简单的直接去代理用户的请求。如果必须做代理的话,服务端应该做IP白名单,去除或者修改User-Agent信息。

额外的资源

这里有几个不错的SSRF资源,在我看来Nicolas Grégoire (@Agarri_FR)在SSRF或者XXE上做的很不错,你们可以看看他的演讲内容和博客。

最喜欢的演讲之一:《Nicolas Grégoire – Hunting for Top Bounties》

最喜欢的博文之一:《Compromising an unreachable Solr server with CVE-2013-6397》

我写这篇博文是因为刚提交了一份Mubix的CFDBSSRF漏洞,这里有些其中的细节。在关于CFDB的发现里,我加入了一些以前工作的内容链接和某些有用的资源。

鄙人认为CFDB是一个伟大的项目,它在我们这行有着重大意义,急需我们做出贡献。

最终的想法

与客户端漏洞XSS和CSRF不同,SSRF可以访问后端不可直达的基础设施。如果你找到了这类漏洞,记得要去证明它的风险。

欢迎对本文指出批评,读者的反馈和鼓励是我最大的荣幸。

头像

Focus On The Network Information Security.

作者主页 邮箱 微博 腾讯微博 QQ Twitter Facebook Google+

发表评论

您的邮箱不会公开,当您的评论有新的回复时,会通过您填写的邮箱向您发送评论内容。 必填字段 *

返回顶部