歡迎光臨
我們一直在努力

搜尋、篩選、排序與分頁欄位的注入風險

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

商品搜尋看似只讀,卻常同時接受關鍵字、分類、價格、排序欄位、方向與頁碼。這些輸入落在 SQL 的不同位置,不能全部用 escaping 或同一個 placeholder 解決。

列表查詢的三種控制技術流程圖
列表查詢的三種控制:依序追蹤資料與安全控制點。

本篇會學到什麼

  • 區分資料值、SQL 識別字與語法關鍵字
  • 安全處理 LIKE、IN、ORDER BY、LIMIT
  • 避免分頁型別錯誤與高成本查詢

必備名詞與心智模型

搜尋詞與價格是值,適合參數化;排序欄位與 ASC/DESC 是 SQL 結構,應由外部代碼映射到固定片段;頁碼與筆數要轉成整數並限制範圍。LIKE 的百分比是搜尋規則,可放進綁定值。

發生情境與生活化比喻

虛構商品頁允許搜尋名稱、選分類、依價格排序並翻頁。就像圖書館讀者可填關鍵字,但只能從館方提供的排序規則選擇,不能自己寫資料庫的 ORDER BY 子句。

不安全的原始碼

$q = $_GET['q'] ?? '';
$sort = $_GET['sort'] ?? 'name';
$page = $_GET['page'] ?? '1';
$sql = "SELECT id,name,price FROM products WHERE name LIKE '%$q%' "
     . "ORDER BY $sort LIMIT 20 OFFSET " . (($page - 1) * 20);

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

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

  1. q 被插進字串 literal
  2. sort 直接成為 SQL 結構
  3. page 依賴 PHP 隱式型別轉換
  4. 同一查詢有三條不同資料流與三種修補方式
  5. 只修搜尋詞仍不代表整條查詢安全

修補後原始碼

$allowedSorts = ['name'=>'name ASC','price_asc'=>'price ASC','price_desc'=>'price DESC'];
$order = $allowedSorts[$_GET['sort'] ?? 'name'] ?? $allowedSorts['name'];
$page = filter_var($_GET['page'] ?? 1, FILTER_VALIDATE_INT,
    ['options'=>['min_range'=>1,'max_range'=>500]]) ?: 1;
$offset = ($page - 1) * 20;
$stmt = $pdo->prepare("SELECT id,name,price FROM products
    WHERE name LIKE :q ORDER BY {$order} LIMIT 20 OFFSET {$offset}");
$stmt->execute(['q'=>'%' . ($_GET['q'] ?? '') . '%']);

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

如何驗證修補

  • 合法排序代碼各自得到正確順序
  • 未知排序值固定回到 name ASC
  • 頁碼 0、負數、文字與過大值被拒絕或收斂
  • 含引號的正常商品名仍可搜尋
  • 慢查詢日誌能辨識異常高成本請求


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

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

把原理放回真實開發情境

搜尋詞與分類用參數;排序鍵映射到固定欄位;頁碼轉整數並設定最大頁面大小。 實作時不要只盯著畫面上的輸入框,還要檢查 API 參數、伺服器端預設值、資料轉換與最後呼叫的資料庫介面。最實用的閱讀方式,是把每一段程式標成「外部來源、轉換、控制、資料庫 sink」,確認資料值沒有在途中重新變回 SQL 結構。

常見誤判

Prepared Statement 不能直接綁定欄位名或 ASC/DESC,把它們當參數通常不是有效解法。 安全判斷不能只靠畫面、單次錯誤或某一個防護產品;應同時看原始碼、驅動程式實際執行方式、資料庫權限與回歸測試。若無法證明查詢結構固定,就應把它視為待修的設計風險。

開發與 SOC 可以觀察什麼

觀察極大 offset、反常排序組合、重複查詢錯誤與昂貴查詢時間,兼顧安全及可用性。 日誌宜記錄時間、路由、請求關聯 ID、查詢名稱、結果狀態與耗時,敏感值則遮罩或雜湊。偵測規則的用途是縮短發現時間;阻擋之後仍須回到程式碼修補,並搜尋其他共用元件與相同資料流。

審查時的三個追問

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

開發與維運防禦清單

  • 值一律參數化,識別字一律映射固定清單
  • 限制關鍵字長度、頁數與每頁筆數
  • 不要把前端 select 選項視為安全控制
  • 對報表與匯出查詢設定逾時與資源限制

重點整理與下一篇

下一篇進入 UNION 型注入,重點不是背語法,而是理解兩個 SELECT 為何需要相容的欄位數與型別,以及防禦為何仍回到查詢邊界。

參考資料與更新日期

更新日期:2026-07-20

贊(0) 贊助
未經允許不得轉載:波波的寂寞世界 » 搜尋、篩選、排序與分頁欄位的注入風險

波波的寂寞世界

Facebook聯繫我們

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

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

贊助本站