Directory traversal

This type of attack is also known as path traversal. The main goal is to show content of a file or directory via an application. Applications read data from the file system in many cases. Paths to these files or directories are often taken from input. If a user’s input is not handled carefully, users can read data from the root directory of the server’s file system.

Example of directory traversal

Let’s inspect the following code:

Response.Write("<strong>Absolute path e:\\: </strong><br />");
string[] dirs = Directory.GetDirectories("e:\\");
foreach (string dir in dirs)
            Response.Write(dir + "<br />");

Response.Write("<br /><strong>Read e:\\StorageHelper.cs with absolute path: </strong><br />");

Response.Write(File.ReadAllText("e:\\StorageHelper.cs") + "<br />");

Response.Write("<br /><strong>Root path of C: taken by ./../../../: </strong><br />");
string[] dirs2 = Directory.GetDirectories("./../../../");
foreach (string dir in dirs2)
            Response.Write(dir + "<br />");

Response.Write("<br/><strong>Read c:\\StorageHelper.cs with ./../../../: </strong><br />");

Response.Write(File.ReadAllText("./../../../StorageHelper.cs") + "<br />");

Response.Write("<br /><strong>Directory with application: taken by ServerMapPath(\"~/../\"): </strong><br />");
string[] dirs3 = Directory.GetDirectories(Server.MapPath("~/../"));
foreach (string dir in dirs3)
            Response.Write(dir + "<br />");

//This code throws an exception - but the security is poor here
Response.Write("Directory with application: taken by /../: <br/>");
string[] dirs4 = Directory.GetDirectories(Server.MapPath("/../."));
foreach (string dir in dirs4)
               Response.Write(dir + "<br />");

Response.Write("<br /><strong>Directory with application: taken by Server.MapPath(\"/\") + \"../: </strong><br />");
string[] dirs5 = Directory.GetDirectories(Server.MapPath("/") + "../");
foreach (string dir in dirs5)
            Response.Write(dir + "<br />");

The result of this code will look like this:

Absolute path e:\:

Read e:\StorageHelper.cs with absolute path:
************ Some code 2 ************

Root path of C: taken by ./../../../:

Read c:\StorageHelper.cs with ./../../../:
*************************** Some code StorageHelper.cs

Directory with application: taken by ServerMapPath(“~/../”):

Directory with application: taken by Server.MapPath(“/”) + “../:

These are listings from one particular hard disk. The exact paths or listings aren’t important, the important thing is that you can simply read any file or list any directory. And you can either use a relative or an absolute path. In this case, it is even a more severe vulnerability called full path disclosure. This bug enables the attacker to see a full path in an error message. The attacker finds out your directory structure and can effectively exploit a directory traversal vulnerability.

What can directory traversal attacks do

The first dangerous thing is that the attacker knows your directory structure. And if there are any sensitive information in files in your application directory, the attacker can simply download these files. A worse case is when your application enables the attacker to read files. The attacker can then read your configuration files (e.g., the connection string in web.config file) or the configuration files of the whole system (if the application is used by a highly privileged user).

Finding directory traversal vulnerabilities

Search for parts of your application where the application reads files and directories. Then try to change the input parameters to get content from a place outside of the application directory. In code, you can search for these strings:

  • ServerMapPath
  • FileStream
  • StreamReader

Avoiding directory traversal

Validate user inputs, check for absolute paths for sequences of “../”, and so on. Also, if you read a file, check if the file is within the application path. The application should never read data from a random path on a hard disk.