I am trying to create a function that will block access to some of my low level directories. For example, while building my site I don't want to allow uploads to be uploaded any lower than /var/www/html/site/uploads/ should I make a mistake while coding. This will also help to prevent a directory delete typo while removing cache files or whatever.
This is easily done with realpath() and strcasecmp().
The problem is that I can't use realpath() to generate an absolute path because any calls to this function with directories that don't exist will return FALSE. Below is my best attempt at looking at paths to validate them.
function is_sub_dir($path = NULL, $parent_folder = NULL) {
//Convert both to real paths
//Fails if they both don't exist
//$path = realpath($path);
//$parent_folder = realpath($parent_folder);
//Neither path is valid
if( !$path OR !$parent_folder ) {
return FALSE;
}
//Standarize the paths
$path = str_replace('\\', '/', $path);
$parent_folder = str_replace('\\', '/', $parent_folder);
//Any evil parent directory requests?
if(strpos($path, '/..') !== FALSE) {
return FALSE;
}
//If the path is greater
if( strcasecmp($path, $parent_folder) > 0 ) {
return $path;
}
return FALSE;
}
//BAD FOLDER!!!
var_dump(is_sub_dir('/var/www/html/site/uploads/../', '/var/www/html/site/uploads/'));
Does anyone know how to properly put file path blocks in place to guard against low-level folder access?
:UPDATED:
I want to further explain that this checking method will be used on multiple severs as well as in the creation of directories that are higher than a given directory.
For example, in my uploads directory I wish to allow administrators to create new sub directories such as ...uploads/sub/. By figuring out a reliable way to insure that the directory given is in fact higher than the parent directory - I can feel safer allowing my admins to work with the file system in the uploads folder.
So since I might need to verify that uploads/sub is higher than uploads/ before I create it I can't use realpath() because uploads/sub doesn't exist again.
As for the actual location of the uploads folder that is figured on the fly by PHP.
define('UPLOAD_PATH', realpath(dirname(__FILE__)));
:UPDATE 2:
I have an idea, what if I were to use realpath to compare the the whole path minus the last directory segment. Then even if that last directory segment still needed to be created - the rest of the path could be forced to match the minimum parent directory?