今年3月份时,我曾上报过Google的任意html/javascript网页在线嵌入工具Caja的一个XSS漏洞,到5月份时,这个漏洞才被修复。之后,我想看看谷歌协作平台(Google Sites)网站调用的Caja服务是否还存在这个未修复漏洞。于是,对Google Sites进行了一番测试,可惜这个Caja XSS漏洞是不存在的,但经过其它方向的深入测试,我发现了Google内部生产网络的SSRF漏洞。
背景介绍
Google Sites:谷歌协作平台是一款在线协作编辑工具,它可以帮助企业创建企业内网、项目管理跟踪、外延网、以及其它类型的定制网站。用户可以通过Google Sites将所有类型的文件包括文档、视频、图片、日历等与好友、团队或整个网络分享。
Google Caja服务会解析html/javascript文件,并会消除掉其中像iframe、object对像标记和document.cookie等敏感javascript内容,起到安全过滤作用。通常,Caja服务主要针对客户端的HTML标记进行解析和安全过滤,但是,对于一些类似的远程调用javascript标记来说,远程资源的获取、解析和过滤是在服务端进行的。
端倪发现
我曾试图在我的自架服务器上托管了一个javascript文件,像这样https://[attacker].com/script.js,之后把它嵌入到一个远程调用标记中,以此来测试 Google Sites 服务端的XSS漏洞,但可惜Google Sites 服务端的响应显示,https://[attacker].com/script.js无法访问。
经过几多测试,我才意识到Google Sites中的Caja服务只会调用谷歌自身的资源文件,就像https://www.google.com 或 https://www.gstatic.com 网站托管的文件才行,但像https://www.facebook.com 这样的外部资源就不行啦。
这就有点奇怪了,因为Caja服务远程调用功能本来就是可以获取到任何外部资源的啊,这种设置看起来就像一个被破坏的功能。更有意思的是,由于谷歌的服务网站非常之多,要确定某个外调URL链接是否属于谷歌,还是有些难度的。除非……
发现Google的SSRF漏洞
每当我能通过服务端应用获取到任意内容时,我都会顺便测试一下SSRF漏洞。针对Google的应用服务,我做过好多SSRF测试,但没有一次是成功的。对Google Caja服务端怪异行为的解释,唯一的可能就是,Caja的链接提取动作发生在Google内部网络的,而且Google只能调用提取自身的资源文件消息,而其它的外部资源文件就不行。这从逻辑上来说,可以算是一个bug,现在的问题是,它是否算得上一个安全漏洞!
在Google服务器上托管和运行任意代码非常容易,例如使用Google云服务啊!于是,我创建了一个Google App Engine应用实例,并在上面托管了一个javascript文件。然后,我将这个javascript文件的URL链接,作为外部资源引用链接在我的Google Sites页面上作了配置。之后,Google Caja服务端成功获取并解析了该javascript文件。据此,我查看了我的Google App Engine实例日志,看看这个外部资源链接到底是谁来请求它的,啊哈,出现了一个IP地址:10.x.x.201,这明显是一个内部网络IP地址啊!有点希望了!
那么,我用包含这个Google内部网络的IP地址作为Google Sites页面的javascript调用外链会产生什么效果呢?试试吧,一起来静待真相。但在请求之后快半分钟了,还是没啥反应,我都觉得是不是请求被拦截了,就快要把页面关闭了。但是,当我查看 Google Caja 服务的响应时,却发现其响应数据并不象通常的1KB左右的典型错误消息,而是有1MB容量的内容!这些1MB的响应消息是来自Google内部网络的某IP地址 10.x.x.x,此时,我是相当的兴奋!打开这个1MB文件,我发现其中包含了很多Google内部网络系统的敏感信息!
利用SSRF漏洞获取到的Google内部信息
首先,我想说的是,我并没有对Google内部网络进行过探测扫描,我只是对其内网测试了3个请求就确定了该SSRF漏洞,并马上上报给了谷歌的漏洞团队VRP,48小时之后,Google团队修复了该漏洞。在此之前,我也好奇心强烈地创建了其它2到3个请求,想看看能否基于该SSRF漏洞,深入利用发现其它的未限制文件访问或RCE漏洞,但可惜最后都没有。
我创建的第一个请求是发向 的,它响应了一个 “Borglet” 的服务器状态监控页面。我对此进行了一些Google查询,发现这是Google内部的大规模集群管理系统Borg。经历多种架构演变,Google曾在2014年开源了 Borg的继任系统Kubernetes,虽然Kubernetes越来越受欢迎,但谷歌内部的生产网络架构仍然严重依赖Borg系统。Borg单元由一组机器,一个称为Borgmaster的逻辑中央控制器和单元中每台机器上运行的称之为Borglet的代理进程构成。

