记一次java项目的代码审计
字数 1356 2025-12-16 12:13:19
Java项目代码审计实战教学
项目概述
项目名称:Roothub物料资产平台
项目地址:https://github.com/RootLinkFE/roothub/tree/backup
项目性质:参考Pandora(umi-ui)改造的物料资产平台
主要功能模块
- 物料市场:集成ant-design物料、自定义私有物料、物料一键下载
- 物料开发和私有物料集成
- 项目管理
- npm script脚本运行
- 依赖管理
- 日志输出
- 框架无关设计
技术栈
- Java项目
- 使用MyBatis作为持久层框架
代码审计发现的安全漏洞
1. 任意文件上传漏洞
漏洞位置
文件上传功能点,涉及参数:file和customPath
漏洞分析
代码流程:
// 上传接口接收两个参数
storageService.store(file, customPath);
存储方法实现分析:
- 对
file参数进行了过滤,防止目录遍历(禁止../出现) - 但未对文件后缀名进行有效验证
- 关键问题:未对
customPath参数进行安全检测,直接使用传入值作为存储路径
漏洞利用方式
攻击者可以通过构造特殊的customPath参数实现任意文件上传:
POST /upload HTTP/1.1
file=malicious.jsp&customPath=../../webapps/ROOT/
修复建议
- 对
customPath参数进行路径规范化检查 - 限制文件上传目录为指定安全路径
- 增加文件类型白名单验证
- 对上传文件名进行重命名处理
2. SQL注入漏洞(漏洞1)
漏洞位置
MyBatis映射文件中使用${}进行参数拼接
漏洞代码示例
<!-- MyBatis映射文件 -->
<select id="pageLike" parameterType="string" resultType="map">
SELECT * FROM table WHERE column LIKE '%${s}%'
</select>
调用链分析
- Controller层调用
pageLike()方法 - Service层执行SQL查询
- 参数
s直接拼接到SQL语句中,未经过预编译处理
漏洞利用
攻击者可构造恶意输入实现SQL注入:
' OR 1=1 --
修复方案
将${s}改为#{s}使用参数化查询:
<select id="pageLike" parameterType="string" resultType="map">
SELECT * FROM table WHERE column LIKE CONCAT('%', #{s}, '%')
</select>
3. SQL注入漏洞(漏洞2)
漏洞位置
另一个MyBatis查询语句中的%${nodeTitle}%拼接
漏洞代码
<select id="pageForAdmin" parameterType="string" resultType="map">
SELECT * FROM table WHERE title LIKE '%${nodeTitle}%'
</select>
调用流程
- Controller层调用
pageForAdmin()方法 - 参数
nodeTitle直接拼接到SQL语句 - 存在SQL注入风险
修复方案
同上,使用参数化查询替代字符串拼接。
代码审计方法论总结
1. 敏感功能点审计策略
- 文件上传功能:全局搜索
upload关键字 - SQL注入:全局搜索
${模式(MyBatis危险用法)
2. 参数传递链跟踪
- 从Controller层→Service层→DAO层完整跟踪参数传递
- 重点关注参数是否经过安全处理
3. 安全防御 bypass 技巧
- 注意多参数组合漏洞(如文件上传中的file和customPath参数)
- 验证逻辑是否覆盖所有输入向量
4. MyBatis安全使用规范
- 禁止使用
${}进行SQL参数拼接 - 统一使用
#{}参数化查询 - 必要时使用MyBatis的
<if>标签进行动态SQL构造
预防措施建议
开发阶段
- 建立安全编码规范
- 使用静态代码分析工具
- 进行定期的代码审查
框架层面
- 统一参数验证机制
- 文件上传安全组件封装
- SQL执行监控和拦截
测试阶段
- 渗透测试覆盖所有输入点
- 自动化安全测试集成到CI/CD
通过本次审计案例可以看出,即使是基础的安全问题(如SQL注入、文件上传漏洞)在实际项目中仍然普遍存在,需要开发团队保持高度的安全意识和完善的安全开发流程。