From 58b762eadebec2fa5380c1f382faf3d7f11b6498 Mon Sep 17 00:00:00 2001 From: Nanne Baars Date: Sun, 28 Jul 2024 17:47:30 +0200 Subject: [PATCH] fix: copying file using `transferTo` sometimes fails. (#1862) Turns out that using this method sometimes fails with an exception about unable to delete a directory. The stacktrace points to: ``` java.nio.file.FileSystemException: /tmp/webwolf-fileserver/dumbanddummer/xxe_a11.dtd: Not a directory at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:100) ~[na:na] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) ~[na:na] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[na:na] at java.base/sun.nio.fs.UnixFileSystemProvider.implDelete(UnixFileSystemProvider.java:248) ~[na:na] at java.base/sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:110) ~[na:na] at java.base/java.nio.file.Files.deleteIfExists(Files.java:1191) ~[na:na] at java.base/java.nio.file.Files.copy(Files.java:3147) ~[na:na] at io.undertow.server.handlers.form.FormData$FileItem.write(FormData.java:274) ~[undertow-core-2.3.10.Final.jar!/:2.3.10.Final] at io.undertow.servlet.spec.PartImpl.write(PartImpl.java:119) ~[undertow-servlet-2.3.10.Final.jar!/:2.3.10.Final] at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile.transferTo(StandardMultipartHttpServletRequest.java:254) ~[spring-web-6.0.13.jar!/:6.0.13] at org.owasp.webgoat.webwolf.FileServer.importFile(FileServer.java:89) ``` It has to do with the underlying implmentation in Undertow. An explaination can be found here: https://stackoverflow.com/questions/60336929/java-nio-file-nosuchfileexception-when-file-transferto-is-called The solution is to take the input stream and use a simple `Files.copy()` to copy the file. Closes: #1737 --- .../org/owasp/webgoat/webwolf/FileServer.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/owasp/webgoat/webwolf/FileServer.java b/src/main/java/org/owasp/webgoat/webwolf/FileServer.java index 63c173da2..58924e5d6 100644 --- a/src/main/java/org/owasp/webgoat/webwolf/FileServer.java +++ b/src/main/java/org/owasp/webgoat/webwolf/FileServer.java @@ -28,6 +28,7 @@ import static org.springframework.http.MediaType.ALL_VALUE; import jakarta.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import java.nio.file.attribute.FileTime; import java.time.ZonedDateTime; @@ -81,13 +82,19 @@ public class FileServer { @PostMapping(value = "/fileupload") public ModelAndView importFile( - @RequestParam("file") MultipartFile myFile, Authentication authentication) + @RequestParam("file") MultipartFile multipartFile, Authentication authentication) throws IOException { - String username = authentication.getName(); + var username = authentication.getName(); var destinationDir = new File(fileLocation, username); destinationDir.mkdirs(); - myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename())); - log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename())); + // DO NOT use multipartFile.transferTo(), see + // https://stackoverflow.com/questions/60336929/java-nio-file-nosuchfileexception-when-file-transferto-is-called + try (InputStream is = multipartFile.getInputStream()) { + var destinationFile = destinationDir.toPath().resolve(multipartFile.getOriginalFilename()); + Files.deleteIfExists(destinationFile); + Files.copy(is, destinationFile); + } + log.debug("File saved to {}", new File(destinationDir, multipartFile.getOriginalFilename())); return new ModelAndView( new RedirectView("files", true),