Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: normalize path of not existing directories to prevent directory traversals?

I would like to normalize a path from an external resource to prevent directory traversal attacks. I know about the realpath() function, but sadly this function returns only the path of existing directories. So if the directory doesn't exist (yet) the realpath() function cuts off the whole part of the path which doesn't exist.

So my Question is: Do you know a PHP function which only normalizes the path?

PS: I also don't want to create all possible directories in advance ;-)

like image 437
JepZ Avatar asked Apr 08 '12 16:04

JepZ


2 Answers

There's no built-in PHP function for this. Use something like the following instead:

function removeDots($path) {
    $root = ($path[0] === '/') ? '/' : '';

    $segments = explode('/', trim($path, '/'));
    $ret = array();
    foreach($segments as $segment){
        if (($segment == '.') || strlen($segment) === 0) {
            continue;
        }
        if ($segment == '..') {
            array_pop($ret);
        } else {
            array_push($ret, $segment);
        }
    }
    return $root . implode('/', $ret);
}
like image 73
Tom Imrei Avatar answered Oct 23 '22 10:10

Tom Imrei


Thanks to Benubird / Cragmonkey corrected me that under some situation my previous answer didn't work. thus I make a new one, for the original purpose: Perform good, fewer lines, and with pure regular expression:

This time I tested with much more strict test case as below.

$path = '/var/.////./user/./././..//.//../////../././.././test/////';

function normalizePath($path) {
    $patterns = array('~/{2,}~', '~/(\./)+~', '~([^/\.]+/(?R)*\.{2,}/)~', '~\.\./~');
    $replacements = array('/', '/', '', '');
    return preg_replace($patterns, $replacements, $path);
}

The correct answer would be /test/.

Not meant to do competition, but performance test is a must:

test case: for loop 100k times, on an Windows 7, i5-3470 Quad Core, 3.20 GHz.

mine: 1.746 secs.

Tom Imrei: 4.548 secs.

Benubird: 3.593 secs.

Ursa: 4.334 secs.

It doesn't means my version is always better. In several situation they perform simular.

like image 30
Val Avatar answered Oct 23 '22 11:10

Val