您现在的位置是:知识 >>正文

sql注入修复

知识6人已围观

简介凌晨两点,某电商平台的订单库突然暴增了几万条“test”记录。DBA打开慢查询日志,发现一条诡异的SQL:SELECT * FROM users WHERE id = 1 OR 1=1。这不是黑客炫技 ...

凌晨两点,入修某电商平台的入修订单库突然暴增了几万条“test”记录。DBA打开慢查询日志,入修发现一条诡异的入修SQL:SELECT * FROM users WHERE id = 1 OR 1=1。这不是入修黑客炫技,是入修实习生把用户输入直接拼进了SQL语句——典型的注入漏洞,一夜之间让数据库裸奔了八小时。入修

修复注入,入修核心就一句话:永远不要相信用户输入。入修但这句话说起来轻巧,入修做起来全是入修坑。我见过不少团队,入修把输入框里的入修单引号过滤掉就以为安全了,结果黑客用%27编码绕过,入修照样把表给拖了。入修真正的修复不是给数据“洗澡”,而是从根上切断拼接路径。

第一层:参数化查询,这是底线

拿Java的PreparedStatement举例,把SQL骨架和参数分开传:

String sql = "SELECT * FROM products WHERE id = ?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, productId); // 参数自动转义,永远不参与SQL编译 ResultSet rs = ps.executeQuery();

这段代码的奥妙在于,即使用户传入1; DROP TABLE products,数据库也只会把它当成一个字符串字面量,而不是可执行的SQL片段。Python的cursor.execute(sql, params)、PHP的PDO预处理、Node.js的mysql.escape(),原理都一样。你用的ORM框架(比如MyBatis、Hibernate)底层已经帮你做了这层,但如果你手写JDBC或者拼MyBatis的${ },那就等于把门焊开。

第二层:输入校验,别指望正则

很多开发者喜欢用黑名单正则,比如过滤union|select|insert。这招对小白黑客有效,但稍微懂点编码的就能绕过——用UNION%0ASELECT、/*!50000UNION*/,甚至十六进制编码。我见过一个案例,攻击者把SELECT写成SeLeCt,大小写混合就绕过了过滤。

靠谱的做法是白名单校验:明确这个字段该是什么类型。ID必须是数字,用is_numeric()或正则^\d+$;邮箱必须匹配标准格式;日期必须符合YYYY-MM-DD。校验不过,直接拒绝请求,别想着“清洗”后放行——清洗规则永远比攻击手法慢半拍。

第三层:最小权限原则,这条命是数据库给的

就算前面两层都崩了,你还能靠数据库权限兜底。很多生产库的Web连接账号居然有DROP权限,这等于把保险箱钥匙挂在门口。修复方案很直接:

-- 只给应用账号SELECT/INSERT/UPDATE/DELETE GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'webuser'@'localhost'; REVOKE DROP, ALTER, CREATE ON mydb.* FROM 'webuser'@'localhost';

如果业务需要存储过程,那就封装好,只授予EXECUTE权限。我见过最狠的案例,某支付系统把数据库账号权限砍到只剩四个操作,就算注入成功,黑客也只能查数据,删不了表——这为应急响应争取了宝贵时间。

第四层:异常处理,别把错误信息当礼物送人

注入攻击经常依赖报错信息来探测数据库结构。比如输入1',如果页面回显SQL语法错误: You have an error in your SQL syntax near ''1''' at line 1,黑客就知道后面该补什么。修复时要把数据库错误统一转为通用提示:

try {  // 执行查询 } catch (SQLException e) {  log.error("DB error", e); // 详细日志存服务端,只给用户看友好提示 return "系统繁忙,请稍后重试"; }

另外,应用层要设置数据库连接超时和最大查询返回行数,防止黑客用SELECT * FROM information_schema.tables一次性拖走元数据。

别忽略的角落:存储过程和动态SQL

不少老系统喜欢把业务逻辑写进存储过程,然后在过程里用EXECUTE IMMEDIATE拼接参数。这等于把参数化查询的成果全毁了。修复时要把存储过程里的动态SQL改成绑定变量:

-- 错误示范 SET @sql = CONCAT('SELECT * FROM orders WHERE id = ', id); PREPARE stmt FROM @sql; EXECUTE stmt; -- 正确做法 SET @sql = 'SELECT * FROM orders WHERE id = ?'; PREPARE stmt FROM @sql; EXECUTE stmt USING @id;

最后说个扎心的事实:很多注入漏洞不是技术问题,是流程问题。开发图省事直接拼SQL,测试没做安全用例,上线前扫描工具没跑。修复注入,技术方案只占一半,另一半靠代码审查和自动化检测——比如在CI流水线里挂上SQLMap或Semgrep规则,每次提交代码自动扫一遍。

SQL注入这玩意儿,跟老鼠一样,你堵住一个洞,它换个角落又钻进来。但只要做到参数化、白名单、最小权限、错误隔离这四板斧,至少能让老鼠绕着你家走。别问我怎么知道——当年那个实习生现在还在工位上,只是他写的SQL已经没人敢直接review了。

Tags:

相关文章

  • 乡镇开展排查巴哈伊教等其他宗教渗透

    知识

    昨天下午,镇里综治办的老周把各村网格员拉进一个临时群,消息只有一条:“下午三点,排查巴哈伊教,重点看家庭聚会点。”我愣了一下,巴哈伊教?不是那个在城里挺时髦的“大同教”吗?怎么渗透到乡镇了。 三点开会 ...

    【知识】

    阅读更多
  • docker漏洞

    知识

    2018年,一个叫Felix Wilhelm的安全研究员在Docker的`docker cp`命令里挖出了一个漏洞。利用它,攻击者可以从容器内部把文件写到宿主机上任意路径——包括`/etc/cron. ...

    【知识】

    阅读更多
  • app诈骗能抓到人吗

    知识

    去年夏天,我一位在派出所干了八年的朋友老周,凌晨两点给我发了条语音:“抓到了,在福建龙岩一个出租屋里,三个人对着二十几部手机。”他说的是一起刷单诈骗案,受害人被骗了六万七,从报案到跨省抓捕,用了十九天 ...

    【知识】

    阅读更多


友情链接