File uploads are a common feature in many web applications, but they can be a serious security risk if not handled properly. One of the lesser-known (but highly dangerous) vulnerabilities is Path Traversal via File Upload. It’s a variation of an insecure file upload, which directly contributes to Broken Access Control, the #1 security risk in the OWASP Top 10 (2021).
If you’re working with Java, especially on web projects, this is something you definitely want to understand and guard against.
Understanding Path Traversal via File Upload
What is Path Traversal?
Path Traversal (also known as Directory Traversal) is a security vulnerability that occurs when an application improperly processes user-supplied input for file paths. Attackers exploit this by inserting special directory characters like ../
to navigate beyond the intended directory structure.
Path Traversal via File Upload
When a Java web application allows users to upload files, it typically:
- Receives the file from the client.
- Determines where to store it.
- Writes it to disk.
If the file’s name or path is not properly validated, an attacker could upload files outside the intended directory, potentially overwriting critical system files or executing malicious scripts.
Example: Vulnerable Java File Upload Code
public void uploadFile(HttpServletRequest request) throws IOException {
Part filePart = request.getPart("file");
String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();
String uploadDir = "/var/www/uploads/";
File file = new File(uploadDir + fileName);
filePart.write(file.getAbsolutePath());
}
What’s Wrong Here?
- Lack of input validation: The
fileName
comes directly fromfilePart.getSubmittedFileName()
, which an attacker can manipulate. - Directly concatenating file paths: This allows attackers to use
../
to traverse directories.
Exploiting Path Traversal via File Upload in Java
Let’s say an application allows users to upload files stored in a server’s directory, such as /var/www/uploads/. If an attacker uploads a file named:
Imagine an application that allows users to upload profile pictures. The application stores the profile pictures in a directory on the server, such as /images/profiles/
. If the application fails to validate the file name specified by the user properly, an attacker could upload a malicious file with a file name like ../../etc/passwd
. This would allow the attacker to access sensitive system files outside the intended directory structure.
../../../etc/passwd
The application would resolve the path as:
/var/www/uploads/../../../etc/passwd
Since ../
moves up the directory, the file ends up in /var/www/uploads/../../../etc/passwd
. If the server isn’t sanitizing the filename, Java will happily navigate directories and write the file where the attacker wants.
How to Prevent Path Traversal in File Uploads
1. Avoid Direct Use of User-Supplied File Names
Instead of saving files with user-provided names, generate a random filename:
import java.util.UUID;
public String generateSafeFileName(String originalFileName) {
String extension = originalFileName.substring(originalFileName.lastIndexOf("."));
return UUID.randomUUID().toString() + extension;
}
If you need the name for some reason, sanitize the filename to strip any path components. Never trust user input.
String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();
fileName = fileName.replaceAll("[^a-zA-Z0-9\\.\\-]", "_"); // basic sanitization
2. Enforce a Safe Upload Directory
Use java.nio.file
APIs to enforce that the file remains within your upload directory:
Path uploadPath = Paths.get(uploadDir);
Path resolvedPath = uploadPath.resolve(fileName).normalize();
if (!resolvedPath.startsWith(uploadPath)) {
throw new SecurityException("Invalid file path!");
}
Further, you should consider if one of the following points meets your business/security requirements
- Store the uploaded file on a different server
- This segregates the duty of your application and the host handling the uploaded files
- Store uploaded files in a non-public folder outside of the webroot folder (e.g.,
/opt/app/uploads/
). - Set restrictive file permissions (e.g., chmod 700).
3. Validate the File
Check MIME types and file signatures. Don’t just rely on file extensions.
String mimeType = Files.probeContentType(resolvedPath);
if (!allowedMimeTypes.contains(mimeType)) {
throw new SecurityException("Invalid file type!");
}
Further, you should consider the following points
- Set a filename length limit.
- Restrict the allowed characters.
- Set a file size limit
4. Use Security Libraries and keep your application up to date
Java security libraries like Apache Commons FileUpload or OWASP Java Encoder can help mitigate risks by handling file uploads securely.
As always, it’s a good idea to keep the libraries of your application updated to mitigate the attack vector for attackers.
Conclusion
Path Traversal via File Upload is one of those sneaky vulnerabilities that can easily slip under the radar. In Java, sanitising, validating, and controlling where and how files are stored is crucial. A few extra lines of code could save you from a massive security breach.
Check out also my other posts, e.g. SQL Injection in Java
👉 Feel free to get in touch with me for a personal consultation or hands-on support. Let’s make your application bulletproof together!
Stay safe, code smart! 😎