关闭工作流 SpEL 命令执行与社团活动 SQL 注入,补齐越权、调试接口、登录喷洒和异常回显等问题;学生密码改为随机临时密码,Web/移动端支持复制。 Constraint: 流程发起/办理接口保持仅登录校验,避免影响请假审批 Rejected: 开启验证码 | Web/移动端登录页均未实现,开启会导致无法登录 Confidence: high Scope-risk: broad Not-tested: 生产环境与社团社长/指导老师视角 Co-authored-by: Cursor <cursoragent@cursor.com>
5.2 KiB
5.2 KiB
2026-10-26 安全扫描整改说明
背景:杭州市网安对生产环境进行安全扫描。本次对严重、高危、中危问题做代码级整改;Snail-Job 生产已下线,不在本次范围。 后端
mvn -o compile全量通过;前端改动文件无新增类型错误。
一、上线前必须执行
| 项 | 说明 |
|---|---|
| SQL | backend/script/sql/update/update_20261026_workflow_permission.sql:新增工作流管理按钮权限(workflow:definition:list/edit、workflow:instance:manage、workflow:task:manage),并自动授给已拥有「流程定义 / 流程实例 / 待办任务」父菜单的角色。执行后相关用户需重新登录。 |
| 配置 | application.yml 新增 security.cors-allowed-origins(默认放行 *.hzdyjsxy.cn 与 localhost),若有其它域名访问后端须补充;user.password.ipMaxRetryCount: 30;sa-token.jwt-secret-key 已换成随机值。 |
| nginx | 必须向后端传递真实客户端 IP(X-Forwarded-For / X-Real-IP),否则按 IP 的登录失败锁定失效。 |
二、整改清单
严重
| 问题 | 整改 |
|---|---|
工作流 SpEL 表达式注入可执行系统命令(T(java.lang.Runtime)) |
新增 SafeSpelHelper / SafeExpressionStrategies,启动时替换 warm-flow 内置 SpEL 策略:禁止类型引用 T()、new、反射与 getClass/forName/exec/getBean 等方法,仅允许对值类型与 org.dromara 业务 Bean 调用 |
| 工作流管理接口无权限控制 | 流程定义全部接口、实例运行/已完成/删除/激活/挂起/变量/作废、全部待办/已办/修改办理人加权限码;/warm-flow/** 设计器接口按读写加权限;删除实例、撤销流程要求必须是发起人或具备管理权限 |
社团活动列表 SQL 注入 ${params.dataScope} |
Mapper 改为 #{} + foreach 的类型化参数;Service 先清除请求中 ds*/dataScope 参数再写入 |
高危
| 问题 | 整改 |
|---|---|
| 文件 ossId 越权访问 | 学生账号只能访问本人或教职工上传的文件;预签名链接最长 1 小时;异常不回显 |
| 登录喷洒 / 账号枚举 | 账号不存在与密码错误提示一致;同一公网 IP 失败 30 次锁定(内网 IP 不计数) |
| 调试接口暴露 | 删除 testCoefficient、testVicePresidentData、两个 debug/permission、test/scholarshipTypesStructure、debug/sqlLogs、test-location、勤工助学 debug/{id} |
| 新生录取名册导出无权限 | 加 zsjy:enrollment:process:export 或 query |
| 学生考核申请越权、篡改分数 | 学生只能增删改查本人申请;审核字段(教师评分、总分、审核人等)服务端清空;只允许状态 1/2/3 时修改 |
| 应聘越权 | /apply、/my 强制使用当前登录人;/submit 强制状态为 pending |
| 按学号重置学生密码 | 改为随机临时密码并踢下线;学院账号只能操作本学院学生;操作日志不记录响应 |
| 异常信息回显 SQL/堆栈 | GlobalExceptionHandler.safeMessage 过滤含 SQL、类名等技术信息的消息;64 处 R.fail(e.getMessage()) 统一过滤 |
| 出国附件任意类型上传 | 扩展名白名单;Content-Type 按扩展名决定(系统 OSS 上传同步改造),不信任客户端 |
中危
| 问题 | 整改 |
|---|---|
| SSE 任意用户群发 | 删除 /resource/sse/send、/sendAll(前端未使用,服务端推送不受影响) |
| CORS 回显任意 Origin 且允许携带凭证 | 仅放行配置的本校域名 |
| 心理咨询预约/爽约限制越权 | 无管理权限时 studentId 强制为本人 |
| 社团报名/签到越权查询 | 无管理权限时 userId/学号强制为本人 |
奖学金 /my 越权 |
无列表权限时 applicantId 强制为本人 |
| 参数配置读取初始密码 | configKey 仅公开白名单键;sys.user.initPassword 需用户新增/重置密码权限 |
| 学生信息完善批量赋值 | 状态、来源、创建人始终由服务端设置 |
| 前端存储型 XSS | 新增 web/src/utils/htmlSafe.ts;招聘岗位富文本清洗、简历 PDF 字段转义、报修图片预览去掉 innerHTML |
| 开放重定向 | 社交登录回调只允许跳转本校域名;报修附件下载仅重定向 http(s) 地址并安全编码文件名 |
| 日志泄露 | 生产关闭 MyBatis StdOut SQL 日志;登录监听不再打印 token;微信下载不再打印带 access_token 的 URL |
| JWT 默认密钥 | 更换为随机值 |
三、遗留与运维事项
- 默认密码
Hzdyjsxs123456!@#、Hzdyjs123456!@#已出现在攻击日志中,需排查并强制修改仍使用默认密码的账号。 - 轮换 git 历史中出现过的数据库、Redis、监控、CAS 等密钥;确认数据库、Redis、监控端口不对公网开放。
- 实习日志
calendar/monthly-statistics的 studentId 未做归属校验(需权限码,移动端未调用),后续补充。 - 社团成员
approvalFlow/{memberId}、用户导入结果弹窗dangerouslyUseHTMLString(仅管理员)风险较低,后续处理。 - web 端
xljk/consultation/calendar/debug.vue页面与勤工助学debug/statistics调用对应的后端接口已不存在,可删除前端代码。