update语句比select更危险,因其直接修改数据且sql注入高发于set字段名、where条件绕过、mybatis ${}误用等场景,须用白名单+preparedstatement严防。

Update 语句比 Select 更危险——它不只读数据,还改数据,而开发者常因“只是更新字段”放松警惕,误以为参数少、逻辑简单就安全。实际上,UPDATE 是 SQL 注入高发区,尤其在后台管理、状态批量变更、用户资料修改等场景下,漏洞一旦触发,直接导致数据被篡改或清空。
为什么 Update 语句更容易被绕过防护?
不是没加 PreparedStatement,而是加了也白加——因为拼接点藏在 WHERE 条件之外,或者混用了拼接与绑定。
- WHERE 子句用了 ? 参数,但 SET 部分拼接了字段名:比如
"UPDATE users SET " + fieldName + " = ? WHERE id = ?"——fieldName无法参数化,攻击者可填入password = 'xxx', email = 'a@b.com'实现多字段覆盖 - 整数型 ID 参数只做
Integer.parseInt(),但没拦截1 OR 1=1这类表达式,数据库仍会执行UPDATE users SET status='blocked' WHERE id = 1 OR 1=1,全表更新 - MyBatis 中误用
${column}动态设字段,而非#{value}绑定值,例如SET ${updateField} = #{newValue}——${updateField}直接代入,等于开放 SQL 注入入口
哪些 Update 场景最常踩坑?
后台批量操作、状态切换、富文本内容更新,表面看是“固定字段”,实则输入路径复杂、校验松散。
-
/admin/update?ids=1,2,3&status=disabled:逗号分隔的 ID 列表若未拆解校验,直接拼进IN (?)就失效;正确做法是用循环 bind 或构建预编译的 IN 占位符序列(如IN (?,?,?)) - 用户提交 JSON 更新多个字段:
{"name":"Alice","bio":"...","avatar_url":"..."},后端若用反射+字符串拼接生成 SET 子句,且未限制可更新字段白名单,攻击者可注入"bio":"xxx', role='admin'-- " - 导出 Excel 后回写状态:
UPDATE ${tableName} SET sync_status = 'done' WHERE id IN (${idList})——${tableName}和${idList}全部不可控,双注入点
怎么验证你的 Update 是否真安全?
别只测“能跑”,要测“恶意输入是否被拦截”。关键看三件事:
- 所有动态部分(字段名、表名、ORDER BY、LIMIT 偏移量)必须来自白名单,不能由用户输入决定;哪怕只允许
status和is_active两个字段更新,也要硬编码判断,而不是正则匹配 - 所有用户可控值(包括 URL 参数、JSON 字段、表单 input)必须走
PreparedStatement的setXxx()方法,禁止任何形式的字符串拼接参与 SQL 构建 - 日志里出现
UPDATE ... WHERE ... = 'xxx'这种带引号的原始 SQL,说明底层可能用了Statement或拼接,立刻排查
真正难防的不是“会不会写 PreparedStatement”,而是“哪一段字符串你以为是数据,其实它是代码”。Update 语句里,字段名、表名、条件逻辑都可能是攻击面,而它们恰好不在参数占位符覆盖范围内——这个边界,必须靠白名单和静态检查守住,不能靠 runtime 转义补救。











