歡迎光臨
我們一直在努力

登入框為什麼會出現 SQL Injection

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

登入功能同時處理身分、密碼與 Session,一旦查詢邏輯被外部資料改變,影響通常比一般搜尋更大。這篇不教繞過真實登入,而是拆解錯誤查詢如何形成,並把認證設計修到正確。

安全登入流程技術流程圖
安全登入流程:依序追蹤資料與安全控制點。

本篇會學到什麼

  • 理解帳號查詢與密碼驗證應分成兩個安全步驟
  • 辨識把 Email 與密碼一起拼進 SQL 的風險
  • 建立不洩漏帳號是否存在的回應與日誌

必備名詞與心智模型

安全登入不是『SQL 查到一列就算成功』。應先用參數化查詢依唯一識別資料取得帳號,再由專用密碼函式驗證雜湊,最後才建立 Session。資料庫不應保存明文密碼,也不該讓前端決定角色。

發生情境與生活化比喻

虛構商店的登入框收到 email 與 password。生活化比喻是櫃台先用名冊找到會員,再由獨立程序核對證件;不能讓訪客自己改寫名冊查詢規則。相同風險也會出現在管理後台、API token 查詢與忘記密碼流程。

不安全的原始碼

$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
$sql = "SELECT id,role FROM users WHERE email='" . $email
     . "' AND password='" . $password . "'";
$user = $pdo->query($sql)->fetch();

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

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

  1. 兩個 POST 值跨過 HTTP 信任邊界
  2. 程式把值、引號與 AND 條件組成同一字串
  3. 資料庫重新解析整段文字,無法分辨原始資料邊界
  4. 只要查詢結果非空,程式就錯誤地視為已完成認證
  5. 明文密碼與過大資料庫權限讓後果繼續擴大

修補後原始碼

$statement = $pdo->prepare(
    'SELECT id,email,role,password_hash FROM users WHERE email=:email'
);
$statement->execute(['email' => $_POST['email'] ?? '']);
$user = $statement->fetch(PDO::FETCH_ASSOC);
$valid = $user && password_verify($_POST['password'] ?? '', $user['password_hash']);
if (!$valid) { /* 回傳統一的登入失敗訊息 */ }

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

如何驗證修補

  • 正確帳密成功,錯誤密碼與不存在帳號都回傳同一外部訊息
  • Email 中的引號與 Unicode 不產生 SQL 錯誤
  • Session ID 在登入後更新,角色只取自資料庫
  • 日誌記錄事件 ID、來源與結果,但不記密碼


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

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

把原理放回真實開發情境

登入應先依帳號取回單一使用者,再用密碼雜湊驗證;驗證成功後才建立 Session。 實作時不要只盯著畫面上的輸入框,還要檢查 API 參數、伺服器端預設值、資料轉換與最後呼叫的資料庫介面。最實用的閱讀方式,是把每一段程式標成「外部來源、轉換、控制、資料庫 sink」,確認資料值沒有在途中重新變回 SQL 結構。

常見誤判

把錯誤訊息改成『帳號或密碼錯誤』只能減少枚舉,不能修補字串拼接。 安全判斷不能只靠畫面、單次錯誤或某一個防護產品;應同時看原始碼、驅動程式實際執行方式、資料庫權限與回歸測試。若無法證明查詢結構固定,就應把它視為待修的設計風險。

開發與 SOC 可以觀察什麼

監控同來源短時間大量失敗、不同帳號輪詢與異常查詢錯誤,但避免把密碼寫入日誌。 日誌宜記錄時間、路由、請求關聯 ID、查詢名稱、結果狀態與耗時,敏感值則遮罩或雜湊。偵測規則的用途是縮短發現時間;阻擋之後仍須回到程式碼修補,並搜尋其他共用元件與相同資料流。

審查時的三個追問

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

開發與維運防禦清單

  • 使用 password_hash/password_verify,不自製密碼雜湊
  • 登入查詢只需 SELECT,帳號不可擁有 DDL 權限
  • 速率限制與 MFA 降低撞庫風險,但不能取代參數化
  • 審查忘記密碼、SSO callback 與後台登入的相同資料流

重點整理與下一篇

登入框顯示了值參數的典型防禦。下一篇會處理搜尋、篩選、排序與分頁,特別說明為什麼欄位名不能直接用 placeholder。

參考資料與更新日期

更新日期:2026-07-20

贊(0) 贊助
未經允許不得轉載:波波的寂寞世界 » 登入框為什麼會出現 SQL Injection

波波的寂寞世界

Facebook聯繫我們

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

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

贊助本站