Saturday, July 21, 2007

Protecting against Canonicalization Attacks

A canonicalization attack occurs when someone enters a filename requesting a file they aren't allowed to have or overwrites a file they shouldn't. Returning files that a user shouldn't have opens security holes because the file can contain sensitive information you don't want to expose. Allowing users to overwrite files causes a couple of problems. Perhaps they delete important information necessary for the operation of the site or the business. Another problem occurs when someone overwrites a file that is executable with a malicious file that can launch a virus.
The operating system tries to be user friendly and can resolve a filename, regardless of how you specify it. For example, the following four lines are equivalent: type c:\log.txt
type \log.txt
type \..\log.txt
type c:\log.txt;;;
It is difficult to test for every case. Figure 14-3 shows a fictitious example of input that renames a file. Notice that the New Name field is set to C:\\SomeData.xml, which should never be allowed. Sure enough, it is possible to write code that is not secure enough to prevent this. Listing 14-6 shows what happens when you click the Bad Rename button.
Figure 14-3
Listing 14-6: The wrong way to handle filename input

protected void btnBadRename_Click(object sender, EventArgs e)
{
// bad file handling - open to attack
string appPath = Request.PhysicalApplicationPath;
string oldPath = Path.Combine(appPath, txtOldName.Text);
string newPath = Path.Combine(appPath, txtNewName.Text);
File.Move(oldPath, newPath);
}
The problem with Listing 14-6 is that it grabs the input filename with no processing at all. The File class has no knowledge that it is an ASP.NET environment and you get no protection at all. Therefore, it does exactly as told and you'll have to hope that other security mechanisms, such as ACLs, help you out.
To work with filenames, most people use the Request.MapPath or Server.MapPath calls. Besides being a convenient way to get a full path to a file, the MapPath methods also help protect against canonicalization attacks. Listing 14-7 shows the secure way to work with filename input.
Listing 14-7: The proper way to handle filename input
protected void btnGoodRename_Click(object sender, EventArgs e)
{
// good file handling - Server.MapPath
// keeps files in application directory
string oldPath = Server.MapPath(txtOldName.Text);
string newPath = Server.MapPath(txtNewName.Text);
File.Move(oldPath, newPath);
}
I know that most people use the MapPath methods all the time. However, some people just like to be dif- ferent. Also, if you are calling a reusable library that handles files, it may not have security in mind. You should test the library with bad input to determine whether it is secure. If not, you can write your own routine or wrap the call in your own type that does proper validation on the input. Using Request.MapPath and Server.MapPath makes your ASP.NET application more resistant to canonicalization attacks.
Important
If you're wrapping a third-party library to validate input with your own class, you won't have direct access to the Server property. However, you can still get to the MapPath method by calling HttpContext.Current.Server.MapPath();.

No comments: