歡迎光臨
我們一直在努力

MySQL SQL Injection 特性與安全實作

安全提醒:本文為防禦導向的虛構案例與不可部署片段;測試僅限自有或明確授權環境。

MySQL 是 PHP 與 WordPress 常見資料庫,但『用了 MySQLi/PDO』不等於自動安全。應用程式若將資料串進 SQL、允許 multiple statements、誤用字元集或給帳號過大權限,仍可能發生注入。

MySQL 安全資料存取技術流程圖
MySQL 安全資料存取:依序追蹤資料與安全控制點。

本篇會學到什麼

  • 理解 MySQL 型別轉換、註解與連線選項對風險判讀的影響
  • 正確使用 PDO MySQL native prepared statements
  • 為 WordPress/PHP 應用配置最小資料庫權限

必備名詞與心智模型

MySQL server 只看最後收到的 SQL。真正安全的邊界通常由驅動建立:查詢模板與參數分開傳遞。PDO 可使用模擬預處理,這不代表所有用法都危險,但複雜解析與反斜線規則可能有差異;新程式宜關閉模擬並遵守每個值使用獨立 placeholder。

發生情境與生活化比喻

商品分類頁用 MySQL 查詢 category、price 與排序。常見誤區包括把數字不加引號就直接拼接、用 addslashes 代替參數化、忘記明確設定 utf8mb4、以及讓網站帳號持有 CREATE USER 或全域權限。

不安全的原始碼

$min = $_GET['min'] ?? 0;
$category = $_GET['category'] ?? '';
$sql = "SELECT id,name,price FROM products WHERE price >= $min "
     . "AND category='$category'";
$rows = $pdo->query($sql)->fetchAll();

此片段刻意省略連線、路由與部署設定,只用來辨識資料流,請勿放入任何服務。

逐步看懂資料如何變成查詢

  1. min 即使畫面是數字,HTTP 傳入仍是可修改字串
  2. category 位於單引號 literal,手動 escaping 依賴正確字元集與所有路徑一致
  3. MySQL 解析完整查詢並套用自己的型別轉換
  4. 網站帳號權限決定漏洞最多能讀寫什麼
  5. 錯誤模式與慢查詢日誌可能暴露或偵測異常

修補後原始碼

$pdo = new PDO($dsn, $user, $password, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
]);
$min = filter_var($_GET['min'] ?? 0, FILTER_VALIDATE_FLOAT);
$stmt = $pdo->prepare('SELECT id,name,price FROM products
    WHERE price >= :min AND category = :category');
$stmt->execute(['min'=>$min, 'category'=>$_GET['category'] ?? '']);

修補的共同原則是先固定 SQL 結構,再把值獨立綁定;無法作為值綁定的識別字只能從程式內允許清單產生。

如何驗證修補

  • 確認連線 DSN 明確使用 utf8mb4
  • PDO 模擬預處理設定符合團隊決策並有整合測試
  • 數字的空值、科學記號、負數與上限有業務規則
  • 網站帳號只有需要的 schema/table 權限
  • 一般引號與多語言分類名稱保持可用


閱讀提醒:以下分析的目的,是讓你能在自己的程式、測試資料與授權環境中辨識風險。面對正式系統時,先取得明確授權並保存變更紀錄;不要用錯誤訊息或一次回應就推論資料外洩,也不要把文章中的概念改造成自動化探測。安全工作的完成條件,是能說明根因、修補位置、回歸結果與剩餘風險。

更多應用情境、常見誤判與觀察方法

把原理放回真實開發情境

MySQL 實作同時確認原生預備語句、utf8mb4、嚴格模式與最小權限應用帳號。 實作時不要只盯著畫面上的輸入框,還要檢查 API 參數、伺服器端預設值、資料轉換與最後呼叫的資料庫介面。最實用的閱讀方式,是把每一段程式標成「外部來源、轉換、控制、資料庫 sink」,確認資料值沒有在途中重新變回 SQL 結構。

常見誤判

更換資料庫引擎、啟用 WAF 或套用 addslashes 都不會自動消除應用程式的動態 SQL。 安全判斷不能只靠畫面、單次錯誤或某一個防護產品;應同時看原始碼、驅動程式實際執行方式、資料庫權限與回歸測試。若無法證明查詢結構固定,就應把它視為待修的設計風險。

開發與 SOC 可以觀察什麼

追蹤語法錯誤、截斷警告、權限拒絕與慢查詢;管理帳號不可作為網站日常連線帳號。 日誌宜記錄時間、路由、請求關聯 ID、查詢名稱、結果狀態與耗時,敏感值則遮罩或雜湊。偵測規則的用途是縮短發現時間;阻擋之後仍須回到程式碼修補,並搜尋其他共用元件與相同資料流。

審查時的三個追問

  1. 這個值最早由誰控制,經過哪些轉換?
  2. 它在資料庫呼叫中是資料值,還是欄位、排序、運算式等結構?
  3. 若預防失效,最小權限、監控與事件流程能限制並發現多少影響?

開發與維運防禦清單

  • 不以 magic quotes、addslashes 或 WAF 取代 bind parameter
  • 關閉不需要的 multiple statements 能力
  • 依讀寫工作拆分帳號並限制 GRANT
  • 監控 MySQL error log、slow query 與大量相似失敗

重點整理與下一篇

MySQL 的 placeholder 與型別行為不能直接套用到所有資料庫。下一篇比較 SQL Server 的 T-SQL、批次語句、sp_executesql 與 ADO.NET 參數。

參考資料與更新日期

更新日期:2026-07-20

贊(0) 贊助
未經允許不得轉載:波波的寂寞世界 » MySQL SQL Injection 特性與安全實作

波波的寂寞世界

Facebook聯繫我們

覺得文章有幫助,歡迎贊助支持本站

感謝你的支持,我會持續整理資安筆記、實務經驗與有價值的技術內容。

贊助本站