sql注入漏洞修复方案
一个凌晨两点,入漏某电商平台数据库里躺着近百万条用户记录。洞修攻击者只用了半行代码,复方就把这些数据全拖走了。入漏事后排查发现,洞修漏洞出在一个搜索框——用户输入的复方商品名直接被拼进了SQL语句,中间连个过滤都没有。入漏这不是洞修个例,OWASP连续多年把SQL注入列为十大安全风险之首,复方但直到今天,入漏仍有大量站点在裸奔。洞修
修复思路其实就三板斧:参数化查询、复方输入验证、入漏最小权限。洞修但真落地时,复方细节里全是坑。
先说参数化查询。这是最根本的解法,原理很简单——SQL语句的结构和参数分开传,数据库只认结构,参数永远只是数据,再诡异的输入也变不成代码。比如Java里用PreparedStatement,PHP用PDO预处理,Python用参数占位符。但问题来了,很多老系统里到处是拼接字符串的写法,改起来工程量大不说,业务逻辑还容易改出bug。我见过一个团队,花了三周把几千处拼接改成参数化,结果上线当晚订单模块直接崩了——有个报表功能用了动态列名,参数化根本搞不定,最后只能靠白名单硬扛。
再说输入验证。这层是第二道防线,但别指望它兜底。很多人爱写黑名单,过滤单引号、关键字、注释符,这思路从一开始就错了——黑名单永远有漏网之鱼,编码绕过、大小写绕过、注释符拆分,攻击者的花样比你想象的多得多。该做的是白名单校验,明确允许的字符集和格式。比如手机号就只认数字和短横线,邮箱就按标准正则来。但有个坑得提醒你:校验必须放在服务端做,前端JS那套只是给普通用户用的,攻击者直接抓包就能绕过去。
第三层是最小权限。很多运维图省事,数据库账号一给就是DBA权限。这等于把保险柜钥匙挂门口。正确的做法是:应用账号只给增删改查的权限,存储过程单独授权,敏感表(比如用户表、支付表)连查询权限都要限制。我见过一个案例,攻击者注入后发现自己只是普通权限用户,连information_schema都读不了,最后只能灰溜溜撤了——这一层防不住攻击,但能把损失降到最低。
还有个容易被忽略的点:报错信息。开发环境里数据库报错直接回显,方便调试,但生产环境必须关掉。攻击者靠报错信息能猜表结构、字段名,甚至直接利用报错函数把数据带出来。别小看这细节,很多注入攻击就是从一条报错信息开始的。把错误日志写到服务端文件里,返回给用户的只有一句“系统繁忙”,这成本几乎为零,效果却立竿见影。
最后说句实在话。修复SQL注入不是搞一次安全整改就完事,得写进开发规范里。新代码必须参数化,旧代码按风险等级逐步替换,上线前用自动化工具扫一遍。别信那些“安全产品一装就万事大吉”的鬼话——WAF能拦常规攻击,但绕过的案例还少吗?真正的安全感,永远来自代码本身。