SQL 注入 (SQLi)
Published: Sat Feb 01 2025 | Modified: Fri Feb 06 2026 , 2 minutes reading.
1. 定義
SQL 注入 (SQL Injection, SQLi) 發生在不受信任的用戶輸入被動態拼接至結構化查詢語言 (SQL) 語句中時。這允許攻擊者操縱查詢結構,從而查看、修改或刪除他們未被授權訪問的數據。
2. 技術原理
SQL 解釋器會同時處理指令和數據。如果應用程式通過字串拼接來構建查詢:
query = "SELECT * FROM users WHERE username = '" + user_input + "'";攻擊者可以輸入 ' OR '1'='1。生成的查詢將變為:
SELECT * FROM users WHERE username = '' OR '1'='1';由於 '1'='1' 永遠為真,資料庫將返回表中的所有行,從而繞過用戶名檢查。
SQLi 的類型:
- 帶內 (In-band, 經典型): 結果直接返回在網頁中(如基於 UNION 的注入)。
- 盲注 (Blind): 不直接返回數據,但應用程式的行為會發生變化(基於時間或布爾值)。
- 帶外 (Out-of-band): 通過 DNS 或 HTTP 請求將數據導出(較罕見,取決於資料庫)。
3. 攻擊流程 (基於 Union)
sequenceDiagram
participant Attacker
participant App
participant DB as 資料庫
Attacker->>App: GET /search?q=' UNION SELECT username, password FROM users--
Note over App: 程式碼構建查詢:<br/>SELECT title FROM products WHERE name = '' UNION ... --'
App->>DB: 執行畸形查詢
Note over DB: 'UNION' 合併了來自 'products' 和 'users' 的結果
DB-->>App: 返回產品列表 + 用戶憑據
App-->>Attacker: 在搜尋結果中顯示管理員密碼4. 真實案例:TalkTalk 遭受黑客攻擊 (2015)
目標: TalkTalk (英國電信營運商)。 漏洞類別: 盲 SQL 注入。
事件回顧: 攻擊者在 TalkTalk 網域上發現了一些未維護的舊網頁,這些網頁仍然連接著核心客戶資料庫。這些頁面使用的 GET 參數存在 SQL 注入漏洞。
攻擊技術: 他們使用 SQLMap(一種自動化工具)利用了盲 SQLi 漏洞。
- 注入 SQL 命令來提取資料庫架構資訊。
- 導出了 156,959 名客戶 的個人資料和 15,000 多個銀行帳號。
影響: TalkTalk 被處以 40 萬英鎊 的罰款(當時創下了紀錄),並估計在業務流失和補救方面損失了 7700 萬英鎊。這凸顯了「殭屍」遺留程式碼帶來的巨大風險。
5. 深度防禦策略
A. 預處理語句 (參數化查詢)
這是唯一的主要防禦手段。 使用資料庫驅動提供的參數化功能,而不是字串拼接。
機制: SQL 查詢結構先被發送到資料庫並編譯。用戶輸入隨後發送,且僅被視為數據,而非可執行的程式碼。
Java/JDBC 範例:
String query = "SELECT * FROM users WHERE username = ?"; PreparedStatement pstmt = connection.prepareStatement(query); pstmt.setString(1, userInput); // 安全 ResultSet results = pstmt.executeQuery();
B. 存儲程序
將查詢封裝在資料庫內部。但請注意,存儲程序本身必須使用參數,並避免在程序內部生成動態 SQL。
C. 最小權限原則
Web 應用程式使用的資料庫帳號應僅擁有以下權限:
- 僅訪問其所需的特定表。
- 僅執行必要的命令(
SELECT,INSERT,UPDATE)。 - 絕不擁有
DROP TABLE,GRANT或管理員權限。 - 絕不允許訪問作業系統檔案系統(如
xp_cmdshell)。
