理解敵人是防禦前提。本文系統梳理 SQL 注入的核心攻擊向量——從基礎條件操控到毀滅性的多語句注入,並深入分析 MySQL、MySQLi、SQLite 在多查詢處理上的差異,為制定分級防禦策略提供理論支撐。
原查詢:SELECT * FROM wines WHERE variety = 'lagrein'
注入載荷:lagrein' OR 1=1;--
結果:SELECT * FROM wines WHERE variety = 'lagrein' OR 1=1;--'
危害:繞過認證、遍歷敏感表、推斷 Schema 結構。
原查詢:UPDATE wines SET type='red' WHERE variety = 'lagrein'
注入載荷:lagrein', vintage='9999' WHERE 1=1;--
結果:UPDATE wines SET type='red', vintage='9999' WHERE 1=1;--'
危害:任意字段修改、全表數據破壞、繞過業務邏輯約束。
注入載荷:lagrein' OR 1=1;--
結果:DELETE FROM wines WHERE variety = 'lagrein' OR 1=1;--'
危害:不可逆的全表數據刪除,災難恢復成本極高。
利用分號終止原語句,追加任意惡意 SQL:
原查詢: SELECT * FROM wines WHERE variety = 'lagrein'
注入後: SELECT * FROM wines WHERE variety = 'lagrein'; GRANT ALL ON *.* TO 'BadGuy@%' IDENTIFIED BY 'gotcha';--
理論後果:創建超級用戶、竊取數據、植入後門、執行系統命令(若啟用 INTO OUTFILE/LOAD DATA)。
mysql_query() 僅執行首條語句,其餘靜默失敗,**意外成為天然防線** |
| **PHP mysqli 擴展** | ❌ 預設禁止 / ✅ 可開啟 | 提供 mysqli_multi_query() 顯式支援,預設單查詢模式安全 |
| **PDO MySQL** | ❌ 預設禁止 | PDO::MYSQL_ATTR_MULTI_STATEMENTS 可開啟,但預設安全 |
| **SQLite (PHP 5 綁定)** | ⚠️ **部分支援** | 批量 INSERT 優化導致默認允許多語句;但 sqlite_query() 若需返回結果集則禁止多查詢 |
SELECT/INSERT/UPDATE/DELETE,無 GRANT/DROP/CREATE)。mysqli_multi_query、PDO::MYSQL_ATTR_MULTI_STATEMENTS 除非極少數批量導入場景。💡 PHP 舊版 mysql_query() 「不支援多查詢」的特性,曾在歷史上默默保護了無數未參數化的應用。但這絕非可依賴的防線——升級驅動、遷移數據庫、啟用新特性都可能打破這層屏障。唯有參數化查詢是永恆的正解。