OAuth 安全性簡要回顧
你對 OAuth 採用的保護措施有多熟悉?你的系統是否遵循 OAuth 的開放標準?在實施用戶驗證流程時,你是否注意到可能出現的潛在風險?讓我們簡要回顧一下我們對 OAuth 的了解。
介紹
幾天前,我們受到了一篇有趣的 OAuth 漏洞文章的衝擊。由 SALT 實驗室撰寫的 影響數百個線上服務的新 OAuth 漏洞 此特定文章強調了在 Expo 中發現的漏洞,這是一個廣泛使用的框架,用於實現 OAuth 和其他功能。文章特別針對 expo-auth-session 庫中的漏洞,該漏洞已被指派並妥善解決。
如果你對 OAuth 感興趣或像我們這樣正在從事 CIAM 相關產品開發,我們強烈建議閱讀這篇文章。這相當具有啟發性並提供了有用的見解。這些白帽報告提醒我們,即使是最簡單的功能也可能導致漏洞。在網絡安全和授權方面,我們永遠不能在保障用戶信息安全和隱私方面謹慎不足。如果這篇文章引起了你的注意,我相信你會強烈同意我們的看法。
這讓我想起我們剛開始時的情景。我們花了很多時間學習和研究 OAuth 和 OIDC 協議的細節。這既痛苦又單調,但收益卻是巨大的。雖然我們團隊中的每個人可能不是 OAuth 專家,但每個人都致力於在安全性和細緻性上付出持續的努力。透過這些專注的努力,Logto 產品已發展到如今的樣子。
感謝這個絕佳的機會,我們想藉此回顧一下有關 OAuth 的一些安全細節。
OAuth 授權碼流程一瞥
OAuth 2.0 提供了各種授權流程,以滿足不同客戶端類型和需求。其中包括隱式流程、客戶端憑證流程、資源擁有者密碼憑證流程 和設備授權流程。不過,授權碼流程是最安全且廣泛使用的。與其他流程不同,它將用戶驗證與客戶端應用程式分開,並涉及將授權碼交換為令牌。此方法提供了額外的安全層,因為敏感令牌從不暴露給客戶端。此外,授權碼流程支持服務器端令牌管理,適合需要強大安全性和增強控制用戶訪問的網絡應用程式。
這是最簡單的授權碼流程圖:
我們來看看在授權碼授權流程中最重要的兩個請求,以及在它們之中看似微不足道的片段,但在防範欺詐中發揮了至關重要的作用。
授權端點:
令牌交換端點:
客戶端憑證
在 OAuth 中,客戶端憑證指的是客戶端應用用於驗證和識別自身到授權服務器的憑證。這些憑證在客戶端註冊過程中獲取,並用於在向授權服務器發送請求時驗證客戶端的身份。(當你首次註冊應用程式時,你可以在 Logto 的管理控制台中找到你的客戶端憑證。)
客戶端憑證通常由兩個組成部分構成:
- 客戶端 ID:授權服務器分配給客戶端應用的唯一識別符號。這是一個公開的值,通常不被視為敏感信息。
- 客戶端密碼:一個僅客戶端和授權服務器知道的機密且安全存儲的值。它作為客戶端應用的身份驗證形式,並用於在向授權服務器發出請求時驗證客戶端的身份。
正如你所發現的,客戶端 ID 和客戶端密碼組合在令牌請求期間用於驗證客戶端並獲取訪問令牌。
客戶端憑證在確保 OAuth 流程的安全性方面發揮著至關重要的作用。它們幫助授權服務器驗證客戶端應用的真實性並控制對受保護資源的訪問。安全處理客戶端憑證並防止未經授權訪問非常重要。Logto 以兩個不同的安全級別對客戶端應用進行分類:
- 機密客戶端:這包括服務器渲染的網頁應用和機器對機器(M2M)應用。對於機密客戶端,所有與授權相關的憑證,包括客戶端憑證,均安全存儲在服務器端。此外,所有的中間交換請求均經加密處理以確保數據的保密性。對於機密客戶端而言,憑證洩漏的風險很低,這使它們天生更安全。因此,機密客戶端預設為高安全性級別。於令牌交換流程中,客戶端密碼的呈現是必須的。
- 公共客戶端:這包括單頁網頁應用(SPA)和原生應用。對於公共客戶端而言,客戶端憑證通常寫死在客戶端程式碼中,例如在 JavaScript 程式包或在原生平台的應用程式包中。由於客戶端憑證在客戶端程式碼中的固有暴露,因此相比機密客戶端,其憑證洩漏風險更高。於令牌交換流程中,客戶端密碼的呈現是可選的。Logto 預設不信任來自公共客戶端的這些憑證。
狀態
在 OAuth 流程中,state
參數是一個隨機生成的值,包含在由客戶端發送給授權服務器的授權請求中。其目的是在授權過程中保持客戶端請求的狀態或上下文。
state
參數作為一種安全措施來防止跨站請求偽造(CSRF)攻擊。當授權服務器在驗證和授權之後將用戶重定向回客戶端應用時,它包括在響應中與原始請求相同的 state 值。客戶端應用 必須
將此值與其在授權請求中發送的原始 state
值進行比較。
通過驗證 state 參數,客戶端可以確保從授權服務器收到的響應與其發出的初始請求吻合。這有助於防止攻擊者試圖欺騙客戶端接受旨在針對其他用戶或應用的響應的攻擊。
以下是在一個虛構用例中 CSRF 攻擊的示例:
CSRF 攻擊:綁定社交賬戶的欺詐問題
使用適當的狀態驗證機制,客戶端可以檢測攻擊並防止用戶被重定向到攻擊者的網站:
CSRF 攻擊:綁定社交賬戶的欺詐解決方案
PKCE
如前所述,公共客戶端如 SPA 網頁應用和原生應用進一步增加了身份驗證憑證洩漏的風險,包括由授權伺服器發行的授權碼。
PKCE 代表授權碼交換的驗證密鑰。這是 OAuth 2.0 授權碼流程 的擴展,增強了公共客戶端的安全性。
PKCE 被引入以減輕攻擊者攔截授權碼並使其在客戶端不知情的情況下將其交換為訪問令牌的風險。這種攻擊被稱為授權碼攔截攻擊,在客戶端應用無法安全存儲客戶端密鑰的環境中更為普遍。
為了實現 PKCE,客戶端應用創建了一個隨機的驗證密鑰並使用特定的哈希算法(通常為 SHA-256)推導出驗證碼。驗證碼包含在發送給授權伺服器的初始授權請求中。
當授權服務器發行授權碼時,客戶端應用在令牌請求中包含了原始的驗證密鑰。伺服器驗證驗證密鑰是否與儲存的驗證碼匹配,只有這樣才會發行訪問令牌。
通過使用 PKCE,客戶端應用確保授權碼本身不足以獲取訪問令牌。此機制為授權流程添加了一層額外的安全性,特別是對於在存儲客戶端密碼具有挑戰性的公共客戶端環境中。
Logto 使用 PKCE 作為所有公共客戶端類型應用的唯一授權流程。然而,對於機密客戶端,PKCE 可被省略。
重定向 URI
重定向 URI(統一資源標識符) 是在 OAuth 中,在身份驗證和授權過程後,授權服務器將用戶重定向的特定端點或 URL。
在 OAuth 流程期間,客戶端應用在初始授權請求中包含重定向 URI。此 URI 作為回調 URL,即用戶成功進行身份驗證並授予客戶端授權後,重定向的目標回調頁面。
一旦用戶完成身份驗證過程,授權服務器生成一個包含授權碼的響應,並將用戶重定向回指定的重定向 URI。
重定向 URI 的驗證是確保 OAuth 流程安全性和完整性的一個關鍵步驟。它涉及確認授權請求和後續重定向中使用的重定向 URI 是否有效、可信。
讓我們回到初始的 OAuth 漏洞報告 查看。(以下部分參考自原始文章)
當用戶通過 Expo Go 的 Mobile APP 點擊 “login with facebook” 時,會將用戶重定向到以下鏈接:
https://auth.expo.io/@moreisless3/me321/start?authUrl=https://www.facebook.com/v6.0/dialog/oauth?code_challenge=...&display=popup&auth_nonce=...&code_challenge_method=S256&redirect_uri=https://auth.expo.io/@moreisless3/me321&client_id=3287341734837076&response_type=code,token&state=gBpzi0quEg&scope=public_profile,email&returnUrl=exp://192.168.14.41:19000/--/expo-auth-session
在響應中,auth.expo.io 設置了以下 cookie:ru=exp://192.168.14.41:19000/--/expo-auth-session. 此數值 RU 稍後將作為返回 URL,在第 5 步使用。然後它向用戶顯示確認消息,如果用戶批准 - 將用戶重定向到 Facebook 登錄以繼續身份驗證流程
…
此頁面讀取查詢參數“returnUrl”並相應設置 cookie。
讓我們將返回 URL 修改為
hTTps://attacker.com
(不允許 https,所以我嘗試插入大寫字母,效果不錯),這將 RU(返回 URL)設置到 cookie 中即為https://attacker.com
。…
在上面的情況中,棄用了原始 redirect_uri
參數,Expo 引入了一個沒有正確驗證的新參數,稱為 returnUrl。此疏忽為攻擊者提供了一個機會訪問由 Facebook 返回的授權碼。有關更多詳情,請參考原始文章。
重定向 URI 驗證具有多個重要目的:
- 防止釣魚攻擊:通過驗證重定向 URI,授權服務器確保用戶被重定向回受信和授權端點。這有助於阻止攻擊者將用戶重定向到惡意或未授權的位置。
- 抵禦開放重定向:開放重定向是一個可以被利用以將用戶重定向到惡意網站的漏洞。通過驗證重定向 URI,授權服務器可以確保重定向保持在授權的域或可信域集合的範圍之內。
- 保證授權響應的正確路由:驗證重定向 URI 有助於保證授權服務器將用戶重定向回預期的客戶端應用。它確保響應(如授權碼或訪問令牌)被送達到正確目標。
在 Logto,redirect_uri
註冊對於所有類型應用都是強制的。 我們將接收到的值與 Logto 伺服器中註冊的值進行比較和匹配。 這包括任何自定義查詢參數。如果由於缺少、無效或不匹配的 redirect_uri
值而導致授權請求驗證失敗,無效的重定向 URI 錯誤將返回給檔案上註冊的 redirect_uri
。
總結
由於其複雜和微妙的特性,這些細節往往容易被忽略。一些只是一個隨機字符串,比如 state
。
然而,值得注意的是,這些安全措施為用戶授權增加了保護層,減少了包括 CSRF 攻擊、授權碼攔截和未經授權重定向等風險。
這些只是 OAuth 協議所提供的全面安全功能的一小部分。OAuth 提供了一個安全驗證和授權的強大框架。它同樣提供靈活的開放端點,以滿足各種需求的實際產品應用。
作為開發人員和服務提供商,必須不斷優先考慮用戶授權流程的安全性。保持謹慎,遵循最佳實踐,並保持最新的 OAuth 生態系統開發至關重要,以確保用戶身份和敏感數據的完整性和保護。我們將繼續致力於堅持最高的安全標準,實施 OAuth 並保護用戶隱私和信任。