Facebook账户劫持漏洞及修复
因为可以窃取第一方的graphql用户token,所以针对受害者Facebook账户来说,完全可以在账户恢复功能中构造添加绑定新手机号的请求。由于该过程中,Facebook后端对GraphQL请求是白名单化且无任何权限验证的,因此,攻击者也就具备了对受害者Facebook账户中消息、照片、视频或隐私权设置的完全读写更改权限。
我及时向Facebook上报了该漏洞,Facebook官方也及时地确认了该漏洞的有效性,并立即进行了以下修复措施:
废弃“/connect/ping”服务端,并取消其对所有Facebook应用的用户access_token生成;
在XD_Arbiter文件中添加了__d(“JSSDKConfig”)代码行,避免在page_proxy中的JS构造执行。
绕过修复措施虽然我和Facebook都清楚OAuth的核心服务端“/dialog/oauth/”中,仍然存在携带用户token跳转到page_proxy的情况,而且在上述漏洞报告中我也提醒过他们需要进行修复。但是,Facebook在回复中声称xd_arbiter是白名单化的,上述修复措施足够缓解该漏洞问题,将不会导致用户token泄露。
之后,我在后续的两三天又再次检查了page_proxy中的代码,发现代码“__d(“JSSDKConfig”)”被移到了底部,而且代码的postMessage()调用仍然可以被执行,为此,我又想办法看看能否再次对其进行绕过。
但分析之后我发现,后端并没有遵循xd_arbiter的重定向状态,而是为客户端的请求域创建了closed_window 和 postMessage() 调用来防止攻击,此规则虽然对chrome浏览器的m版本(multi-install)、”mobile”和”touch”版本生效,但对firefox浏览器却无任何防护效果。
另外,在域名“mbasic.facbook.com”下也会发生HTTP 302跳转,且对所有浏览器有效,这就再次和之前的漏洞结合起来了:
最终修复措施
不允许对xd_arbiter的任意修改,只接受单纯的文件路径”xd_arbiter.php”;
禁用所有xd_arbiter上的HTTP跳转;
删除page_proxy资源“7SWBAvHenEn.js”;
在另外一个JS脚本资源中增加正则过滤验证。
漏洞影响攻击者利用该漏洞,部署控制恶意站点诱惑用户访问,当用户在使用Facebook的Oauth身份验证机制时,就能窃取用户的Facebook access token,实现对用户的Facebook或其它第三方账户劫持。
漏洞上报和修复进程2019.12.16 漏洞初报
2019.12.16 漏洞确认
2019.12.23 漏洞修复
2020.1.3 修复措施绕过
2020.1.10 后续漏洞再次被确认
2020.1.17 漏洞修复
2020.2.21 Facebook奖励$55,000(账户劫持的单个最高漏洞奖励)