我创建的第二个请求是发向 的,它响应了另一个 “Borglet” 服务器状态监控页面,我创建的第三个请求则是 ,它的响应主体也是一个 “Borglet” 服务器状态监控页面,但其中包含了很多进程任务的权限和参数等详细信息。
每个Borglet代表一台服务器,从硬件方面来说,10.x.x.1 和 10.x.x.201 这两台服务器都使用了英特尔第四代架构的Haswell 2.30GHz 72内核CPU,相当于一组2到3个Xeon E5 v3 CPU处理器。这两台服务器都使用了 77%的CPU,它们具备250 GB内存,使用量达 70%。它们的硬盘容量都是2TB硬盘,且每台硬盘容量几乎都是空的,只有15个G的使用占有空间。所以,重要数据可能存储在其它地方。

服务器中的处理进程非常多样化,我想这种方式可能是一种资源优化手段吧,有些进程在使用着内存,其它的可能在用CPU、网络等,有一些则具备高优先权,等等…。还有一些服务看似非常活跃:如视频编码、Gmail和广告等。这也并不奇怪,因为视频处理非常繁重,Gmail是谷歌的主要服务之一,而广告是谷歌的核心业务。
我没有在服务器任务列表信息中看到Google Sites 或 Caja服务,所以要成功形成SSRF漏洞,要么是通过一个代理,或是 10.x.x.201 服务器上的,有别于我在Google App Engine实例日志中的,其它网络环境下的一个Borglet来形成的。

在架构方面,我们可以发现很多Google系统栈相关的元素,特别是 MapReduce, BitTable, Flume, GFS…等。在技术方面,Java使用频率较高,我没发现任何关于Python、c++、NodeJS或Go语言的提及,但这也并不意味着Google没使用这些编程语言,不能定论。
我想说的是, Borg 和 Kubernetes 一样都依赖Docker 和 VM虚拟机这样的容器技术。另外,在视频处理方面,Google使用的是其开源工具Gvisor,Gvisor貌似能在容器运行和虚拟机安全方面表面不错。
从SSRF漏洞获取的参数中,有着网络端口到应用程序映射信息。在Borg系统中,貌似每个服务器上的所有应用程序都共享相同的IP地址,且每个应用程序都有一些专用的端口。
对我来说,全是代码的应用程序参数是最有意思的部份。我虽然没能发现神秘的Google搜索排名算法原理,但是我发现了如下一些有趣的查询:
MSCR(M(Customer.AdGroupCriterion+Customer.AdGroupCriterion-marshal+FilterDurianAdGroupCriterion+FilterNeedReviewAdGroupCriterion+GroupAdGroupCriterionByAdGroupKey+JoinAdGroupData/MakeUnionTable:3)+M(JoinAdGroupData/MakeUnionTable:2)+M(Customer.AdGroup+Customer.AdGroup-marshal+FilterDurianAdGroup+ParDo(AdGroupDataStripFieldsFn)+JoinAdGroupData/MakeUnionTable)+R(JoinAdGroupData/GroupUnionTables+JoinAdGroupData/ConstructJoinResults+JoinAdGroupData/ExtractTuples+ExtractCreativeAndKeywordReviewables))
你可能会想,Gmail的系统用户是什么呢?它是:
gmail@prod.google.com
还有一个名为 “legal-discovery@prod.google.com” 的用户,据我推测,它具备针对 “mdb:all-person-users” 用户的 “auth.impersonation.impersonateNormalUser”权限。
在我的测试中,大部份任务还没完成就被无故终止执行了。最后,还存在大量指向其它Google服务器和应用服务端的URL链接,特别是,当我尝试去访问一个很有可能的 链接时,竟然没成功。于是乎,我在该服务上测试了以下链接:
/getFileFileName=/sys/borglet/borglet.INFO
Google VRP 安全团队的响应
我于2018年5月12日星期六上报了这个漏洞,它被Google自动分类为P3中等优先级问题。在星期天,我又向Google 安全团队发送了一封漏洞邮件,希望对方能有所响应。星期一一大早,该漏洞就被提升为P0(高危)级,之后又被降为 P1 级,星期一晚上,漏洞就得到了修复,相关漏洞服务端被删除。
确定SSRF漏洞的影响危害非常不易,因为这要看内部网络的实际情况而定。Google倾向于让其大部分基础架构在内部可用,与此同时,使用了大量web应用端,这就意味着,如果发生SSRF漏洞,攻击者可能会间接访问到数百甚至数千个内部web应用程序。但另一方面,Google严重依赖认证来实现资源访问,这种手段某种程度上也限制了SSRF漏洞的威胁。
但在Google的认证手段下,Borglet状态监控页面未经身份验证,就泄露了很多关于内部网络的基础设施信息。但据我了解,Kubernetes系统的这种状态监控页而是要经身份验证的。
最终,Google安全团队奖励了我 $13,337美金,这相当于未授权文件访问级别的高危漏洞了。Google对该奖励的解释是,虽然其大多数内部资源需要身份验证,但他们发现很多内部开发项目或调试处理程序,可以被攻击者利用的不仅是信息泄露问题,因此他们决定奖励这种存在严重潜在影响的漏洞。感谢Google的慷慨赏金和快速反应。