2020年3月1日,漏洞赏金猎人Amol Baikar在其博客公布了一个Facebook OAuth框架权限绕过的漏洞。
关于Facebook OAuth漏洞,作者声称获取了赏金55000美元,按照当日的美元汇率计算,奖金金额达38万元人民币之多。那么这个漏洞是如何形成的呢?下面就带着读者来一探究竟。
漏洞类型: API2-失效的用户认证。
漏洞难度: 高。
报告日期: 2019-12-16。
信息来源: https://www.amolbaikar.com/facebook-oauth-framework-vulnerability。
Facebook登录功能 遵循OAuth 2.0授权协议,第三方网站(Instagram、Oculus、Netflix等)使用Facebook账号认证通过后获取访问令牌access_token来访问获得用户授权许可的资源信息 。恶意攻击者通过技术手段劫持OAuth授权流程,窃取应用程序的access_token,从而达到接管用户账号的目的。其攻击过程如图3-1所示。
●图3-1 Facebook OAuth绕过漏洞攻击示意图
Facebook网站和国内的社交应用腾讯、微信、微博一样,提供第三方集成授权功能。正常情况下,Facebook第三方应用OAuth授权流程中,其中获取用户访问令牌access_token的URL请求格式如下:
上述URL链接中,参数APP_ID为第三方应用在Facebook注册时生成的应用ID值, /connect/ping为Facebook提供给第三方应用获取用户访问令牌access_token的API端点 ,这是在大多数互联网平台OAuth认证时都需要提供的功能。Facebook为开发者提供JavaScript SDK作为接入方式,接入时,开发者通过编码在后台创建跨域通信的代理iframe,再使用window.postMessage() 收发令牌。
模拟攻击者在测试中发现,此链接中跳转地址xd_arbiter.php?v=42的值可以被篡改,可以通过 篡改来添加更多路径和参数 ,比如修改为xd_arbiter/?v=42,而且xd_arbiter也是请求的白名单路径。通过这样的方式,可以获取访问令牌的hash值。但若想获取可读写的访问令牌值,最好是借助于postMessage()将消息传送出来。而恰好在staticxx.facebook.com域名下,存在了提供上述代码功能的JavaScript文件,于是模拟攻击者利用了这个链接构造出登录的URL。原链接如下:
构造出来的登录链接格式如下所示(其中124024574287414是instagram的app_id):
最后,Amol Baikar定制了Facebook JavaScript SDK,其关键代码如下:
运行之后,可以在受害者不知情的情况下获取access_token。漏洞在上报后,很快得到了Facebook的响应,并修复了漏洞。
下面再来回顾一下整个攻击过程,如图3-2所示。
●图3-2 OAuth绕过攻击过程
在此次攻击成功的路径上, 可修改xd_arbiter是第一个关键点 ,提供 代理劫持框架的7SWBAvHenEn.js是第二个关键点 。有了第一个关键点,攻击者才能伪造可执行路径,将7SWBAvHenEn.js加入进来。7SWBAvHenEn.js文件在攻击中充当了攻击武器,本来有第一个关键点攻击者即可找到攻击方向,但炮弹精准度不足,7SWBAvHenEn.js文件所提供的功能加速了攻击者完成攻击的速度。同时,在网媒报道中,也提到了“即使用户更改了Facebook账号密码,令牌仍然有效”,这是导致账号权限被接管的主要原因。
作为防守方,如果仅仅使用URL白名单来防御往往是不够的。尤其是复杂的应用程序中,在面对跨域通信,PC端、手机端、移动平板等不同类型设备的多端接入提供多个接入点的情况下。而且还要考虑不同浏览器、同一浏览器不同版本的复杂情况下,即使使用X-Frame-Options来防止跨域但也要考虑其兼容性问题。通过这个案例,也给开发人员提了个醒。在做某个程序设计时,在实现功能的前提下,尽可能遵循简单原则,参考标准的协议实现流程。对线上环境中不使用的文件,尽快清除。