Preventing Directory Traversal in PHP but allowing paths

directory-traversal, php, security

Solution

Well, one option would be to compare the real paths:

$basepath = '/foo/bar/baz/';
$realBase = realpath($basepath);

$userpath = $basepath . $_GET['path'];
$realUserPath = realpath($userpath);

if ($realUserPath === false || strpos($realUserPath, $realBase) !== 0) {
    //Directory Traversal!
} else {
    //Good path!
}

Basically, `realpath()` will resolve the provided path to an actual hard physical path (resolving symlinks, `..`, `.`, `/`, `//`, etc)... So if the real user path does not start with the real base path, it is trying to do a traversal. Note that the output of `realpath` will not have any "virtual directories" such as `.` or `..`...

Problem

I have a base path /whatever/foo/ and `$_GET['path']` should be relative to it. However how do I accomplish this (reading the directory), without allowing directory traversal? eg. ``` /\.\.|\.\./ ``` Will not filter properly.

Original source