Sanitizing string to prevent relative URI paths

I have an HTTP handler that I created to update information in a local SQL Express database.

I realized that the user can use the relative paths of the URI "/../../file.zip" as a query string and can upload files outside the restricted area.

The site is not yet online, so this is not a security problem right now, but I would really like to prevent such things.

I added a simple string.replace line that removes any ".." from the input request.

Is there anything else I have to do here to protect this?

public void ProcessRequest(HttpContext context) { string filesPath = "C:/Downloads/"; string fileName = context.Request.QueryString["filename"]; fileName = fileName.Replace("'", "''").Replace("..", "").Replace("/", "").Replace("\\", ""); if (!string.IsNullOrEmpty(fileName) && File.Exists(filesPath + fileName)) { context.Response.ContentType = "application/octet-stream"; context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", fileName)); context.Response.WriteFile(filesPath + fileName); //Do work to update SQL database here } else { context.Response.ContentType = "text/plain"; context.Response.Write(filesPath + fileName + " Invalid filename"); } } 
+6
source share
2 answers

I usually use this simple code to verify this problem:

(I type it directly so that it does not compile, it just gives you an idea)

 private string getPath(string basePath, string fileName) { var fullPath = System.IO.Path.GetFullPath(System.IO.Path.Combine(basePath, fileName)); if (fullPath.StartsWith(basePath)) return fullPath; return null; } 

The goal is to use Path.GetFullPath . This method will translate any /../ etc. In a full way. Then check that the returned path is in the allowed directory.
Make sure that this method can return an insignificant path than expected, for a more detailed explanation read the MSDN

+10
source

You may have Request.QueryString["filename"] actually the key representing the file. The key can be a number or a random string if you do not want users to easily guess about files. You can save the mapping in the database and use the key to get the local file name (and possibly the display file name if you want the two to be different and really hide implementation details).

+2
source

All Articles