Monday 27 July 2009

Issue #4 Directory Traversal

This issue is one where you can get caught even though you think you are being smart :) What directory traversal means, is exactly like it sounds. Its moving between directories when you are not supposed to be able to. Now this is not like traversing directories when directory browsing in IIS is on for example. It means downloading files where it would normally be impossible to do. Such as the web.config.

Firstly it relies on a bit of patience and some poking around to find the correct information. Let us consider the following scenario.

The developer has created a nifty file download solution. It takes the name of a file and sends the file to the user with a Save As dialog box. A common enough scenario. The developer has created this application using ASP.NET and used the TransmitFile function that is part of the Response object.

A sample URL http://mydomain.com/ServeFile.aspx?FilePath=File.txt . In the code behind the developer uses code like the following

var filename = DateTime.Now.Ticks + ".txt"; 
var filePath = Request.QueryString["FilePath"];

if (string.IsNullOrEmpty(filePath)) return;

Response.ContentType = "text/plain";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + filename);
Response.TransmitFile(Server.MapPath("~") + filePath);
Response.End();


Fairly routine code, nothing too surprising. The developer creates a new filename and sets the content type of the request to text and then serves the file which will prompt a Save As dialog box in most browsers.


So where is the problem?.


Lets look at the following things. Server.MapPath(“~”) returns the physical root directory of the web application and the page blindly encodes the file it is looking for as a text file. Lets for the moment assume that the directory that it returns is c:\webs\Demo


So what would happen if we changed the URL slightly to the following:  http://mydomain.com/ServeFile.aspx?FilePath=web.config


Now the web.config file would be served as a text file to the user. If this config file contained connection strings that were not encrypted or other sensitive material, your system would be seriously compromised.  Furthermore, if the system is designed using the ASP.NET website template, you could download the ASPX and CS/VB code behind files as well as other DLLs and reverse engineer them. Your system would be thoroughly penetrated.


Right, so you found this issue and you change the code to use a specific directory for downloadable files. Your code now looks like this


var filename = DateTime.Now.Ticks + ".txt"; 
var filePath = Request.QueryString["FilePath"];

if(string.IsNullOrEmpty(filePath)) return;

Response.ContentType = "text/plain";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + filename);
Response.TransmitFile(Server.MapPath("~/downloads/")+filePath);
Response.End();

So the download URL is still the same http://mydomain.com/ServeFile.aspx?FilePath=File.txt. And the directory it is trying to read is c:\webs\Demo\downloads


If we try the http://mydomain.com/ServeFile.aspx?FilePath=web.config URL we will get an invalid file as there is no web.config file in that directory. So we are safe. Well no, you are not. Lets change the FilePath query string variable once more to http://mydomain.com/ServeFile.aspx?FilePath=../web.config


So in this case the directory is now c:\webs\demo\downloads\..\ which will be translated to c:\webs\demo because the ..\ says go one directory up from the current. Again we can download the web.config. The reason it is changed is that the directory translation works like that.


So how do you avoid such problems. Well first dont do what was just shown. If do want to transmit a file to the user make sure you know exactly what you are transmitting. Additionally a check to see if its the correct file type will usually give you an idea if something funky is happening.


You can prevent such types of problems by again validating your input and not sending the filename you want to download across the wire. Using id numbers is ok, but make sure you check your inputs again.


Always put your web apps on a different partition than your system files because if we were to use the following example it would be possible to get access to the other configuration files (providing that the permissions allowed).


Make sure your web server is fully patched and the correct permissions for your application are in force.


You can use tools such as URLScan and IIS Lockdown to scan your system for vulnerabilities. These tools are free and part of a well maintained server. Just be aware that URL Scan and IIS Lockdown can sometimes adversely affect your servers ability to serve certain requests such as ASMX which is possible if you tighten the security too much or don’t watch what the settings correctly.


You can download the code sample for this post here. It just shows how the code can manipulated and it serves as an example of what not to do!

No comments: