| 字段 | 内容 |
/admin/auser/getAdminskeyword、/home/getLikeMovieList、cat | |
一个看起来只是后台搜索词的 keyword,和一个看起来只是前台分类值的 cat,为什么最后都能变成 SQL 注入入口?
`weimai-wetapp` 这个 case 值得看的地方,不只是“同一个项目里有两条 SQL 注入”,而是这两条路径一条落在后台管理员列表接口里,另一条落在前台电影推荐接口里,业务位置完全不同,暴露出来的却是同一种查询信任边界问题。
ZAST.AI 这次确认并验证下来的,也不是同一路径上的重复报错,而是两条分布在不同业务位置、但都已经被打实的 SQL 注入。这意味着问题不只是某个查询写坏了,而是请求参数进入数据库查询这件事,本身就缺少足够的约束。

一、第一条注入在后台管理员列表接口里
CVE-2026-3956 对应的路径是 /admin/auser/getAdmins。
在 ZAST.AI 提交的披露记录里,这条链路写得很直接:keyword 参数沿着 controller → service → MyBatis mapper 这条路径进入查询,过程中没有被妥善约束,最后形成 SQL 注入。
披露记录里给出的原始请求形态是:
/admin/auser/getAdmins?pageNum=1&limit=10&keyword=a*随后 SQLMap 成功确认了这条路径可利用,披露记录里列出了布尔盲注和报错注入的结果,其中一条 payload 形态如下:
.../admin/auser/getAdmins?pageNum=1&limit=10&keyword=a%' AND 5227=5227 AND 'bfKA%'='bfKA更关键的是,披露记录里还给出了最短的代码证据,能直接看到 keyword 是怎么被带进查询链路里的:
@GetMapping({"/getAdmins"})public Result getAdmins(..., @RequestParam(value = "keyword", required = false) String keyword) { PageBean<AdminUser> page = this.adminUserService.getAdmins(pageNum, limit, keyword); return new Result(page);}public PageBean getAdmins(Integer pageNum, Integer limit, String keyword) { PageHelper.startPage(pageNum, limit); List<AdminUser> adminUsers = this.adminUserMapper.getAdminsByKeword(keyword); ...}后续通过构造payload拿到了当前数据库用户信息:
current user: 'root@%'到了这一步,结论其实已经足够明确:这不是一个可疑参数,而是一条被验证成功的 SQL 注入路径。
二、第二条注入在前台电影推荐接口里
CVE-2026-3957 对应的是 /home/getLikeMovieList。
这条路径更值得警惕,因为它不像后台管理接口那样天然带着“高风险”标签。表面上看,它只是一个和电影推荐、分类筛选有关的接口,参数名 cat 也很像普通业务字段。
披露记录里的请求形态是:
/home/getLikeMovieList?movieId=1&cat=Action*但这条路径同样被 ZAST.AI 用 SQLMap 打实,其中一条 payload 如下:
.../home/getLikeMovieList?movieId=1&cat=-1900' OR 3543=3543 OR 'MjOe'='rmnM这条披露记录里也给出了对应的最短代码链路。能看到 cat 先从 controller 进入推荐逻辑,最后又回到 mapper 查询方法里:
@GetMapping({"/getLikeMovieList"})public Result getLikeMovieList(@RequestParam("movieId") Integer movieId, @RequestParam("cat") String cat) { List<Movie> movies = this.moviceService.getLikeMovieList(movieId, cat, 3); ...}public List getLikeMovieList(Integer movieId, String cat, Integer limit) { return this.movieMapper.getLikeMovieList(movieId, cat, limit);}而且这条路径最终也拿到了同样的数据库用户信息:
current user: 'root@%'这就说明,问题并不局限在后台管理员查询。连这种前台推荐逻辑里的分类参数,也能一路进入数据库执行语境。看起来越“像普通业务字段”的输入,越容易在 review 里被低估。
三、为什么这两个问题要放在一起看
如果分别看,这当然是两条 SQL 注入。
但放在一起看,信息量会更大:同一个项目里,后台列表查询和前台推荐查询都出现了同类问题,说明这里更像是查询构造方式本身出了系统性问题,而不是某一处偶然漏掉了校验。
这也是为什么这种案例比单点漏洞更值得重视。keyword 看起来像搜索词,cat 看起来像分类值,这类参数在很多系统里都容易被开发者当成“普通文本输入”。可一旦它们没有在进入 MyBatis 查询之前被正确约束,参数名再无害,也照样可能变成 SQL 注入入口。
四、这类问题不该只被理解成“某个接口写错了”
这两个 CVE 最值得看的地方,不只是它们都能注入,而是它们分别落在两个不同的业务面上:
后台管理员列表
前台电影推荐接口
一个偏管理端,一个偏公开业务端。两条路径都被验证成功,说明问题不是孤立的“某个 mapper 手滑”,而是项目对请求参数进入查询的整体防线不够可靠。
这也是为什么这类结果比单纯的静态告警更有价值。真正决定优先级的,不只是“输入有没有流到查询”,而是这条路径到底能不能被打实。ZAST.AI 在这里做的,就是把这件事验证下来。
六、结语
CVE-2026-3956 和 CVE-2026-3957 值得一起看,不是因为“同一项目中存在两个sql注入漏洞”这么简单,而是因为它们分别落在后台和前台两个完全不同的业务位置上,却暴露出同一种数据库信任边界问题。
这也是为什么验证比猜测更重要。ZAST.AI 这次并非停留在 “识别参数存在潜在风险” 的层面,而是完整打通利用链路,直接验证漏洞可成功利用,无需额外人工分析与手动验证。
详细报告可见:
https://blog.zast.ai/vulnerability%20research/application%20security/weimai-wetapp-multiple-sql-injections/
披露记录:
https://github.com/xierongwkhd/weimai-wetapp/issues/48
https://github.com/xierongwkhd/weimai-wetapp/issues/49
夜雨聆风