Path Traversal Vulnerability /sys/comment/addFile /sys/upload/uploadMinio endpoint (notice the uploadlocal function is different from the /sys/common/upload ) #8827

This commit is contained in:
JEECG
2025-09-29 18:24:33 +08:00
parent c3822ab702
commit 35aba0784d
7 changed files with 91 additions and 91 deletions

View File

@ -1,16 +1,15 @@
package org.jeecg.modules.system.controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.constant.enums.FileTypeEnum;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
@ -22,8 +21,6 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.*;
/**
@ -68,50 +65,19 @@ public class CommonController {
Result<?> result = new Result<>();
String savePath = "";
String bizPath = request.getParameter("biz");
//LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
if (oConvertUtils.isNotEmpty(bizPath)) {
if(bizPath.contains(SymbolConstant.SPOT_SINGLE_SLASH) || bizPath.contains(SymbolConstant.SPOT_DOUBLE_BACKSLASH)){
throw new JeecgBootException("上传目录bizPath格式非法");
}
}
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
// 获取上传文件对象
MultipartFile file = multipartRequest.getFile("file");
if(oConvertUtils.isEmpty(bizPath)){
if(CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)){
//未指定目录,则用阿里云默认目录 upload
bizPath = "upload";
//result.setMessage("使用阿里云文件上传时,必须添加目录!");
//result.setSuccess(false);
//return result;
}else{
bizPath = "";
}
// 文件安全校验,防止上传漏洞文件
SsrfFileTypeFilter.checkUploadFileType(file, bizPath);
if (oConvertUtils.isEmpty(bizPath)) {
bizPath = CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType) ? "upload" : "";
}
if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){
//update-begin-author:liusq date:20221102 for: 过滤上传文件类型
SsrfFileTypeFilter.checkUploadFileType(file);
//update-end-author:liusq date:20221102 for: 过滤上传文件类型
//update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
savePath = this.uploadLocal(file,bizPath);
//update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
/** 富文本编辑器及markdown本地上传时采用返回链接方式
//针对jeditor编辑器如何使 lcaol模式采用 base64格式存储
String jeditor = request.getParameter("jeditor");
if(oConvertUtils.isNotEmpty(jeditor)){
result.setMessage(CommonConstant.UPLOAD_TYPE_LOCAL);
result.setSuccess(true);
return result;
}else{
savePath = this.uploadLocal(file,bizPath);
}
*/
}else{
//update-begin-author:taoyan date:20200814 for:文件上传改造
savePath = CommonUtils.upload(file, bizPath, uploadType);
//update-end-author:taoyan date:20200814 for:文件上传改造
}
if(oConvertUtils.isNotEmpty(savePath)){
result.setMessage(savePath);

View File

@ -2,9 +2,9 @@ package org.jeecg.modules.system.controller;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.MinioUtil;
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.oss.entity.OssFile;
import org.jeecg.modules.oss.service.IOssFileService;
@ -35,20 +35,18 @@ public class SysUploadController {
@PostMapping(value = "/uploadMinio")
public Result<?> uploadMinio(HttpServletRequest request) throws Exception {
Result<?> result = new Result<>();
// 获取业务路径
String bizPath = request.getParameter("biz");
//LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
boolean flag = oConvertUtils.isNotEmpty(bizPath) && (bizPath.contains("../") || bizPath.contains("..\\"));
if (flag) {
throw new JeecgBootException("上传目录bizPath格式非法");
}
// 获取上传文件对象
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("file");
// 文件安全校验,防止上传漏洞文件
SsrfFileTypeFilter.checkUploadFileType(file, bizPath);
if(oConvertUtils.isEmpty(bizPath)){
bizPath = "";
}
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
// 获取上传文件对象
MultipartFile file = multipartRequest.getFile("file");
// 获取文件名
String orgName = file.getOriginalFilename();
orgName = CommonUtils.getFileName(orgName);

View File

@ -15,6 +15,7 @@ import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.SysFilesModel;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.system.entity.SysComment;
import org.jeecg.modules.system.entity.SysFormFile;
@ -119,28 +120,24 @@ public class SysCommentServiceImpl extends ServiceImpl<SysCommentMapper, SysComm
@Transactional(rollbackFor = Exception.class)
@Override
public void saveOneFileComment(HttpServletRequest request) {
//update-begin-author:taoyan date:2023-6-12 for: QQYUN-4310【文件】从文件库选择文件功能未做
String existFileId = request.getParameter("fileId");
if(oConvertUtils.isEmpty(existFileId)){
String savePath = "";
// 获取业务路径
String bizPath = request.getParameter("biz");
//LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
if (oConvertUtils.isNotEmpty(bizPath)) {
if (bizPath.contains(SymbolConstant.SPOT_SINGLE_SLASH) || bizPath.contains(SymbolConstant.SPOT_DOUBLE_BACKSLASH)) {
throw new JeecgBootException("上传目录bizPath格式非法");
}
}
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
// 获取上传文件对象
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("file");
// 文件安全校验,防止上传漏洞文件
try {
SsrfFileTypeFilter.checkUploadFileType(file, bizPath);
} catch (Exception e) {
throw new JeecgBootException(e);
}
if (oConvertUtils.isEmpty(bizPath)) {
if (CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)) {
//未指定目录,则用阿里云默认目录 upload
bizPath = "upload";
} else {
bizPath = "";
}
bizPath = CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType) ? "upload" : "";
}
if (CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)) {
savePath = this.uploadLocal(file, bizPath);
@ -348,10 +345,13 @@ public class SysCommentServiceImpl extends ServiceImpl<SysCommentMapper, SysComm
* @return
*/
private String uploadLocal(MultipartFile mf, String bizPath) {
//LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
if (oConvertUtils.isNotEmpty(bizPath) && (bizPath.contains("../") || bizPath.contains("..\\"))) {
throw new JeecgBootException("上传目录bizPath格式非法");
try {
// 文件安全校验,防止上传漏洞文件
SsrfFileTypeFilter.checkUploadFileType(mf, bizPath);
} catch (Exception e) {
throw new JeecgBootException(e);
}
try {
String ctxPath = uploadpath;
String fileName = null;