深入学习Java代码审计技巧—详细剖析某erp漏洞
字数 2246 2025-08-10 08:28:52
Java代码审计技巧与ERP系统漏洞深度剖析
1. 审计准备工作
1.1 项目结构分析
src/main/java:存放核心Java代码,包含controller、service、filter、dao等src/main/resources:包含mybatis配置文件、properties等erp_web:存放网站的html、css及js文件docs:数据库文件及文档文件test:项目测试目录pom.xml:项目依赖配置
1.2 环境搭建
- 数据库创建:
mysql -u root -h 127.0.0.1 -p
create database jsh_erp;
use jsh_erp;
source /path/to/jsh_erp.sql
- 项目启动:
- 配置
application.properties中的数据库连接信息 - 启动主类
ErpApplication.java
2. 配置文件审计
2.1 关键配置文件
application.properties:Spring全局配置,包含server IP/port和数据库连接信息pom.xml:组件依赖配置,重点检查已知漏洞组件
2.2 组件漏洞分析
Fastjson反序列化漏洞
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.55</version>
</dependency>
- 1.2.55版本存在反序列化漏洞
- 审计点:全局搜索
parseObject方法
漏洞利用链:
StringUtil.getInfo()调用JSONObject.parseObject()UserComponent.getUserList()调用StringUtil.getInfo()ResourceController.getList()最终调用UserComponent.getUserList()
测试Payload:
{"@type":"java.net.Inet4Address","val":"xxxxxx"}
Log4j漏洞
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.10.0</version>
</dependency>
- 2.10.0版本无相关漏洞
3. Filter分析
3.1 LogCostFilter分析
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 具体过滤逻辑
}
免登录访问条件:
- URL包含
/doc.html、/register.html或/login.html - URL包含
.css、.js、.jpg、.png、.gif、.ico - URL以
/user/login、/user/registerUser、/v2/api-docs开头
4. 路由分析
4.1 特殊路由处理
ResourceController处理包含{apiName}的路径- 通过
CommonQueryManager和Component类进行路由分发
5. SQL注入漏洞
5.1 审计关键点
- 关注
createQuery()、createSQLQuery()、createNativeQuery() - 检查SQL语句是否直接拼接参数
- MyBatis中搜索
${}使用情况 - JPA检查
JpaSort.unsafe()使用
5.2 注入点1:用户查询
漏洞位置:UserMapperEx.xml
<select id="countsByUser" resultType="java.lang.Long">
select count(user.id)
FROM jsh_user user
where 1=1
<if test="userName != null">
and user.username like '%${userName}%'
</if>
<if test="loginName != null">
and user.login_name like '%${loginName}%'
</if>
</select>
利用链:
ResourceController.getList()接收search参数- 传递到
UserComponent.counts() - 最终调用
UserMapperEx.countsByUser()
测试Payload:
%'/**/And/**/SleeP(3)--
5.3 注入点2:消息状态查询
漏洞位置:MsgMapperEx.xml
<select id="getMsgCountByStatus" resultType="java.lang.Long">
SELECT COUNT(id) FROM jsh_msg
WHERE 1=1
<if test="status != null">
and status = '${status}'
</if>
</select>
测试Payload:
1'/**/and/**/1=1--1'/**/and/**/1=2--
6. XSS漏洞
6.1 审计关键点
- 关键字:
<%=、${、<c:out、ModelAndView、request.getParameter - 存储型XSS需寻找数据存储和显示两个点
6.2 漏洞点1:供应商信息更新
存储利用链:
ResourceController.updateResource()接收beanJson- 传递到
SupplierComponent.update() - 最终调用
SupplierMapper.updateByPrimaryKeySelective()
显示利用链:
ResourceController.getList()查询数据- 前端
supplier.js通过AJAX获取并显示数据
测试Payload:
{
"supplier": "客户1",
"description": "<script>alert('desc')</script>",
"address": "<script>alert('address')</script>"
}
7. 信息泄露漏洞
7.1 Swagger API文档泄露
漏洞配置类:Swagger2Config.java
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
修复建议:
- 限制请求处理程序和路径
- 添加访问控制和身份验证
7.2 账号密码泄露
利用Filter的免登录条件直接访问敏感接口
8. 越权漏洞
8.1 密码重置越权
漏洞位置:UserController.resetPwd()
@PostMapping(value = "/resetPwd")
public String resetPwd(@RequestParam("id") Long id, HttpServletRequest request) {
// 无权限校验直接重置
int update = userService.resetPwd(md5Pwd, id);
}
测试方法:
- 修改请求中的
id参数为其他用户ID
8.2 用户删除越权
漏洞位置:UserController.deleteUser()
@PostMapping("/deleteUser")
public Object deleteUser(@RequestParam("ids") String ids) {
// 无权限校验直接删除
userService.batDeleteUser(ids);
}
9. 总结与建议
9.1 审计经验总结
- 组件分析优先:从
pom.xml入手,检查已知漏洞组件 - SQL注入重点检查:
- MyBatis中的
${}使用 - 模糊查询、排序、IN条件等场景
- MyBatis中的
- XSS漏洞需同时分析存储和显示逻辑
- 越权漏洞需检查每个接口的权限控制
9.2 修复建议
- 升级存在漏洞的组件版本
- MyBatis中使用
#{}替代${} - 添加全局XSS过滤器
- 实现完善的权限控制机制
- 限制Swagger等开发工具的访问
9.3 进阶审计工具
- 静态分析工具:CodeQL、Fortify
- 动态测试工具:Yakit、Burp Suite
- 代码搜索技巧:关键API和特征关键字搜索