This article is my summary note after learning on the PortSwigger Academy. If you curious about the Academy, You can visit the PortSwigger Academy in this link.
Path Traversal (also known as “directory traversal”) are vulnerabilities that enable an attacker to read arbitrary files on the server that is running an application.
1. Attack
1.1 Reading arbitrary files via path traversal
Imagine a shopping application that displays images of items for sale. This might load an image using the following HTML:
<img src="/loadImage?filename=218.png">
The loadImage
URL takes a filename
parameter and returns the contents of the specified file.
The image files are stored on disk in the location /var/www/images
. To return an image, the application appends the requested filename to this base directory and uses a filesystem API to read the contents of the file. In other words, the application reads from the following file path:
/var/www/images/218.png
This application implements no defenses against path traversal attacks. As a result, an Attacker can request the following URL to retrieve the /etc/passwd
file from the server filesystem:
https://insecure-website.com/loadImage?filename=../../../etc/passwd
This causes the application to read from the following file path:
/var/www/images/../../../etc/passwd
The sequence ../
is valid within a file path and means to step up one level in the directory structure. The three executive ../
sequences step up from /var/www/images
to the filesystem root, and so the file that is actually read is:
/etc/passwd
On Unix-based operating systems, this is a standard file containing details of the users that are registered on the server, but an attacker could retrieve other arbitrary files using the same technique.
On Windows, both ../
and ..\
are valid directory traversal sequences. The following is an example of an equivalent attack against a Windows-based server.
https://insecure-website.com/loadImage?filename=..\..\..\windows/win.ini
1.2 Common obstacles to exploiting path traversal vulnerabilities
Many applications that place user input into file paths implement defenses against path traversal attacks. These can often be bypassed. If an application steps of blocks directory traversal sequences from the user-supplied filename. it might be possible to bypass the defense using a variety technique.
- You might be able to use an absolute path from filesystem root, such as
filename=\etc\passwd
, to directly reference a file without using any traversal sequences. - You might be able to use nested sequences, such as
....//
or....\/
. These revert to simple traversal sequences when the server sequences is stripped.
In some context, such an is a URL path or the filename
parameter if a multipart/form-data
request, web servers may strip any directory traversal sequences before passing your input to the application.
You can sometimes bypass this kind of sanitization by URL encoding or even double URL encoding the ../
characters. This results %2e2e2f
and %252e%252e%252f
respectively. Various non-standard encodings, such as ..%c0%af
or ..%ef%bc%8f
may also work.
For Burp Suite Professional users, Burp Intruder provides the predefined payload list
Fuzzing - path traversal
. This contain some encoded path traversal sequences that you can try.
An application may require the user-supplied filename to start with the expected base folder, such as /var/www/images
. In this case, it might be possible to include the required base folder filename=/var/www/images/../../../etc/passwd
.
An application may require the use supplied filename to end with an expected file extension, such as .png
. In this case, it might be possible to use a null byte to effectively terminate the file path before the required extension. For example filename=../../../etc/passwd%00.png
2. Prevention
The most effective way to prevent Path Traversal vulnerabilities is to avoid passing user supplied input to filesystem APIs altogether. Many application functions that do this can be rewritten to deliver the same behavior in a safer way.
If you can’t avoid passing user-supplied input to filesystem APIs, we recommended using two layers of defense to prevent attacks:
- Validate the user input before processing it. Ideally, compare the user input with a whitelist of permitted values. If that isn’t possible, verify that the input contains only permitter content, such as alphanumeric characters only.
- Alter validating the supplied input, append the input to the base directory and use a platform filesystem API to canonicalize the path. Verify that the canonicalized path starts with the expected base directory. Below is an example of some simple Java code to validate the canonical path of a file based on user input:
file = new File(BASE_DIRECTORY, userInput);
if (file.getCanonicalPath().startsWith(BASE_DIRECTORY)) {
// process file
}