介紹
在網路安全中,跨站腳本 (XSS) 是最古老、最持久的漏洞之一。
如果惡意腳本在受害者的瀏覽器上執行,它們可能會破壞整個會話、竊取會話令牌 (cookie)、劫持帳戶或動態變更頁面內容以取得敏感憑證。
本文回顧了消除現代 Web 應用程式中 XSS 漏洞所需的基本防禦原則。我們將探索上下文轉義、清理、安全 DOM 操作和防禦深度機制。
1.XSS的三種分類
根據惡意負載的傳輸方式,XSS 漏洞大致分為三類:
- 反射的XSS: 當惡意負載嵌入到連結或表單提交時會發生。當使用者點擊連結時,伺服器會將不受信任的輸入「反射」迴響應 HTML,而無需進行適當的轉義。
- 儲存(持久)XSS: 最危險的形式。有效負載儲存在伺服器的資料庫中(例如,論壇貼文、使用者簡介)並傳遞給任何存取該頁面的後續使用者。
- 基於 DOM 的 XSS:
與反射或儲存 XSS 不同,這完全發生在客戶端 JavaScript 中。此腳本處理不受信任的來源資料(例如
location.hash或查詢參數)並使用不安全的 API 將其直接寫入 DOM。
2. 原則 1:上下文感知 HTML 轉義
XSS 的根本解決方法是在渲染不受信任的動態資料之前對其進行轉義。轉義將 HTML 語法中具有特殊意義的字元文字轉換為各自的惰性 HTML 實體(字元引用)。
基本字元映射表
&->&<-><>->>"->"'->'(或')
警告:上下文很重要
轉義規則會根據資料放置的「位置」而變化。
- 放置在元素標記內的文字需要標準實體轉義。
- 放置在元素屬性內的文字(例如
<input value="DYNAMIC_DATA">)需要嚴格的引號轉義。 - 單獨使用 HTML 轉義無法保護
<script>區塊、CSS 版面配置或 URL 屬性 (href) 內呈現的資料。它們分別需要 JavaScript 轉義、CSS 轉義或 URL 編碼。
3. 原則 2:安全 DOM API(防止基於 DOM 的 XSS)
使用 JavaScript 動態更新頁面內容時,選擇錯誤的 API 可能會造成安全漏洞。
不良做法
// Reading a query parameter and injecting it directly
const params = new URLSearchParams(window.location.search);
const username = params.get("name");
// DANGEROUS: If name is "<img src=x onerror=alert(1)>", the script will execute
document.getElementById("greeting").innerHTML = `Hello, ${username}!`;
最佳實踐
如果要將動態資料解釋為純文本,請務必使用 textContent 或 innerText 而不是 innerHTML。
const params = new URLSearchParams(window.location.search);
const username = params.get("name");
// SAFE: The browser treats input strictly as plain text, rendering tags harmlessly
document.getElementById("greeting").textContent = `Hello, ${username}!`;
如果您的應用程式必須呈現使用者提供的 HTML 標記(例如,Markdown 預覽),則必須先將字串傳遞給經過考驗的清理庫(例如 DOMPurify)。
4. 原則 3:安全連結方案
當應用程式允許使用者保存網站連結並直接在錨元素 (<a href="USER_URL">) 中呈現它們時,就會出現常見的安全漏洞。
風險
即使您轉義 HTML 字符,使用者也可以提供類似 javascript:alert(document.cookie) 的有效負載。點擊該連結將立即執行該腳本。
<!-- DANGEROUS: The script executes when clicked -->
<a href="javascript:alert(document.cookie)">Visit Website</a>
解決方案
對使用者 URL 實施嚴格的方案驗證。僅允許明確以 http:// 或 https:// 開頭的 URL,拒絕 javascript: 或 data: 等方案。
5.縱深防禦
僅依靠程式碼清理是有風險的。分層瀏覽器安全控制提供了一個重要的安全網。
內容安全策略 (CSP)
內容安全策略是一個 HTTP 回應標頭,它定義允許哪些腳本來源在您的頁面上運行。
Content-Security-Policy: default-src 'self'; script-src 'self' https://trustedscripts.com;
強大的 CSP 可以限制內聯腳本,即使存在逃逸漏洞,也可以防止注入的有效負載運作。
僅 Http Cookie
透過 cookie 發出會話識別碼時,請務必設定 HttpOnly 標誌。這可以防止客戶端腳本讀取 cookie 值(透過 document.cookie),從而減少會話盜竊,即使 XSS 攻擊成功也是如此。
結論
保護您的 Web 應用程式免受 XSS 侵害需要一致性:
- **將上下文感知轉義應用於所有動態輸入。 **
- **對於 DOM 操作,優先使用
textContent而不是innerHTML。 ** - **在渲染連結之前驗證 URL 方案 (
http:/https:)。 ** - **使用內容安全策略和 HttpOnly cookie 作為安全網。 **
透過將這些安全實務納入您的開發工作流程,您可以防止 XSS 漏洞。

