sql注入需全链路防御,不能仅靠预编译或waf;必须严格校验动态sql元素(如表名、排序字段)、最小化数据库权限、慎用orm原始查询、监控异常查询模式,并在各环节设置可验证检查点。

SQL注入不是靠某一个补丁能堵住的,它暴露的是整个数据访问链路的设计缺陷。光用预编译语句(PreparedStatement)或过滤函数(mysqli_real_escape_string)只能拦住表层攻击,绕过方式太多。
为什么参数化查询仍可能被绕过
参数化查询本身安全,但开发者常在「不该拼接的地方硬拼」。比如动态表名、字段名、ORDER BY 子句、LIMIT 偏移量——这些无法用占位符绑定,却常被直接插入 SQL 字符串。
- 错误示例:
"SELECT * FROM " + table_name + " WHERE id = ?"——table_name来自用户输入且未白名单校验 - 正确做法:只允许从预定义枚举中选表名,如
["users", "orders", "products"],用in_array($table_name, $allowed_tables, true)校验 - 排序字段同理:把
sort=created_at&order=desc映射为白名单键值对,而非直插字符串 - 注意 MySQL 8.0+ 的
PREV/NEXT窗口函数、JSON 函数等新语法,也可能成为拼接盲区
WAF 和数据库配置不是保险丝,而是最后一道筛子
依赖 WAF(如 ModSecurity)拦截 ' OR 1=1 -- 这类特征,本质是“用正则防语法”,漏报率高;而数据库层面关闭 information_schema 或禁用 LOAD_FILE,只能限制利用深度,不能阻止注入发生。
一款AI开发辅助工具,主要用于通过后台进程将编码任务委托给 Codex、Claude Code 或 Pi 智能体。适用场景:(1)构建或创建新功能/应用,(2)审查 PR,适合需要提升相关任务效率的用户。
- 必须关闭 MySQL 的
secure_file_priv(设为NULL或空目录),否则攻击者仍可通过SELECT ... INTO OUTFILE写 Webshell - 应用连接数据库的账号权限要最小化:不给
DROP、CREATE、FILE、PROCESS权限,连SHOW DATABASES都应禁止 - PostgreSQL 要禁用
pg_read_file()、dblink_connect()等高危函数,通过REVOKE显式收回 - WAF 规则需定期更新,尤其关注绕过手法:如用
%27替换单引号、用/**/绕过空格检测、用UNION/*comment*/SELECT拆分关键字
ORM 和 Query Builder 的陷阱比原生 SQL 更隐蔽
很多人以为用了 Laravel Eloquent 或 Django ORM 就自动免疫,其实不然。当调用 whereRaw()、DB::select(DB::raw(...))、extra()、annotate() 或原生 SQL 方法时,参数化保护立即失效。
- Laravel 中避免
whereRaw("status = '" . $input . "'"),改用whereRaw("status = ?", [$input])或更推荐的where('status', $input) - Django 的
extra(where=["name LIKE '%" + keyword + "%"])是典型雷区,应改用filter(name__icontains=keyword) - MyBatis 的
${}是字符串替换,#{}才是预编译——但很多人在<bind></bind>或动态 SQL 中误用${}拼接列名 - 所有 ORM 的「原始查询」接口都应打上显眼注释,并纳入代码扫描规则(如 SonarQube 检查
raw/execute/unsafe关键字)
日志和监控不能只记「谁查了什么」,得盯住「异常查询模式」
单纯记录 SQL 日志没用,关键是要识别出偏离基线的行为:比如单次请求执行 50 条 SELECT、响应时间突增 10 倍、返回行数远超预期、出现 information_schema.columns 查询等。
- 在应用层加轻量钩子:用 AOP 或中间件捕获所有 DB 查询,统计耗时、结果集大小、关键词(
UNION SELECT、CONCAT(、CHAR()并采样上报 - 数据库代理层(如 ProxySQL、MySQL Router)可配置查询重写规则,把含
@@version、user()的语句直接拒绝 - ELK 或 Loki 中建立告警规则:如 1 分钟内同一 IP 出现 3 次含
--或#注释的查询,触发人工核查 - 注意:不要在日志里记录完整 SQL 参数值(尤其密码、token),避免二次泄露
最危险的不是不知道怎么防,而是以为某个环节防住了就万事大吉。真实攻防中,SQL 注入常是多点突破——前端绕过校验、后端信任内部 API、DBA 忘记回收测试账号权限、监控日志只存 7 天。防御方案必须在每个环节留下可验证的检查点,而不是堆砌工具。










