Vulnerability Detail Report
Vulnerability Overview
- ZDID: ZD-2026-00726
- Vendor: 狄卡科技股份有限公司
- Title: Dcard 驗證流程 returnUrl 可透過控制字元繞過檢查造成開放轉址
- Introduction: *網頁版 /* 流程的 returnUrl 參數只檢查是否以 / 開頭,未處理控制字元。攻擊者可使用 %2F%09%2Fexample.com 這類 payload,讓使用者在 *頁面點擊「稍後」後被導向外部網域。
處理狀態
目前狀態
-
新提交
-
已審核
-
已通報
-
已修補
-
未複測
-
公開
處理歷程
- 2026/05/21 14:42:13 : 新提交 (由 monkey47 更新此狀態)
- 2026/05/25 15:53:41 : 審核中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2026/05/26 17:12:48 : 審核中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2026/05/26 17:13:05 : 審核中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2026/06/12 14:34:11 : 複測申請中 (由 組織帳號 更新此狀態)
- 2026/06/30 03:00:03 : 公開 (由 HITCON ZeroDay 平台自動更新)
詳細資料
- ZDID:ZD-2026-00726
- 通報者:davidyen1124 (monkey47)
- 風險:中
- 類型:未驗證的 URL 轉址 (Unvalidated Redirects and Forwards)
參考資料
OWASP Top 10 2010 - A10 - Unvalidated Redirects and Forwards
https://www.owasp.org/index.php/Top_10_2010-A10-Unvalidated_Redirects_and_Forwards
Unvalidated Redirects and Forwards Cheat Sheet
https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet
CWE-601: URL Redirection to Untrusted Site ('Open Redirect')
http://cwe.mitre.org/data/definitions/601.html
相關網址
https://www.dcard.tw/_next/static/chunks/0r-507nat1yw~.js
敘述
摘要
Dcard 網頁版的驗證流程存在一個開放轉址問題。受影響路徑為:
/signup/verify/profession
該頁面會讀取 query string 中的 returnUrl,並在使用者點擊「稍後」後導向該位置。目前前端只確認 returnUrl 是否以 / 開頭,沒有排除 ASCII 控制字元或其他容易被瀏覽器重新解析的 URL 變形。
因此攻擊者可以準備一個看起來是 Dcard 官方網域的連結,讓使用者先進入真正的 www.dcard.tw 頁面,再透過正常的頁面互動被帶到外部網站。
影響範圍
- 受影響網域:
www.dcard.tw - 受影響路徑:
/signup/verify/profession - 弱點類型:Unvalidated Redirects and Forwards / Open Redirect
- 風險等級建議:Medium
重現步驟
- 使用已登入 Dcard 的瀏覽器開啟下列網址:
https://www.dcard.tw/signup/verify/profession?returnUrl=%2F%09%2Fexample.com
- 頁面會顯示 Dcard 的驗證流程。
- 點擊頁面上的「稍後」按鈕。
- 瀏覽器會離開
www.dcard.tw,最後導向:
https://example.com/
實測日期:2026-05-21。
技術分析
公開前端 chunk:
https://www.dcard.tw/_next/static/chunks/0r-507nat1yw~.js
可觀察到相關的 minified 邏輯如下:
e$="string"==typeof W.query.returnUrl?W.query.returnUrl:"",
eL=e$.startsWith("/")?e$:"/f",
eN=()=>{W.push(eL)}
「稍後」按鈕的處理流程會呼叫同一個導向 helper:
eO=()=>{eM("cancel"),eN()}
也就是說,只要 returnUrl 字串開頭是 /,就會被視為可接受的站內導向目標,並交給 Next router 處理。
本次可利用 payload 為:
%2F%09%2Fexample.com
解碼後可視為:
/ /example.com
它可以通過 startsWith("/") 檢查;但在後續 router / browser URL 解析過程中,會被正規化並解析成外部網域,最後導向 https://example.com/。
測試結果
| Payload | 實際導向結果 |
|---|---|
%2F%2Fexample.com |
https://www.dcard.tw/example.com |
%2F%5Cexample.com |
https://www.dcard.tw/example.com |
%2F%5C%5Cexample.com |
https://www.dcard.tw/example.com |
%2F%2F%5Cexample.com |
https://www.dcard.tw/example.com |
%2F%09%2Fexample.com |
https://example.com/ |
%2F%2E%2E%2F%2Fexample.com |
https://www.dcard.tw/example.com |
%2F%2Fexample.com%2F%252e%252e |
https://www.dcard.tw/f |
為什麼這是安全問題
這個問題可被用於釣魚或社交工程攻擊。攻擊者可以散布一個開頭為 https://www.dcard.tw/... 的連結,使用者點開後會先看到真實的 Dcard 頁面,因此較容易信任該流程。當使用者點擊頁面中的正常按鈕後,就會被帶到攻擊者控制的網站。
可能的利用情境包含:
- 偽造 Dcard 重新登入頁面
- 偽造帳號驗證或 MFA 驗證頁
- 搭配訊息、貼文或客服詐騙流程提高可信度
- 繞過只檢查初始 URL 網域的郵件、簡訊或內部安全過濾規則
測試限制
本次測試只進行非破壞性驗證:開啟 Dcard 頁面、點擊「稍後」,並確認導向結果。測試過程沒有讀取 cookies、localStorage、sessionStorage、密碼、Authorization header、API request body、API response body,或任何私人帳號資料。
修補建議
建議將所有由使用者可控參數決定的導向目標集中到同一個安全 helper 處理,避免各流程各自做不完整的字串檢查。
建議修補方向:
1. 導向前先拒絕或移除 ASCII 控制字元,包含 tab、newline、carriage return 等。
2. 拒絕 protocol-relative URL,例如 `//example.com`,以及編碼後可被解析成相同語意的變形。
3. 拒絕反斜線變形與完整外部 URL,例如 `http://`、`https://`。
4. 使用 `new URL(candidate, window.location.origin)` 解析後,再確認 `url.origin === window.location.origin`。
5. 驗證失敗時導向固定安全路徑,例如 `/f`。
6. 建議補上單元測試,至少涵蓋 `/%09/example.com`、`//example.com`、`/\example.com`、`https://example.com` 等案例。