Sanitize file path in PHP

Viewed 27654

I'm hoping to make my tiny program secure so that potential malicious users cannot view sensitive files on the server.

    $path = "/home/gsmcms/public_html/central/app/webroot/{$_GET['file']}";


    if(file_exists($path)) {
        echo file_get_contents($path);
    } else {
        header('HTTP/1.1 404 Not Found');
    }

Off the top of my head I know that input such as '../../../../../../etc/passwd' would be trouble, but wondering what other malcious inputs I should expect and how to prevent them.

9 Answers

realpath() will let you convert any path that may contain relative information into an absolute path...you can then ensure that path is under a certain subdirectory that you want to allow downloads from.

Use basename rather than trying to anticipate all the insecure paths a user could provide.

If you can, use a whitelist like an array of allowed files and check the input against that: if the file asked by the user isn't present in that list, deny the request.

There is an additional and significant security risk here. This script will inject the source of a file into the output stream without any server-side processing. This means that all your source code of any accessible files will be leaked to the internet.

Another approach:

$path = "/app/webroot/{$_GET['file']}";
$realTarget = realpath($path);

if( strtolower($path) !== strtolower($realTarget) ) {
    // invalid path!
}
// life goes on

I think this is the best answer for PHP7.

This will only allow people to see files they have the absolute path to.

It won't let people fish for valid filenames outside the specified path by making all failure conditions report the same.

$base_dir = $temp_path;
$path = "";
if(isset($_GET['filename'])) {
    $path = realpath($base_dir.$_GET['filename']);
    //realpath returns false if the file doesnt exist
    if(!$path ||
    //dont look outside temp path 
        substr($path, 0, strlen($base_dir)) != $base_dir){
            header('HTTP/1.1 404 Not Found'); 
            echo "The requested file could not be found";
            die;
    }
}
Related