開放重新導向是指以你的真網域開頭的 URL,卻把訪客送到完全不同的站點。下面講解其原理和可靠的防禦方法(不會寫攻擊步驟)。
為什麼危險
危險的本質在於「對網域的信任被濫用」這一點。
| 被濫用的方式 | 會發生什麼 |
|---|---|
| 經由你的網域進行 phishing | 連結開頭是真網域→使用者和過濾器都信任→被誘導到假站點 |
| 認證流程被劫持 | 竄改 OAuth 等的重新導向目標,盯上 token/code 的傳遞 |
| 放大其他漏洞 | 與 SSRF 或 XSS 組合,擴大危害 |
為什麼會成立(原理)
在「登入後回到原來的頁面」之類的功能裡,如果原樣信任並轉發返回位址 URL,就會發生。使用者看到的 URL 的「開頭」是真網域,所以很難一直懷疑到最後,這正是麻煩之處。
防禦:不接收外部 URL
跳轉目標只允許相對路徑(最重要)
返回位址只接受 /dashboard 這樣的相對路徑,拒絕完整 URL(以 http://、// 開頭的)。不給使用者留下任何能指定跳轉目標網域的餘地。
對照允許清單校驗
如果需要動態的跳轉目標,就只對已知跳轉目標的固定集合(對應表)放行。不符合就回到預設頁面。
不要依賴字串判斷
//evil、反斜線、@、多重編碼等繞過手法很多。改變接收方式的設計(相對路徑+允許清單)比一條條往過濾器裡追加規則更可靠。
實在要跳到外部就明確告知
如果跳到外部是規格需要,就插入一個確認頁面,向使用者顯示「即將跳轉到外部站點」。不要悄無聲息地跳走。
本站的視角:單獨看評為「低」,但和 phishing 組合就很嚴重
開放重新導向單獨看時往往被認為嚴重度低,但因為攻擊者能借用你網域的信任,一旦和 phishing 或認證劫持組合起來,就會變得很嚴重。正因如此,用「相對路徑+允許清單」這種設計層面的修正來消除原因才高效。它和 SSRF(讓伺服器去存取任意目標)的思路相似,二者共同的防禦原則都是「不讓使用者來決定跳轉目標・連線目標」。
開放重新導向、SSRF 與網路釣魚的比較
開放重新導向本身與其說是攻擊,不如說是讓其他攻擊更有說服力的缺陷。把它與相關用語並列,就能看出它的位置。
| 用語 | 發生什麼 | 由誰修正 |
|---|---|---|
| 開放重新導向 | 真網站的 URL 把使用者的瀏覽器轉送到外部網站 | 有重新導向功能的網站開發者 |
| SSRF | 不是瀏覽器,而是伺服器向被指定的目標送出請求 | 有 URL 取得功能的網站開發者 |
| 網路釣魚 | 用假網站讓人輸入帳號、密碼或信用卡資料 | 使用者、郵件接收端,以及被冒充的組織 |
當釣魚連結可以使用真網域時,使用者與郵件過濾器都更難識破。消除開放重新導向,可以避免你的網域被用於詐騙。
實例:影響最大的地方是登入整合(OAuth)
開放重新導向影響最大的地方,是登入整合(OAuth)周邊。授權後,使用者會帶著授權碼或權杖被送回登錄的 redirect URI。如果返回的網站有開放重新導向,授權碼或權杖就可能被轉送到外部網站。
因此 OAuth 2.0 安全最佳實務(RFC 9700,2025 年 1 月)要求兩件事。
- 授權伺服器以完全比對檢查 redirect URI 與事先登錄的值
- 用戶端與授權伺服器都不公開「把查詢參數裡的任意 URL 拿來轉送」的頁面
開放重新導向被分類為 CWE-601。它單獨被評為高嚴重度的情況很少,但放在登入整合旁邊就會成為嚴重的問題。
嚴重程度
單獨來看,開放重新導向通常評為中等。常見的評分是 CVSS 3.1 6.1。
- 需要使用者開啟連結(UI:R)
- 影響是把使用者送到別的網站,並不能讓任何人直接讀取網站的資料
- 由於影響範圍超出了進行重新導向的網站,因此以範圍變更(S:C)計分
不要因為這個數字就延後處理。如果它位於登入整合的返回路徑上,或已經被用於網路釣魚,請優先修正。要為自己的情況評分,請使用 CVSS 計算器。
框架內建的安全輔助函式
框架的功能比自己寫的字串檢查更不容易漏掉情況。兩個常見的例子:
| 框架 | 輔助函式 | 作用 |
|---|---|---|
| Ruby on Rails | redirect_to 的預設行為與 url_from | 預設會阻擋重新導向到其他主機;要把使用者送到外部,必須明確指定 allow_other_host: true。url_from 只在 URL 屬於同一主機時才回傳該 URL,否則回傳 nil |
| ASP.NET Core | LocalRedirect 與 Url.IsLocalUrl | 只重新導向到同一網站內的 URL,遇到外部 URL 會擲回例外 |
Rails 文件提醒,即使使用 allow_other_host: true,把使用者提供的參數直接傳入也不安全。新增外部重新導向功能時,請避免這種組合。
如何檢查自己的網站
找出接收跳轉目標的參數
在程式碼與 URL 清單中搜尋名為 next、url、redirect、return_to、continue、callback 之類的參數,確認它們是否被原樣交給重新導向。
確認跳轉目標的校驗方式
看校驗是否依賴字串前綴比對或「是否以 http 開頭」。應改用 URL 解析器把 URL 拆成協定、主機與埠再對照允許清單,或使用框架提供的安全輔助函式(例如 ASP.NET Core 的 LocalRedirect)。
檢查登入整合的登錄內容
在 OAuth 或 SSO 設定中,確認已登錄的 redirect URI 不含萬用字元,也沒有留下已不需要的舊 URL。
考慮以 ID 指定跳轉目標
如果必須跳到外部,就接收簡短的 ID 而不是 URL 本身,並在伺服器端的對照表中查出跳轉目標。OWASP 推薦這種做法。
在存取記錄中尋找外部重新導向
在存取記錄中搜尋跳轉目標參數裡含有自己以外主機名稱的請求。如果找到了,確認該重新導向是否真的會把人送到外部,並把它視為可能有人在散布這類連結的跡象。
出處(一手資料)
- OWASP, "Unvalidated Redirects and Forwards Cheat Sheet" — cheatsheetseries.owasp.org(在伺服器端對應 ID、對解析後的 URL 以允許清單校驗、警告頁面)
- IETF RFC 9700, "Best Current Practice for OAuth 2.0 Security"(2025 年 1 月)— datatracker.ietf.org(redirect URI 的完全比對、禁止開放重新導向器)
- Ruby on Rails API, "ActionController::Redirecting" — api.rubyonrails.org(預設阻擋重新導向到其他主機、
allow_other_host、url_from) - Microsoft, "Prevent open redirect attacks in ASP.NET Core" — learn.microsoft.com(
LocalRedirect、IsLocalUrl、記錄非本機 URL) - MITRE, "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" — cwe.mitre.org