Checkmarx Client DOM Open Redirect

June 02, 2025

  • checkmarx
有任何問題,我能幫上忙的話都能到 github 發 issue 問我。

Preface

在開發前端 SPA 管理系統時,與第三方 SSO(Single Sign-On)整合是常見需求。此時,常會需要透過前端協助將使用者導向到其他網域。這類操作若未妥善處理,在使用像 Checkmarx 這類靜態檢測工具時,就可能被標記為 Client DOM Open RedirectClient DOM XSS 的安全漏洞。

What is Open Redirect

假設有一個網址是:

https://facebooks.com?redirect=https://hacker.com

使用者若未注意 facebooks 這個偽冒網域,很可能就會上當。若這個網站在接收到 redirect 參數後沒有妥善檢查,直接導向,就會讓使用者被轉送到 https://hacker.com 這樣的惡意站台,進一步進行釣魚攻擊。這就是典型的 Client DOM Open Redirect

What is Client DOM XSS

若應用允許使用者在 URL 中注入可執行的程式碼,例如:

https://facebooks.com?exec=<script>console.log(1)</script>

且前端或後端未妥善處理,就可能被觸發,導致攻擊者植入惡意腳本,這就是 Client DOM XSS 攻擊。

How To Fix

所以比較好的做法是什麼呢?

透過後端導向(建議)✅,建議將跳轉邏輯移至後端,由伺服器發出 HTTP 302 redirect,並搭配白名單檢查可接受的 URL 來源:

app.get("/sso", (req, res) => {
  const redirect = req.query.redirect
  const allowedOrigins = ["https://qoo.com", "https://lol.com"]

  try {
    const url = new URL(redirect)
    // 當然你也可以做更嚴謹的驗證,這邊就請依據自己的需求去做修改
    if (allowedOrigins.includes(url.origin)) {
      return res.redirect(302, redirect)
    }
  } catch (e) {}

  res.status(400).send("Invalid redirect URL")
})

透過前端去導向,則需對參數預處理及設定白名單

// 這三種語法都能執行 javaScript,因此是不安全的
window.location.href = "javascript:console.log(1)"
window.location.assign("javascript:console.log(1)")
window.location.replace("javascript:console.log(1)")
function redirect() {
  // ssoLoginRedirectURL 建議從伺服器取得
  const redirectURL = new URL(ssoLoginRedirectURL)

  // 僅允許特定參數,避免 XSS,當然由於你允許了這些參數,後端也建議做好處理
  const allowParams = ["sso-token"]
  const currentParams = new URLSearchParams(location.search)

  for (const key of currentParams.keys()) {
    if (!allowParams.includes(key)) {
      currentParams.delete(key)
    }
  }

  // URLSearchParams.toString() 會自動做 encodeURIComponent 處理
  redirectURL.search = currentParams.toString()

  // ⚠️ Checkmarx 建議:請避免使用 window.location.href
  // 改用 assign 或 replace 以減少誤判
  window.location.assign(redirectURL.toString())
}

Location 差異

方法 新頁面 影響歷史紀錄 備註
href ✅ 是 ✅ 是 靜態分析工具容易誤判為 Open Redirect 或 XSS 攻擊途徑
assign ✅ 是 ✅ 是 推薦使用方式,風險較低
replace ✅ 是 ❌ 否 推薦使用方式,風險較低

補充assignreplace 也有針對錯誤額外做處理。

如果呼叫 assignreplace 的 JavaScript 程式碼的來源(origin) 和 Location 物件所描述的頁面來源不同,就會拋出 SecurityError。這通常發生在程式碼來自不同的網域,也就是跨域(Cross-Origin)情況,及如果不是合格的網址,也會跳錯誤。

所以相比於 href 直接調用,assignreplace 安全性也相對比較高。

Conclusion

  • 後端轉址 是最推薦的方式,可完全避免前端風險。
  • 前端轉址 若無法避免,請加入 URL 白名單檢查、允許參數清單,並過濾 javascript: 等可執行內容,避免產生 XSS 或 Open Redirect 風險。

Mayvis Chen
你好,我是 Mayvis Chen
住在台北,會點前端,會點後端,熱愛分享新知及愛喝奶茶的全端打雜工程師。