首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL 注入攻擊原理與防禦全攻略:參數化查詢、型別檢查、編碼函數

     編輯:關於SqlServer

SQL 注入本質

將使用者輸入的資料當作SQL 命令執行。根因:字串拼接構建 SQL,未使用參數化查詢。

經典攻擊演示

-- 正常查詢
SELECT id, no FROM user WHERE id = 2;

-- 攻擊輸入:2 OR 1=1
SELECT id, no FROM user WHERE id = 2 OR 1=1;  -- 返回全表

-- 攻擊輸入:2; DROP TABLE sqlinject; --
-- 刪除資料表!

三層防禦體系

第一層:參數化查詢(預編譯 + 綁定變數)—— 最佳、首選

String sql = "SELECT id, no FROM user WHERE id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id);  -- 型別安全綁定
ps.executeQuery();

原理:SQL 引擎在預編譯階段完成語法分析、生成執行計畫。後續參數只作為字面值,絕不參與語法解析,故 OR 1=1 等片段不會被視為命令。

第二層:嚴格型別檢查與正則驗證(無法用參數化時)

-- 應用層驗證
if (!input.matches("\\d+")) throw new IllegalArgumentException("ID 必須為整數");
String sql = "SELECT * FROM user WHERE id = " + input; // 相對安全
  • 數值型:Integer.parseInt() 捕獲異常
  • 字串型:白名單正則、長度限制
  • 識別碼型:^[a-zA-Z0-9_]+$

第三層:安全編碼函數(最後防線)

MySQLCodec codec = new MySQLCodec(Mode.STANDARD);
String safeName = ESAPI.encoder().encodeForSQL(codec, name);
String sql = "SELECT * FROM user WHERE name = " + safeName;

encodeForSQL 將特殊字元(引號、分號、註解符等)轉義,使其喪失 SQL 命令語意。

框架層面的對應

防禦清單

  1. 全專案禁用字串拼接 SQL,Code Review 必查
  2. 所有動態查詢統一用參數化
  3. 資料庫帳號最小權限(讀/寫分離、無 DROP 權限)
  4. 錯誤訊息不回傳給前端(避免資訊洩露輔助盲注)
  5. 部署 WAF(Web Application Firewall)攔截已知攻擊特徵
  6. 定期掃描:SQLMap、OWASP ZAP 自動化檢測

總結

參數化查詢是銀彈。 只要 SQL 與資料分離,注入就失去立足之地。其他手段只是防禦深度的補充。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
框架參數化語法非參數化(危險)
MyBatis#{param}${param}
iBATIS#param#$param$
Hibernate/JPA? / :name (HQL/Criteria)字串拼接 HQL