开发者

How do I make sure a file path is safe in C#?

I have an asp.net mvc app with a route that allows users to request files that are stored outside of the web application directory.

I'll simplify the scenario by just telling you that it's going to ultimately confine them to a safe directory to which they have full access.

For example:

If the user (whose ID is 100) requests:

http://mysite.com/Read/Image/Cool.png

then my app is going to append "Cool.png" to "C:\ImageRepository\Users\100\" and write those bytes to the response. The worker process has access to this path, but the anonymous user does not. I already have this working.

But will some malicious user be able to request something like:

http://mysite.com/Read/Image/..\101\Cool.png

and have it resolve to

"C:\ImageRepository\Customers\101\Cool.png"

(some other user's image?!)

Or something like that? Is there a way to make开发者_如何转开发 sure the path is clean, such that the user is constrained to their own directory?


How about

var fileName = System.IO.Path.GetFileName(userFileName);
var targetPath = System.IO.Path.Combine(userDirectory, fileName);

That should ensure you get a simple filename only.


Perhaps you should verify that the path starts with the user's directory path?

e.g. "C:\ImageRepository\Customers\100\"

You should also normalize the paths to uppercase letters when comparing them.


The safest way, if it is an option (you are using windows auth), is to make it a non-issue by using Active Directory rights on the folders so it doesn't matter if the user attempts to access a directory that is not valid.

Absent that, store the files so that the path is abstracted from the user. That is, use whatever name the user provides as a lookup in a table that has the REAL path to the file.

Cannolocalization protection is tricky business and it is dangerous to try and outthink a potential attacker.


Using the Request.MapPath overload is one way to check this:

try
{
  string mappedPath = Request.MapPath( inputPath.Text,                                  Request.ApplicationPath, false);
}
catch (HttpException)
{
  // do exception handling
}

Also you could explode the string and delimit it by slashes, and check the username match also.


To also be able to include a subdirectory in the path you can use:

string SafeCombine(string basePath, string path)
{
    string testPath = Path.GetFullPath(Path.Combine(basePath, path));
    if (testPath.startsWith(basePath))
        return testPath;
    throw new InvalidOperationException();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