Filef=newFile(imgFile); if (f.exists() && !f.isDirectory()) { byte[] data = Files.readAllBytes(Paths.get(imgFile)); returnnewString(Base64.encodeBase64(data)); } else { return"File doesn't exist or is not a file."; } }
定位到漏洞代码和修复代码
@GetMapping("/path_traversal/vul") public String getImage(String filepath)throws IOException { return getImgBase64(filepath); }
// use while to sovle multi urlencode while (temp.indexOf('%') != -1) { try { temp = URLDecoder.decode(temp, "utf-8"); } catch (UnsupportedEncodingException e) { logger.info("Unsupported encoding exception: " + filepath); returnnull; } catch (Exception e) { logger.info(e.toString()); returnnull; } }
if (temp.contains("..") || temp.charAt(0) == '/') { returnnull; }
return filepath; }
修复也很简单,首先判断%,有则进行url解码处理,然后判断有无..和/,常规的过滤
文件上传审计
文件上传在spring业务中会很少,一般会采用cdn还有得上传到特定的目录下才能解析执行
spring的jsp文件必须在web-inf目录下才能执行
上传war包到tomcat的webapps目录。
没有过滤的上传
@PostMapping("/upload") public String singleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { if (file.isEmpty()) { // 赋值给uploadStatus.html里的动态参数message redirectAttributes.addFlashAttribute("message", "Please select a file to upload"); return"redirect:/file/status"; }
try { // Get the file and save it somewhere byte[] bytes = file.getBytes(); Pathpath= Paths.get(UPLOADED_FOLDER + file.getOriginalFilename()); Files.write(path, bytes);
@PostMapping("/upload/picture") @ResponseBody public String uploadPicture(@RequestParam("file") MultipartFile multifile)throws Exception { if (multifile.isEmpty()) { return"Please select a file to upload"; }
/** * Check if the file is a picture. */ privatestaticbooleanisImage(File file)throws IOException { BufferedImagebi= ImageIO.read(file); return bi != null; }
for (i = start ; !aRef && (i < limit) && ((c = spec.charAt(i)) != '/') ; i++) { if (c == ':') { Strings= toLowerCase(spec.substring(start, i)); if (isValidProtocol(s)) { newProtocol = s; start = i + 1; } break; }
通过:对协议进行截断,然后扔进isValidProtocol
privatebooleanisValidProtocol(String protocol) { intlen= protocol.length(); if (len < 1) returnfalse; charc= protocol.charAt(0); if (!Character.isLetter(c)) returnfalse; for (inti=1; i < len; i++) { c = protocol.charAt(i); if (!Character.isLetterOrDigit(c) && c != '.' && c != '+' && c != '-') { returnfalse; } } returntrue; }