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
This commit is contained in:
Nanne Baars 2024-07-28 17:47:30 +02:00 committed by GitHub
parent 2b0c22ac68
commit 58b762eade
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -28,6 +28,7 @@ import static org.springframework.http.MediaType.ALL_VALUE;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
@ -81,13 +82,19 @@ public class FileServer {
@PostMapping(value = "/fileupload") @PostMapping(value = "/fileupload")
public ModelAndView importFile( public ModelAndView importFile(
@RequestParam("file") MultipartFile myFile, Authentication authentication) @RequestParam("file") MultipartFile multipartFile, Authentication authentication)
throws IOException { throws IOException {
String username = authentication.getName(); var username = authentication.getName();
var destinationDir = new File(fileLocation, username); var destinationDir = new File(fileLocation, username);
destinationDir.mkdirs(); destinationDir.mkdirs();
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename())); // DO NOT use multipartFile.transferTo(), see
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename())); // 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( return new ModelAndView(
new RedirectView("files", true), new RedirectView("files", true),