JAVA代码审计——Echo4.2
JAVA代码审计——Echo4.2
项目介绍
🦄 开源社区系统:基于 SpringBoot + MyBatis + MySQL + Redis + Kafka + Elasticsearch + Spring Security + ... 并提供详细的开发文档和配套教程。包含帖子、评论、私信、系统通知、点赞、关注、搜索、用户设置、数据统计等模块。3000+Star的项目还是比较不错的
环境搭建
项目地址:https://gitee.com/veal98/Echo
环境准备
JDK 1.8.0_65
Maven 3.9.9
redis 3.0.504
zookeeper 3.6.4
kafka 2.12-3.5.1配置文件:
src/main/resources/application-develop.properties
创建对应数据库,并且修改数据库配置文件,以及文件存放路径

我这里创建数据库采用utf8 utf8_bin
创建后导入所有数据库文件


先启动zookeeper
zkServer再启动 kafka
.\bin\windows\kafka-server-start.bat .\config\server.properties然后启动springboot
访问自己设置的对应端口

代码审计
鉴权绕过
在看过用户登入凭证生成后发现无法伪造,转思路查看用户权限校验
权限校验对应.class文件
src/main/java/com/greate/community/controller/interceptor/LoginTicketInterceptor.java

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从 cookie 中获取凭证
String ticket = CookieUtil.getValue(request, "ticket");
if (ticket != null) {
// 查询凭证
LoginTicket loginTicket = userService.findLoginTicket(ticket);
// 检查凭证状态(是否有效)以及是否过期
if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) {
// 根据凭证查询用户
User user = userService.findUserById(loginTicket.getUserId());
// 在本次请求中持有用户信息
hostHolder.setUser(user);
// 构建用户认证的结果,并存入 SecurityContext, 以便于 Spring Security 进行授权
Authentication authentication = new UsernamePasswordAuthenticationToken(
user, user.getPassword(), userService.getAuthorities(user.getId())
);
SecurityContextHolder.setContext(new SecurityContextImpl(authentication));
}
}
return true;
}这里只判断ticket不会null值的身份校验,ticket的值为null时会直接放行,没有考虑到tucket为null的情况
未授权用户信息遍历
通过路由传入的userID进行数据库查询,这里会验证ticket的身份和查询的userID是否相同主要是根据ticket查询,根据前面的鉴权绕过就可以实现未授权用户信息遍历
漏洞触发数据包
GET /user/profile/102 HTTP/1.1
Host: 192.168.242.1:8081
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.242.1:8081/index
Accept-Language: zh-CN,zh;q=0.9
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
Accept-Encoding: gzip, deflate
Upgrade-Insecure-Requests: 1可通过控制id未授权遍历用户信息

未授权任意文件上传
全局搜索upload关键词

查看代码
@PostMapping("/uploadMdPic")
@ResponseBody
public String uploadMdPic(@RequestParam(value = "editormd-image-file", required = false) MultipartFile file) {
String url = null; // 图片访问地址
try {
// 获取上传文件的名称
String trueFileName = file.getOriginalFilename();
String suffix = trueFileName.substring(trueFileName.lastIndexOf("."));
String fileName = CommunityUtil.generateUUID() + suffix;
// 图片存储路径
File dest = new File(editormdUploadPath + "/" + fileName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
// 保存图片到存储路径
file.transferTo(dest);
// 图片访问地址
url = domain + contextPath + "/editor-md-upload/" + fileName;
} catch (Exception e) {
e.printStackTrace();
return CommunityUtil.getEditorMdJSONString(0, "上传失败", url);
}
return CommunityUtil.getEditorMdJSONString(1, "上传成功", url);
}这里获取我们上传的文件,然后通过lastIndexOf 方法获取文件后缀,然后,通过CommunityUtil.generateUUID()生成一个文件名,并将获取到的后缀和文件名进行拼接。
最后,文件是通过 file.transferTo 方法进行保存的。在此过程中,没有检测文件后缀,那么这里存在任意文件上传,加上前面的鉴权绕过就是未授权任意文件上传,但是很可惜springboot没有jsp解析环境,这里还限制了目录
通过代码使用ai构造上传文件的html文件


测试上传抓包

访问文件


师傅你好,kafka里面不是已经内置zookeeper了吗,那应该不需要再另准备zookeeper了吧