views:

41

answers:

3

Consider the following security problem:

I have a static base path (/home/username/) to which I append a user-controlled sub-path (say foo/bar.txt). The content of this file is then read and presented to the user.

In the case described the full path would be: /home/username/foo/bar.txt

Now to the problem. I want to control so that the full path is always a subdirectory of the static base path. In other words I don't want the user to supply a path such that the base path is escaped.

The following full path is OK:

/home/username/foo/bar.txt

Whereas this one is one is clearly not safe:

/home/username/foo/../../../etc/passwd

To complicate matters further the proper solution of chroot:ing to the base path is not available. Due to various reasons the only available solution is to use a regexp to differentiate between safe and unsafe paths.

Given the problem outlined above, what is the proper regexp?

Please note:

  • The code will run under Linux. The path separator is hence /.
  • The question is totally language agnostic.
  • Please do not suggest other ways to solve the problem. I know that there are alternative better ways to solve it (such as chroot:ing), but this question is restricted to the regexp solution only.
+1  A: 

You can simply reject any user input that matches /(^|\/)\.\.(\/|$)/

That means: if it contains /../ or begins with ../ or ends with /.. or is ..

Leventix
But you have to make sure, that you prepend '/home/username/', otherwise `~/something` or `/var/log` will cause problems.
Leventix
A: 

I believe it can't be done using just one single regexp. Regexps can't count anything, while here you definitely need to count the number of ../

However, you may try using recursive regexps and check for recursive nesting of ([[:alpha:]]+/..), like [[:alpha:]]+(\R)|..

I agree that it is better to forbid ../ at all

Dmitry
+1  A: 

If you don't want to reject it outright, just strip any "../" from the path, like this :

sed -e 's/\..\///g'

You should be aware that there could be files in the directory hierarchy that you allow that are linked to directories outside of that hierarchy.

Without using chroot I don't think there is a way that you can guarantee for it to be totally safe.

Tim