# [Security] Direct SSRF via uploadImgByHttp Endpoint in jeecgboot_jeecBoot #9555 ## 漏洞概述 在 `jeecgboot_jeecBoot` 的 `/sys/common/uploadImgByHttp` 端点中存在直接服务器端请求伪造(SSRF)漏洞。该漏洞允许攻击者在未经身份验证的情况下,强制服务器向任意外部或内部资源发起 HTTP 请求。由于文件类型过滤(`SvrFileTypeFilter.checkUploadFileType`)在外部资源完全下载后才执行,攻击者可以利用此漏洞进行内网扫描、本地服务枚举或窃取敏感云元数据凭证。 ## 影响范围 * **受影响版本**: uploadImgByHttp(@RequestBody JSONObject jsonObject, HttpServletRequest request){ String fileUrl = oConvertUtils.getString(jsonObject.get("fileUrl")); String filename = oConvertUtils.getString(jsonObject.get("filename")); String bizPath = oConvertUtils.getString(jsonObject.get("bizPath")); // NO URL VALIDATION HERE! MultipartFile file = HttpFileToMultipartFileUtil.httpFileToMultipartFile(fileUrl, filename); // File type validation happens AFTER download - too late! SvrFileTypeFilter.checkUploadFileType(file, bizPath); // Save file to server if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){ savePath = this.uploadLocal(file,bizPath); } return Result.OK(savePath); } ``` **Utility Forwarding - HttpFileToMultipartFileUtil.java:28-31** ```java public static MultipartFile httpFileToMultipartFile(String fileUrl, String filename) throws Exception { byte[] bytes = downloadImageData(fileUrl); // IMMEDIATE SSRF return convertByteToMultipartFile(bytes, filename); } ``` **The Sink - HttpFileToMultipartFileUtil.java:38-66** ```java private static byte[] downloadImageData(String fileUrl) throws IOException { URL url = new URL(fileUrl); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); connection.setReadTimeout(10000); connection.setRequestProperty("User-Agent", "Mozilla/5.0..."); connection.setRequestProperty("Accept", "image/*"); int responseCode = connection.getResponseCode(); try (InputStream inputStream = connection.getInputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } return outputStream.toByteArray(); } } ```