Potential path traversal vulnerability when using File class and its solution
Tags: webdev, programming, java, security
Published: 2023-06-12 11:53:31

**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.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s83boggraw3qixpwo7j1.png)


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 .

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ep9bq2l95sujfh3iwv7.png)

Also I have created another text file named "**test**" inside “**C:\Users\arpan.bandyopadhyay\myfiles**” and stored “**arpan**” inside it. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tbc876ld3mnddf5hxqsg.png)

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. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axu6qlu3rgveit4amfky.png)

 
_**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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wqucfbvcx2ttu29hnn7z.png)


_**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**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fnobivyovjx2nzgv4hx6.png)



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.