mybatis查询代码报xss存储型漏洞

探索 2026-10-17 04:17:24 6862

mybatis查询代码报xss存储型漏洞

上周五,查s存储型一个老项目的询代安全扫描报告砸到我头上。里面赫然写着:用户评论查询接口存在XSS存储型漏洞。码报我第一反应是漏洞“不可能”,这接口我半年前刚重构过,查s存储型参数都是询代预编译的#{ },怎么会出问题?码报

打开代码一看,傻眼了。漏洞问题出在MyBatis的查s存储型<script>标签动态SQL上。有个统计报表功能,询代需要根据前端传的码报排序字段动态拼接ORDER BY。图省事,漏洞直接用了${ }字符串替换。查s存储型#{ }是询代预编译占位符,安全;${ }是码报纯字符串拼接,等于把SQL大门敞开。

更坑的是,这个排序字段值被塞进了<script>里的choose分支。攻击者传个1; DROP TABLE users--进去,MyBatis直接把它拼进SQL执行。虽然这例子夸张了点,但真实攻击场景里,${ }配合页面回显,就能注入<script>alert(document.cookie)</script>。用户评论存库,再被其他用户查询时渲染,存储型XSS就成立了。

修复方案不复杂。第一,排序字段这种白名单场景,压根不该用动态SQL。写死几个允许的字段名,用if判断映射到固定字符串。第二,如果非要传参,就用#{ },让MyBatis帮你转义。第三,输出到页面前做HTML实体编码,<变&lt;,>变&gt;,双保险。

我花了一下午把所有Mapper文件翻了个底朝天。统计下来,项目里${ }出现17处,其中11处是排序字段,3处是表名拼接,剩下2处是模糊查询like。模糊查询那个最冤,LIKE '%${ keyword}%'看着没毛病,但keyword里塞个' OR '1'='1照样炸。改成CONCAT('%', #{ keyword}, '%')就好了。

这事的教训是:安全扫描工具不会骗人。你以为重构过的代码没问题,但工具能看见你没注意到的角落。MyBatis的#{ }和${ }区别,入职培训就讲过,但写代码时手一滑,就滑进了坑里。现在我把这个案例贴到团队Wiki上,每次Code Review都有人拿它当反面教材。

老实说,XSS漏洞本质不是MyBatis的错,是开发者对输入数据太信任。数据库里存的评论内容,谁保证都是纯文本?用户提交时过滤一遍,查询出来再过滤一遍,加上参数预编译,三层防护才敢说“基本安全”。别嫌麻烦,安全这玩意,就是拿麻烦换平安。

本文地址:http://www.79wt.cn/news/106f0199892.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

友情链接