mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-01-28 17:58:12 +00:00
文件目录扫描漏洞
This commit is contained in:
parent
1936f503df
commit
360f5d779a
@ -286,5 +286,38 @@ public class SsrfFileTypeFilter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验文件路径安全性,防止路径遍历攻击
|
||||
* @param filePath 文件路径
|
||||
*/
|
||||
public static void checkPathTraversal(String filePath) {
|
||||
if (StringUtils.isBlank(filePath)) {
|
||||
return;
|
||||
}
|
||||
// 1. 防止路径遍历:不允许 ..
|
||||
if (filePath.contains("..")) {
|
||||
throw new JeecgBootException("文件路径包含非法字符");
|
||||
}
|
||||
// 2. 防止URL编码绕过:%2e = .
|
||||
String fileLower = filePath.toLowerCase();
|
||||
if (fileLower.contains("%2e")) {
|
||||
throw new JeecgBootException("文件路径包含非法字符");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量校验文件路径安全性(逗号分隔的多个文件路径)
|
||||
* @param files 逗号分隔的文件路径
|
||||
*/
|
||||
public static void checkPathTraversalBatch(String files) {
|
||||
if (StringUtils.isBlank(files)) {
|
||||
return;
|
||||
}
|
||||
for (String file : files.split(",")) {
|
||||
if (StringUtils.isNotBlank(file)) {
|
||||
checkPathTraversal(file.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.ai.handler.LLMHandler;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.util.AssertUtils;
|
||||
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.airag.common.consts.AiragConsts;
|
||||
import org.jeecg.modules.airag.common.handler.AIChatParams;
|
||||
@ -401,6 +402,7 @@ public class AIChatHandler implements IAIChatHandler {
|
||||
String filePath = uploadpath + File.separator + imageUrl;
|
||||
// 读取文件并转换为 base64 编码字符串
|
||||
try {
|
||||
SsrfFileTypeFilter.checkPathTraversal(filePath);
|
||||
Path path = Paths.get(filePath);
|
||||
byte[] fileContent = Files.readAllBytes(path);
|
||||
String base64Data = Base64.getEncoder().encodeToString(fileContent);
|
||||
@ -409,7 +411,7 @@ public class AIChatHandler implements IAIChatHandler {
|
||||
// 构建 ImageContent 对象
|
||||
imageContents.add(ImageContent.from(base64Data, mimeType));
|
||||
} catch (IOException e) {
|
||||
log.error("读取文件失败: " + filePath, e);
|
||||
log.error("读取文件失败: {}", imageUrl, e);
|
||||
throw new RuntimeException("发送消息失败,读取文件异常:" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
@ -529,12 +531,13 @@ public class AIChatHandler implements IAIChatHandler {
|
||||
} else {
|
||||
// 本地文件
|
||||
String filePath = uploadpath + File.separator + imageUrl;
|
||||
SsrfFileTypeFilter.checkPathTraversal(filePath);
|
||||
Path path = Paths.get(filePath);
|
||||
fileContent = Files.readAllBytes(path);
|
||||
}
|
||||
originalImageBase64List.add(Base64.getEncoder().encodeToString(fileContent));
|
||||
} catch (Exception e) {
|
||||
log.error("图片读取失败: " + imageUrl, e);
|
||||
log.error("图片读取失败: {}", imageUrl, e);
|
||||
throw new JeecgBootException("图片读取失败: " + imageUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.*;
|
||||
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.message.enums.RangeDateEnum;
|
||||
import org.jeecg.modules.message.websocket.WebSocket;
|
||||
@ -142,6 +143,8 @@ public class SysAnnouncementController {
|
||||
// 代码逻辑说明: 标题处理xss攻击的问题
|
||||
String title = XssUtils.scriptXss(sysAnnouncement.getTitile());
|
||||
sysAnnouncement.setTitile(title);
|
||||
// 【安全校验】校验附件文件名,防止路径遍历攻击
|
||||
SsrfFileTypeFilter.checkPathTraversalBatch(sysAnnouncement.getFiles());
|
||||
sysAnnouncement.setDelFlag(CommonConstant.DEL_FLAG_0.toString());
|
||||
//未发布
|
||||
sysAnnouncement.setSendStatus(CommonSendStatus.UNPUBLISHED_STATUS_0);
|
||||
@ -173,6 +176,8 @@ public class SysAnnouncementController {
|
||||
// 代码逻辑说明: 标题处理xss攻击的问题
|
||||
String title = XssUtils.scriptXss(sysAnnouncement.getTitile());
|
||||
sysAnnouncement.setTitile(title);
|
||||
// 【安全校验】校验附件文件名,防止路径遍历攻击
|
||||
SsrfFileTypeFilter.checkPathTraversalBatch(sysAnnouncement.getFiles());
|
||||
sysAnnouncement.setNoticeType(NoticeTypeEnum.NOTICE_TYPE_SYSTEM.getValue());
|
||||
boolean ok = sysAnnouncementService.upDateAnnouncement(sysAnnouncement);
|
||||
//TODO 返回false说明什么?
|
||||
|
||||
@ -12,6 +12,7 @@ import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.FileDownloadUtils;
|
||||
import org.jeecg.common.util.filter.SsrfFileTypeFilter;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.JeecgBaseConfig;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
@ -303,6 +304,8 @@ public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMappe
|
||||
if (oConvertUtils.isEmpty(fileUrl)) {
|
||||
continue;
|
||||
}
|
||||
// 【安全校验】防止路径遍历攻击
|
||||
SsrfFileTypeFilter.checkPathTraversal(fileUrl);
|
||||
// 生成ZIP内文件名:避免重名,添加序号
|
||||
String fileName = FileDownloadUtils.generateFileName(fileUrl, i, fileUrls.length);
|
||||
String uploadUrl = jeecgBaseConfig.getPath().getUpload();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user