Potential path traversal vulnerability when using File class and its solution
Arpan Bandyopadhyay
Posted on June 12, 2023
What is path/directory traversal?
Directory traversal (also known as file path traversal) is a web security vulnerability that allows an attacker to read arbitrary files on the server that is running an application. This might include application code and data, credentials for back-end systems, and sensitive operating system files. In some cases, an attacker might be able to write to arbitrary files on the server, allowing them to modify application data or behavior, and ultimately take full control of the server.
In Java, a file API can take a filename as the second argument and construct the file path based on the directory specified in the first argument. If the applications place user input into file paths, this could result in a path traversal attack. An attacker might try to manipulate the file path using special characters in the user input.
Here , I have created a small POC to demonstrate the vulnerability.
I have created a text file "pass" inside “C:\Users” and stored 1234 inside it .
Also I have created another text file named "test" inside “C:\Users\arpan.bandyopadhyay\myfiles” and stored “arpan” inside it.
Now assume that our requirement is to develop one java code using which we can access and read the files present inside “C:\Users\arpan.bandyopadhyay\myfiles” . In my case I am reading “test” file .
*Here is my java code . (Non Compliant) *
import java.io.*;
public class Filecano1 {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\arpan.bandyopadhyay\\myfiles", "test.txt");
BufferedReader br
= new BufferedReader(new FileReader(file));
// Declaring a string variable
String st;
// Condition holds true till
// there is character in a string
while ((st = br.readLine()) != null)
// Print the string
System.out.println(st);
}
}
If I execute the above code I can see content of the “test” file , which is well and good.
Then, where is the vulnerability ?
File class present inside java.io package is having below constructors :
File(File parent, String child)
Creates a new File instance from a parent abstract pathname and a child pathname string.File(String pathname)
Creates a new File instance by converting the given pathname string into an abstract pathname.File(String parent, String child)
Creates a new File instance from a parent pathname string and a child pathname string.File(URI uri)
Creates a new File instance by converting the given file: URI into an abstract pathname.
Here , I am using File(String parent, String child) constructor ,where first argument of the constructor is the base directory, and second argument is child directory path . In the above example, if the user can influence the value of child directory path , he/she can manipulate the value start with "../". An attacker might also use various non-standard encoding, such as ..%c0%af, ..%252f, or a null byte to bypass the input filter.
Now I will show you How Attacker can access and read files which is not present in the base location using the same above code “C:\Users\arpan.bandyopadhyay\myfiles” but present in the system using the below code.
import java.io.*;
public class Filecano1 {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\arpan.bandyopadhyay\\myfiles", "..\\..\\pass.txt");
System.out.println(file.getCanonicalPath());
// process file
BufferedReader br
= new BufferedReader(new FileReader(file));
// Declaring a string variable
String st;
// Condition holds true till
// there is character in a string
while ((st = br.readLine()) != null)
// Print the string
System.out.println(st);
}
}
Here we can see though I have specified the different base location/base directory , I am able to see the data which is present inside “C:\Users” , This is vulnerable . Files present inside this location, might include application code and data, credentials for back-end systems, and sensitive operating system files.
Now how to prevent this attack ?
Ensure user inputs are properly sanitized by whitelisting permitted names and/or characters.
Use getCanonicalPath() method of the given file object and validate the file name against a list of valid benign for path names.
The getCanonicalPath() method is a part of Path class. This function returns the Canonical pathname of the given file object. If the pathname of the file object is Canonical, then it simply returns the path of the current file object. The Canonical path is always absolute and unique, the function removes the ‘.’ ‘..’ from the path, if present.
See the below code :
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class Filecano {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\arpan.bandyopadhyay\\myfiles", "..\\..\\pass.txt");
if(file.getCanonicalPath().startsWith("C:\\Users\\arpan.bandyopadhyay\\myfiles")) {
// process file
BufferedReader br
= new BufferedReader(new FileReader(file));
// Declaring a string variable
String st;
// Condition holds true till
// there is character in a string
while ((st = br.readLine()) != null)
// Print the string
System.out.println(st);
}
}
}
Here I used getCanonicalPath() method of the given file object and validate the file name against Base directory path .
Now here you can see canonical path is printed and as the child path does not start with base directory path , it does not execute the code inside IF block and we cant access and read the content of pass.txt
This is how getCanonicalPath() helps us to prevent directory traversal attack.
Let's connect:
LinkedIn : https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/
** reference - internet, youtube vlogs.
Posted on June 12, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.