SQL注入是最经典也最危险的Web安全漏洞之一,每年仍有大量企业因此遭受数据泄露。攻击者通过在输入中嵌入SQL语句,欺骗后端执行恶意SQL命令。本文系统讲解SQL注入的原理和多种防御方案。
SQL注入攻击原理
正常请求:GET /users?id=1,后端执行 SELECT * FROM users WHERE id = 1。恶意请求:GET /users?id=1 OR 1=1,后端执行 SELECT * FROM users WHERE id = 1 OR 1=1,返回所有用户数据。更严重的:id=1; DROP TABLE users,可能导致数据丢失。注入点包括查询参数、请求体、请求头甚至Cookie。参数化查询和输入转义是防御的核心手段。
参数化查询优先
参数化查询(PreparedStatement)是防御SQL注入最有效的手段。它将SQL语句和数据参数分离,数据库先编译SQL模板再绑定参数,参数中的特殊字符不会被当作SQL指令执行。Java的PreparedStatement、PHP的PDO、Python的数据库cursor都支持参数化查询。任何时候都不要拼接SQL字符串,即使是表名和字段名也尽量使用白名单校验。
ORM框架安全使用
ORM框架如Hibernate、MyBatis、Entity Framework等内置了参数化查询机制,但使用不当仍然存在风险。MyBatis的$符号直接拼接参数,会引入注入风险,应该用#符号代替。Hibernate的原生SQL查询同样需要使用参数化方式。ORM框架的动态查询也要注意,使用Criteria API或QueryDSL这类类型安全的查询构建器比字符串拼接更安全。
多层防御体系
不能只依赖数据库层的防御。输入层:参数类型校验和特殊字符过滤。应用层:参数化查询和ORM安全使用。数据库层:最小权限原则,应用账号只有必要的表权限,禁止DROP、TRUNCATE等高危操作。WAF层:部署Web应用防火墙过滤恶意请求。存储过程:将SQL逻辑封装在存储过程中,应用层只传递参数。多层防御即使某一层被绕过,其他层仍然能起到保护作用。