OAuth 攻擊者模型
RFC 9700 在 §3 定義了一套正式的攻擊者模型,作為所有安全建議的共同基礎。
解決什麼問題
Section titled “解決什麼問題”安全建議不能只列清單,還必須說明「針對什麼攻擊者」。
在 OAuth 流程中,一個 Access Token 可能跨越多個環節傳遞——從 Client 發出授權請求、Authorization Server 核發 Token,到 Client 持 Token 存取 Resource Server。每個環節的威脅情境都不同,沒有精確的威脅描述,就無法回答:
- 為什麼一定要用 HTTPS?
- 為什麼不能把 Token 放在 URL fragment 裡?
- 為什麼要做 PKCE?
- 為什麼 sender-constraining 可以降低洩漏後的損害?
透過定義五種能力各異的攻擊者類型,RFC 9700 讓每條安全建議都能對應到具體威脅,而不只是「安全最佳實踐」的籠統說法。
五種攻擊者類型
Section titled “五種攻擊者類型”A1:網路攻擊者(Web Attacker)
Section titled “A1:網路攻擊者(Web Attacker)”最基本的攻擊者模型。A1 可以:
- 架設任意的惡意伺服器與網站
- 誘導或欺騙使用者造訪惡意連結
- 接收被導向至其伺服器的請求與回應
能力邊界:只能控制自己的伺服器,無法攔截或修改他人的網路流量。
典型攻擊場景:利用 redirect URI 驗證不嚴謹,讓 Authorization Server 將授權碼導向攻擊者的惡意伺服器;或透過開放式重新導向(open redirector)達到相同效果。
對應防護:Redirect URI 精確比對、禁止 open redirector
A2:中間人攻擊者(Network / MitM Attacker)
Section titled “A2:中間人攻擊者(Network / MitM Attacker)”在 A1 的基礎上,A2 還可以:
- 竊聽未加密或弱加密的網路通訊
- 竄改傳輸中的 HTTP 請求與回應
- 降級 HTTPS 連線(若 Authorization Server 未啟用 HSTS)
能力邊界:只能攔截未受 TLS 保護、或 TLS 設定不當的流量。
典型攻擊場景:在公共 Wi-Fi 上竊聽明文傳輸的 Token;透過 SSL stripping 攻擊將 HTTPS 降級為 HTTP 後讀取 Token。
sequenceDiagram
participant Client
participant 攻擊者 A2
participant Authorization Server
Client ->> 攻擊者 A2: HTTP 明文請求(帶 Token)
攻擊者 A2 ->> Authorization Server: 轉發(並竊取 Token)
對應防護:強制 TLS、Authorization Server 啟用 HSTS
A3:授權回應讀取者(Authorization Response Reader)
Section titled “A3:授權回應讀取者(Authorization Response Reader)”A3 可以讀取(但不能修改)授權回應的內容,包括:
- 跳轉 URL 的 query string 或 fragment(
?code=...或#token=...) - 瀏覽器自動附帶的
RefererHeader(可能洩漏含有授權碼的前一頁 URL) - 瀏覽器歷史記錄、代理伺服器 log 中留存的跳轉網址
能力邊界:不需要控制網路流量,只需要能「看到」授權回應。這使 A3 的威脅更廣——許多非攻擊性的基礎設施(日誌系統、第三方 JavaScript、瀏覽器外掛)都可能成為洩漏管道。
典型攻擊場景:
- 同源的惡意 JavaScript 讀取 URL fragment 中的 Token(Implicit Flow 的核心問題)
- 含有授權碼的跳轉 URL 透過
RefererHeader 洩漏給頁面中的第三方資源
對應防護:廢除 Implicit Flow(避免 Token 出現在 URL 中);使用 PKCE,即使授權碼被讀取也無法兌換 Token
A4:授權請求讀取者(Authorization Request Reader)
Section titled “A4:授權請求讀取者(Authorization Request Reader)”A4 可以讀取(但不能修改)授權請求的內容,包括:
- 授權請求 URL 中的參數(
client_id、scope、redirect_uri等) - PKCE 的
code_challenge(公開附在授權請求中的雜湊值)
能力邊界:只能「看到」請求,不能竄改。A4 的主要意義是確認 PKCE 的設計是否能在 code_challenge 公開的情況下仍然安全。
典型攻擊場景:攻擊者取得 code_challenge 後,嘗試逆推 code_verifier,以便在攔截到授權碼後自行換取 Token。
對應防護:PKCE 使用 S256 方法(SHA-256 單向雜湊),從 code_challenge 在計算上無法還原 code_verifier
A5:Token 取得者(Token Obtainer)
Section titled “A5:Token 取得者(Token Obtainer)”A5 能夠透過各種手段取得已核發的 Access Token,例如:
- 利用 A1~A4 的任意組合竊取 Token
- 入侵 Resource Server、日誌系統或監控平台
- 利用 Client 端儲存 Token 的漏洞(如 localStorage 的 XSS 風險)
能力邊界:A5 代表的是「Token 已經洩漏」這個事實,而不是特定的攻擊手法。它的存在承認了現實:即使前四種攻擊者的威脅都已妥善防禦,Token 仍可能因為其他意外或設定錯誤而洩漏。
典型攻擊場景:
- 伺服器日誌意外記錄了 Bearer Token
- 第三方依賴套件的 XSS 漏洞導致 Token 從 localStorage 洩漏
- 遭入侵的 Resource Server 中留存的有效 Token
對應防護:sender-constraining(DPoP、Mutual TLS)——即使 Token 已洩漏,沒有對應的金鑰就無法使用
攻擊者與防護一覽
Section titled “攻擊者與防護一覽”| 攻擊者 | 核心能力 | 典型威脅 | 主要防護 |
|---|---|---|---|
| A1 網路攻擊者 | 架惡意站、誘導點擊 | 竊取被錯誤導向的授權碼 | Redirect URI 精確比對、禁止 open redirector |
| A2 中間人攻擊者 | 竊聽與竄改明文流量 | 攔截 Token 或竄改回應 | 強制 TLS、HSTS |
| A3 授權回應讀取者 | 讀取授權回應內容 | 從 URL、Referer 洩漏授權碼或 Token | 廢除 Implicit Flow、PKCE |
| A4 授權請求讀取者 | 讀取授權請求內容 | 嘗試逆推 code_verifier | PKCE S256 |
| A5 Token 取得者 | 取得已核發的 Token | 任何管道的 Token 洩漏 | Sender-constraining(DPoP / mTLS) |
攻擊者能力彼此獨立
Section titled “攻擊者能力彼此獨立”這五種攻擊者不是從低到高的等級制,而是能力維度不同的獨立威脅類型:
- A3 不需要 A1 的能力(不需要自架惡意站,只要能讀到授權回應就夠了)
- A4 不需要 A3 的能力(只讀請求,不讀回應)
- 真實的攻擊者可能同時具備多種類型的能力
實作時要思考的不是「這個攻擊者能做什麼」,而是「我的系統在哪個假設被違反時會失守」。
RFC 9700 明確說明,如果攻擊者入侵了 Client 本身(取得了 Client 的私鑰或 credentials),這已超出威脅模型的範圍——OAuth 協定本身無法防禦。
這設定了一個重要前提:OAuth 的安全假設 Client 的實作是可信的。保護 Client 端的安全(例如金鑰管理、程式碼安全)是另一個層次的課題。