4

I have a directory and a dynamic file name. Are there any functions I can use to make sure it is impossible to break out from the specified directory?

for example:

secure_path('/tmp/', 'file.txt') -> /tmp/file.txt
secure_path('/tmp/', '../file.txt') -> /tmp/file.txt
Philip
  • 151
  • 2
  • 9

3 Answers3

2

Use realpath() to get a canonic form of the path, and eliminate any ../-s. Then verify that it contains the full path of the directory you want to contain it to.

Such as:

$path = "/tmp/file.txt";
$directory = "{full path of your files directory}";

if (strpos(realpath($path), $directory) === 0) {
    // path OK
}
else {
    // path not ok
}
hakre
  • 193,403
  • 52
  • 435
  • 836
hogdex
  • 51
  • 5
2

If you're only working in the single directory and not subdirectories below you could do

$file = "/tmp/".basename($input);

Which should give you the filename at the end of any path given in input, and append it to the directory you wanted.

BugFinder
  • 17,474
  • 4
  • 36
  • 51
0

I don't really know how ../file.txt is supposed to turn into /tmp/file.txt in your example, but to check whether a path is a subpath of another, use realpath with a simple comparison:

$path = '../foo';
$allowedPath = '/tmp/';

$path = realpath($path);
if (substr($path, 0, strlen($allowedPath)) !== $allowedPath) {
    // path is not within allowed path!
}
deceze
  • 510,633
  • 85
  • 743
  • 889