输入验证:文件上传 CWE434 如何解决

![1685061419860.png](https://cdn-yg-zzbm.yun.qianxin.com/attack-forum/2023/05/attach-3f5ca3b4b4fac414378b1000d9efe57a82a332c1.png) 做了如下验证 还是不能解决 @PostMapping(value = "/upload") public Result<?\> upload(HttpServletRequest request) throws Exception { Result<?\> result = new Result<>(); //创建一个CommonsMultipartFile对象,获取上传到request中的文件 CommonsMultipartFile file = null; //创建文件解析器(目的是调用该对象的isMultipart方法来检测request请求中是否有上传文件) CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); //判断request中是否有上传文件流 if(multipartResolver.isMultipart(request)){ //将request转为MultipartHttpServletRequest MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request; //从request中获取key名为uploadFile的文件,并保存的CommonsMultipartFile对象中 file = (CommonsMultipartFile) multipartHttpServletRequest.getFile("file"); } // 检查文件是否为空 if (file == null || file.isEmpty() ) { throw new FileUploadException("上传的文件为空"); } String fileType = file.getContentType(); // 自定义文件类型白名单 String\[\] allowedTypes = new String\[\] {"image/jpeg", "image/png", "application/pdf"}; // 文件头检查 try (InputStream inputStream = file.getInputStream()) { FileMagic fileMagic = FileMagic.valueOf(inputStream); if (!Arrays.asList(allowedTypes).contains(fileType) || FileMagic.UNKNOWN.equals(fileMagic)) { return result.error500("文件包含恶意代码"); } } catch (IOException e) { e.printStackTrace(); } String fileName = file.getOriginalFilename(); // 验证文件名是否合法 if (fileName.contains("..") || fileName.endsWith(".exe") || fileName.endsWith(".bat")) { return result.error500("Invalid file name"); } // 验证文件类型是否合法 if (!fileType.equals("image/jpeg") && !fileType.equals("image/png") && !fileType.equals("application/pdf")) { return result.error500("Invalid file type"); } int uploadFileCount = (int) redisUtil.get("uploadFileCount"); if (uploadFileCount >= MAX\_UPLOAD\_FILES) { throw new RuntimeException("上传文件数量超过了限制"); } fileName = fileName.replaceAll("\\0","\_"); String\[\] illegalChars = {"\\\\", "/", ":", "\*", "?", "\\"", "<", ">", "|"}; for (String illegalChar : illegalChars) { if (fileName.contains(illegalChar)) { throw new FileUploadException("文件名包含非法字符"); } } if (!fileName.matches(".\*\\\\.(jpg|jpeg|png|gif)$")) { result.error500("仅支持上传jpg、jpeg、png、gif格式的图片文件"); return result; } String contentType = file.getContentType(); if (!contentType.startsWith("image/")) { result.error500("仅支持上传图片文件"); return result; } // 文件类型判断 if (!isValidFileType(fileName)) { return Result.error("上传的文件类型不允许"); } // 文件大小判断 if (!isValidFileSize(file.getSize())) { return Result.error("上传的文件大小超过限制"); } // 文件名字过滤 if (!isValidFileName(fileName)) { return Result.error("上传的文件名存在非法字符"); } String suffix = FileUploadUtils.getExtension(file); if (!FileUploadUtils.isAllowedExtension(suffix, MimeTypeUtils.IMAGE\_EXTENSION)) { return Result.error("上传文件类型不支持"); } String bizPath = "temp"; String savePath = null; try { String path = uploadpath \+ File.separator \+ bizPath + File.separator; File fileObj = new File(FilenameUtils.getFullPath(path)); if (!fileObj.exists()) { fileObj.mkdirs();// 创建文件根目录 } String extension = FileUploadUtils.getExtension(file); String endName = getExtension(extension); if (oConvertUtils.isNotEmpty(endName)) { fileName = System.currentTimeMillis() \+ "." \+ endName; } else { fileName = "" \+ System.currentTimeMillis(); } savePath = fileObj.getCanonicalPath() \+ File.separator \+ fileName; String dbpath = null; File savefile = new File(savePath); file.transferTo(savefile); //FileCopyUtils.copy(file.getBytes(), savefile); if (oConvertUtils.isNotEmpty(bizPath)) { dbpath = bizPath + File.separator \+ fileName; } else { dbpath = fileName; } if (dbpath.contains("\\\\")) { dbpath = dbpath.replace("\\\\", "/"); } } catch (IOException e) { log.error(e.getMessage(), e); } result.setMessage(savePath); result.setSuccess(true); uploadFileCount = uploadFileCount + 1; redisUtil.set("uploadFileCount",uploadFileCount); return result; }

1 个回答

铉清

使用Content-Disposition头浏览器在下载文件时不依赖于文件名防止通过修改Content-Disposition头进行攻击

随机文件名生成虽然代码中有生成时间戳加后缀的逻辑但未明确展示是否使用随机字符串以增加不可预测性使用UUID或类似的随机命名策略

  • 1 关注
  • 0 收藏,10365 浏览
  • 匿名 提出于 2023-05-26 08:39