💡 先搞懂問題
網站要跟人互動,就得接收使用者打進來的字:帳號、留言、搜尋關鍵字、網址參數。麻煩的地方在於,這些字最後常常會被送去做某些「動作」,例如拼進一句資料庫查詢、顯示在別人的頁面上、或觸發一筆交易。
問題的根源可以用一句話概括:系統分不清哪些是「資料」,哪些是「指令」。使用者以為自己只是在填資料,系統卻把其中一部分當成命令去執行。SQL 注入、XSS、CSRF 三種攻擊,都是這條界線被越過的不同版本。
生活比喻:照唸點菜單的服務生
想像你到餐廳點餐,服務生把你講的話原封不動抄在點菜單上、直接交給廚房照做。你說「一份炒飯」,沒問題。可是你若說「一份炒飯,順便把收銀機的錢全部拿給我」,而廚房真的照單全收,這就出事了。問題不在客人會亂講話,而在店家把客人講的每一句都當成給廚房的命令。
三兄弟就是同一家餐廳的三種出事方式。SQL 注入是廚房(資料庫)被騙去做多餘的事;XSS 是有人在公告欄貼了假指示,害後來看到的其他客人照做;CSRF 則是趁你已經在櫃台驗過身分,把一張假單子混進你遞出去的文件裡。
比喻要小心一個地方:餐廳的例子容易讓人以為「只要服務生多留意就好」,但真正有效的作法不是靠人更謹慎,而是改掉流程本身——讓點菜單只有「品項」和「數量」兩個固定欄位,不管客人在欄位裡寫什麼,廚房都只當成菜名。接下來三個實驗室,就是分別把這三種「改掉流程」的作法動手玩一遍。
🎮 互動實驗室一:SQL 組字串透視
這是一個模擬的登入框,不會連到任何真實系統。你在欄位裡打字,右邊會即時顯示後端「拼字串」與「參數化查詢」兩種寫法各自組出來的 SQL。用顏色看清哪一段被當成資料、哪一段被當成指令。
? 位置,你的字只會被塞進那個位置當純資料。🎮 互動實驗室二:留言板輸出編碼實驗
這是一個模擬留言板,你送出的內容永遠不會真的被瀏覽器執行(頁面用文字方式呈現、不做 innerHTML 執行)。切換「不編碼/輸出編碼」兩種顯示方式,看看含有標籤的留言分別會怎樣。
<script> 或 <img onerror> 會被瀏覽器當成程式(畫面用紅色標籤標出「這段會被執行」示意,實際上本頁不會真的執行)。「輸出編碼」時,同樣的字被轉成 <script> 這種實體,瀏覽器只會把它當文字原樣印出來。傳遞路徑:儲存型 vs 反射型 vs DOM 型
🎮 互動實驗室三:CSRF 時間線
逐步播放一個模擬情境:使用者登入網銀後沒登出,又開了一個惡意網頁。按「下一步」看瀏覽器如何自動帶著 Cookie 送出一筆非本人意願的轉帳。接著打開防禦開關再重播一次,看它在哪一步被擋下。
🎮 互動實驗室四:三兄弟分辨
看一段症狀描述,先判斷是哪一種攻擊,再挑出對應的根本防禦。兩題都答完才算過關,答錯會說明原因。情境皆為原創示意。
📘 原理補完
三個實驗室動手玩過之後,把它們接回正式的技術細節。最重要的一句:三者根本原因相近(輸入被當成指令或有效請求),受害對象卻不同,所以根本防禦也各自不同。
SQL 注入
打誰:後端資料庫。
根本原因:程式把輸入直接串接進 SQL 字串,資料庫分不出哪段是指令、哪段是使用者打的字。
根本防禦:參數化查詢(Prepared Statement),讓輸入永遠只當資料。
XSS 跨站腳本
打誰:其他使用者的瀏覽器。
根本原因:網站把使用者提交的內容直接顯示在頁面,沒有轉換特殊字元,腳本因此混進頁面被別人執行。
根本防禦:輸出編碼(HTML Encode)+內容安全政策(CSP)。
CSRF 跨站請求偽造
打誰:使用者已登入的身分。
根本原因:瀏覽器自動帶上登入 Cookie,網站沒確認請求是否為本人在站上主動發出。
根本防禦:CSRF Token+Cookie 設 SameSite,必要時重新驗證。
逐項比較
| 比較項目 | SQL 注入 | XSS | CSRF |
|---|---|---|---|
| 攻擊對象 | 後端資料庫 | 其他使用者的瀏覽器 | 使用者已登入的身分 |
| 是否需要執行腳本 | 否,送 SQL 片段 | 是,讓 JavaScript 在受害者瀏覽器跑 | 否,只是借身分送出請求 |
| 根本原因 | 指令與資料混在一起 | 輸出未編碼 | 信任「已登入」卻不驗證來源 |
| 根本防禦 | 參數化查詢 | 輸出編碼、CSP、Cookie 設 HttpOnly | CSRF Token、SameSite、檢查 Origin/Referer |
| 常見後果 | 撈出或竄改整個資料庫、繞過登入 | 竊取 Session Cookie、側錄輸入、導向釣魚頁 | 在使用者不知情下轉帳、改密碼 |
三者常互相牽動
它們並非完全獨立。XSS 常被用來竊取 Session Cookie,等於幫助攻擊者冒用身分;而一段成功的 XSS 腳本也能在受害者瀏覽器裡直接發出請求,繞過只靠 Token 的 CSRF 防禦。這說明為什麼防禦要一層一層疊:把 Cookie 設為 HttpOnly 讓腳本讀不到、用 CSP 限制可執行的腳本來源,都是在縮小 XSS 得手後能造成的傷害。
WAF:有用,但只是輔助
網頁攻擊都走正常的 80/443 埠,傳統防火牆看不出一個登入請求裡藏了注入語法。WAF(網頁應用防火牆,Web Application Firewall)通常以反向代理放在網站前面,逐一解析 HTTP 請求的網址、參數與內容,依規則攔下常見的注入與跨站腳本,也能做請求速率限制。當網站程式一時改不完,WAF 可以先擋在前面爭取時間,這叫虛擬修補。
但它有明確的限制。WAF 看不懂業務邏輯,對「這個使用者到底有沒有權限看這筆資料」這類越權問題幾乎無能為力;攻擊者也常用編碼、大小寫混用、拆字等方式改變請求內容來繞過規則。所以考試裡只要選項寫 WAF 能「完全阻擋」所有攻擊,通常就是錯的。
容易混淆與答錯的地方
只過濾特殊字元不算根治:只把單引號、分號或 < 過濾掉是黑名單思維,攻擊者能用編碼或變形繞過。防 SQL 注入要用參數化查詢,防 XSS 要在顯示時做輸出編碼,兩者都不是靠過濾幾個字元。
參數化查詢防的是 SQL 注入,不是 XSS:這是常見的張冠李戴。反過來,輸出編碼防的是 XSS,對 SQL 注入沒幫助。
輸入驗證 vs 輸出編碼:輸入驗證在資料進來時擋掉不合格內容(最好用白名單、且在伺服器端做,因為前端檢查可被繞過);輸出編碼在顯示時讓內容無法被當成程式碼執行。防 XSS 兩者最好都做,但真正的關鍵是輸出編碼。
XSS vs CSRF:XSS 要讓惡意腳本在受害者瀏覽器執行;CSRF 不需要執行任何腳本,只是借用受害者已登入的身分送出一筆請求。
CSRF 不屬於注入類別:OWASP 的「注入」包含 SQL、OS 命令、LDAP 注入與 XSS,但不包含 CSRF。與 CSRF 相關的還有 Session 連線劫持(竊取或預測 Session ID 冒用登入),對策是加密連線、登入後更換 Session ID、閒置自動登出。
✅ 自我檢測
以下 6 題都是原創情境題,選完立即顯示對錯與解析。目前得分:0 / 6
🎯 重點整理
- 三者根本原因相近(輸入被當成指令或有效請求),但打的對象不同:SQL 注入打資料庫、XSS 打其他使用者的瀏覽器、CSRF 借用已登入的身分。
- SQL 注入的根本防禦是參數化查詢,讓輸入永遠只當資料;只過濾特殊字元、加 MFA、資料庫加密都無法根治。
- XSS 的根本防禦是輸出編碼,再加 CSP 與 Cookie 設 HttpOnly;主要語言是 JavaScript,常用來偷 Session Cookie。
- XSS 分三型:儲存型存在伺服器、影響所有訪客、危害最大;反射型藏在網址要誘騙點擊;DOM 型由前端腳本寫入頁面。
- CSRF 的根本防禦是CSRF Token+SameSite Cookie,並檢查 Origin/Referer、重要操作重新驗證;CSRF 不屬於注入類別。
- WAF 是輔助不是根治:能擋明顯攻擊樣式與暴量請求,但看不懂業務邏輯、擋不了越權,也可能被編碼變形繞過;選項寫「完全阻擋」就是錯的。
- 別張冠李戴:參數化查詢防 SQL 注入、輸出編碼防 XSS、Token 與 SameSite 防 CSRF。