將使用者輸入的資料當作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 命令語意。
| 框架 | 參數化語法 | 非參數化(危險) |
|---|---|---|
| MyBatis | #{param} | ${param} |
| iBATIS | #param# | $param$ |
| Hibernate/JPA | ? / :name (HQL/Criteria) | 字串拼接 HQL |