【API安全漏洞剖析】 FaceBook OAuth 漏洞 - 2020-03-01
【API安全漏洞剖析】 FaceBook OAuth 漏洞 - 2020-03-01
信息来源: https://www.amolbaikar.com/facebook-oauth-framework-vulnerability/
漏洞描述
第三方网站如(Instagram)是可以通过 Facebook 账号进行登录的, 具体登录逻辑就是利用 Facebook 提供的 SDK,使用 OAuth 授权进行登录。
具体来说就是用户登录 ins, 然后 ins 会根据 FaceBook 的 SDK 规范, 跳转到 Facebook 对应的登录页面, Facebook 登录完成之后, 返回一个 access_token 给 ins, 完成登录。
黑客在这个 OAuth 授权流程能够窃取 access_token ,从而达到接管用户账号的目的。
漏洞成因
 在 Facebook 提供给开发者接入的 SDK 中, 有一个名为 “/connect/ping” 的登录服务端, 它是提供给第三方应用获取用户访问令牌的第三方端点, 具体逻辑是开发者通过编码在后台创建跨域通信的代理 iframe , 再使用 window.postMessage() 方法接收令牌, 在接收令牌后, 该 API 会把链接跳转指向 Facebook 的 “XD_Arbiter” 下。 完整的 URL 为(以 ins 为例):
| 1 | https://www.facebook.com/connect/ping?client_id=APP_ID&redirect_uri=https://staticxx.facebook.com/connect/xd_arbiter.php?version=42#origin=https://www.instagram.com | 
 这里的 APP_ID 是第三方应用在 Facebook 注册时生成的应用 ID 值。
 攻击者发现这里的 xd_arbiter.php?version=42 可以被篡改成 xd_arbiter/?version=42 , 然后在此基础下, 能够将目录附加到后面实现资源访问。
在这里由于通过上述目录获取到的 access_token 的相关值都是哈希片段, 很难去还原, 但是攻击者在 page_proxy 目录中发现了一个名为 7SWBAvHenEn.js 的 js 文件, 这个文件中包含如下内容:
| 1 | var frameName = window.location.href.split("#")[1]; | 
第一行代码会获取 URL 请求参数中 # 后面的内容, 将它赋值给 frameName , 然后调用 window.parent.postMessage 转发来自 frameName 发送的内容, 这里的 * 代表他可以接收任意源的请求。
然后攻击者构造 URL 为:
| 1 | https://staticxx.facebook.com/connect/xd_arbiter/r/7SWBAvHenEn.js?version=42 | 
就可以穿越访问到这个文件, 再通过 # 去指定源, 就可以拦截该源发送回来的 access_token .
这个 js 文件能够被攻击者利用, 原因如下:
- 攻击者能够通过资源附加访问到这个文件.
- postMessage()方法会发送未加密的令牌.
- *允许了攻击者能在自己的源 ip 下请求并获取响应.
- API 请求中没有验证 X-Frame-Options标题,导致能够在xd_arbiter中嵌入跨域嵌套postMessage()回显的窗口.
- window.parent下的方法不用与用户交互, 不需要关心- window.open或任何- onClick事件.
漏洞劫持
最后攻击者重写 Custom_SDK.js
| 1 | var app_id = '124024574287414', | 
实现跨域攻击, 接管账户.
启示
作为防守方, 仅仅使用 URL 白名单来防御是不够的, 在面对跨域通信, 不同设备甚至浏览器的情况下, 即使使用了 X-Frame-Options 来防止跨域请求, 也有可能会因为兼容性问题产生漏洞.
在这里的启示就是, 应用设计时, 在实现功能的前提下, 要尽可能遵循简单原则, 参考标准协议实现流程, 线上环境不使用的文件, 要尽快清除.






