Update 攻击技术.md

补充预处理语句在 MySQL 驱动中的执行方式。
This commit is contained in:
CyC2018
2026-10-26 22:04:05 +08:00
parent 74dc880742
commit d446e7bd69
+8
View File
@@ -194,6 +194,14 @@ stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();
```
需要注意的是,MySQL 的 JDBC 驱动(Connector/J)默认并不在服务器上预编译,而是在客户端把参数中的单引号等字符转义后,拼成完整的语句发送。在本机用 Connector/J 8.3 执行上面的查询,两个参数都传入 1' OR '1'='1,MySQL 通用查询日志中记录的是:
```text
Query SELECT * FROM users WHERE name = '1'' OR ''1''=''1' AND pw = '1'' OR ''1''=''1'
```
参数仍然只是一个普通的字符串,查询结果为空。连接参数加上 useServerPrepStmts=true 后,驱动才会先发送 Prepare、再发送 Execute。两种方式都能防止注入,关键在于参数由驱动或数据库处理,而不是由开发者拼接。表名、列名和 ORDER BY 的字段不能使用占位符,只能用白名单校验,见 [MyBatis 的 #{} 和 ${}](Spring.md#-和--的区别)。
#### 2. 单引号转换
将传入的参数中的单引号转换为连续两个单引号。PHP 的 Magic Quotes 曾经自动完成这个功能,但是因为不可靠已经被移除,应该使用数据库驱动提供的转义函数,并且只在无法使用参数化查询时使用。