Is there a way to safely sanitize path input, without using realpath()
?
Aim is to prevent malicious inputs like ../../../../../path/to/file
$handle = fopen($path . '/' . $filename, 'r');
Advertisement
Answer
Not sure why you wouldn’t want to use realpath
but path name sanitisation is a very simple concept, along the following lines:
- If the path is relative (does not start with
/
), prefix it with the current working directory and/
, making it an absolute path. - Replace all sequences of more than one
/
with a single one (a). - Replace all occurrences of
/./
with/
. - Remove
/.
if at the end. - Replace
/anything/../
with/
. - Remove
/anything/..
if at the end.
The text anything
in this case means the longest sequence of characters that aren’t /
.
Note that those rules should be applied continuously until such time as none of them result in a change. In other words, do all six (one pass). If the string changed, then go back and do all six again (another pass). Keep doing that until the string is the same as before the pass just executed.
Once those steps are done, you have a canonical path name that can be checked for a valid pattern. Most likely that will be anything that doesn’t start with ../
(in other words, it doesn’t try to move above the starting point. There may be other rules you want to apply but that’s outside the scope of this question.
(a) If you’re working on a system that treats //
at the start of a path as special, make sure you replace multiple /
characters at the start with two of them. This is the only place where POSIX allows (but does not mandate) special handling for multiples, in all other cases, multiple /
characters are equivalent to a single one.