• Browse topics
Login
Sign up
Login

SNYK LEARN LOGIN

OTHER REGIONS

For Snyk Enterprise customers with regional contracts. More info

Sign up

Directory traversal

Unintended disclosure of sensitive files

Select your ecosystem

Directory traversal: the basics

What is directory traversal?

A directory traversal attack aims to access files and directories that are stored outside the intended folder. By manipulating files with "dot-dot-slash (../)" sequences and its variations, or by using absolute file paths, it may be possible to access arbitrary files and directories stored on the filesystem; including application source code, configuration, and other critical system files.

About this lesson

In this lesson, you will learn how directory traversal works and how to mitigate it in your application. You will first use a directory traversal attack to hack a vulnerable web server. We will then explain directory traversal by showing you the backend code of that vulnerable server. Finally, we will teach you how to prevent directory traversal from affecting your code.

Ready to learn? Buckle your seat belts, put on your hacker's hat, and let's get started!

FUN FACT

Valar Morghulis - The faceless vulnerability

The directory traversal vulnerability wears many faces. Some people also call it path traversal, path manipulation, dot-dot-slash, directory climbing, or the backtracking vulnerability. All of these are actually the same vulnerability.

Directory traversal in action

Hacking a to-do app

To increase revenue and survive until the next funding round, a company called startup.io decided to create a side product. Since the market for image hosting platforms has recently become a bit saturated, the firm made a call to build an app for managing to-do lists instead.

Sadly, their to-do app is vulnerable to directory traversal attack. Let's use a terminal window and curl to exploit the vulnerability. Our goal is to view the /etc/passwd stored on the backend server.

The application is hosted on https://todoapp.startup.io. First, let's try to curl a page we should have access to.

Copy the following into the terminal: curl https://todoapp.startup.io/public/about.html

Demo terminal

Listing the public page

We see the about.html page returned, which is to be expected. Notice that this HTML page is being served from the public directory.

Let's remove the about.html filename from this request and see if we can get a directory listing back.

Copy the following into the terminal: curl https://todoapp.startup.io/public/

Demo terminal

Bingo! We've managed to list the files in the public directory. This is not a severe hack yet, since we're still in the public directory. However, showing a directory listing like this is a form of unnecessary information disclosure.

List one page up

Since we can list files in the public directory, maybe we could also traverse to other directories and see their contents? Let's add a ../ onto the URL to break up to the parent directory. Run the following command:

Copy the following into the terminal: curl https://todoapp.startup.io/public/../

Demo terminal

Uh oh, we've lost our directory listing and are back into HTML! Our attempt at performing directory traversal has been caught! Sanitization exists, and it caught our malicious effort. It looks like we've been taken back to the to-do app homepage.

Circumventing sanitization

Our hope is not lost yet! There is a different way to represent a . in the web world: URL encoding. Let's try to circumvent the sanitization by URL encoding the .s. Replace the .s with %2e as follows:

Copy the following into the terminal: curl https://todoapp.startup.io/public/%2e%2e/

Demo terminal

Congrats! You've broken out of the public directory. We can now step up our game and access some sensitive information.

Accessing sensitive information

I've got a suspicion we're running as the root user, so let's aim big and try to access some sensitive system information. For example, let’s access the /etc/passwd file. To do this, run the following command:

Copy the following into the terminal: curl https://todoapp.startup.io/public/%2e%2e/%2e%2e/etc/passwd

Demo terminal

Boom! We’ve managed to view the /etc/passwd file. Imagine what else we could disclose if we poked around the filesystem for a bit longer. Maybe SSL certificates? Or database passwords with read/write access to production databases?

Let's see what went wrong on the startup.io backend server, which allowed us to perform a directory traversal attack.

Directory traversal under the hood

How does directory traversal work?

Essentially, the attack is accomplished by adding characters such as ../ into a URL that serves content from a directory structure. The content is usually served from a base directory, such as /public. An attacker can supply filenames that contain ../ or a URL encoded equivalent %2e%2e%2f. These URLs allow the attacker to break out of the base directory and view files stored in other folders on the filesystem.

A directory traversal attack which shows a hacker sending malicious payload to a server and accessing files which shouldn't be publicly accessible

The vulnerable code

To illustrate this, let's jump into the code. Below you will find the a function, which constructs a filesystem path from the URL. All files and directories returned by the function are served statically by the web server.

$_REQUEST['img'] is sent to the server from user input. An attacker could make $image resolve to ../../../etc/passwd

FUN FACT

Double trouble!

In PHP, the include() function has a sibling: require()! These functions are identical except for how they handle errors (require will stop the script, include will only flag that an error occurred). Both, however, are vulnerable to directory traversal!

Scan your code & stay secure with Snyk - for FREE!

Did you know you can use Snyk for free to verify that your code
doesn't include this or other vulnerabilities?

Scan your code

Directory traversal mitigation

Resolving paths

We can use the “realpath” function to dereference the requested (relative) path, and return the absolute path of the file.

By defining a base path (or an array of allowable paths) in our program, we can compare them to the output of realpath and decide whether a request should be permitted or not. If the prefix paths do not match up, then our user could be attempting to access files they’re not supposed to!

Now the images may only be used if they reside within /var/www/html/site.com/images/, and it will not result in code injection, because we are using readfile() instead of include(). If the requested file doesn’t exist, or the path doesn’t begin with the one we specify, then this code will return a default placeholder.

FUN FACT

Zip Slip - A more dangerous cousin

As presented in this lesson, directory traversal is a read-only vulnerability: it allows the attacker to read sensitive files. However, there is a more dangerous cousin in the directory traversal family tree. That cousin is called Zip Slip, and it allows the attacker to execute commands by overwriting files on a remote server. Sounds scary? It is! Check out more about Zip Slip on Snyk's Zip Slip research page.

Quiz

Test your knowledge!

Quiz

Which of the following is the most accurate description of a directory traversal vulnerability in web applications?

Keep learning

To learn more about directory traversal, check out some other great content produced by Snyk:

Congratulations

You’ve learned what directory traversal is and how to protect your systems from it. We hope you will apply your new knowledge wisely and make your code much safer. Feel free to rate how valuable this lesson was for you and provide feedback to make it even better! Also, make sure to check out our lessons on other common vulnerabilities.