Search code examples
javascriptphpsecurityfrontenddirectory-traversal

Restrict PHP script only to its directory and sub directories


I'm making a website with some image galleries. I want to do as little backend as possible. I have the images separated into folders. I have a PHP script that fetches the contents of a directory specified by a get param. fetchFiles.php?dir=./art. Javascript sends a fetch there and it returns a JSON array of image file names and creates images with an src of. I would like to have it so that PHP can only access things in the directory the script it's executing in, so someone can't access all the directories on the server.

fetchFiles.php

<?php
    echo json_encode(
        array_values(
            array_diff(
                scandir($_GET['dir'], SCANDIR_SORT_ASCENDING),
                array('.', '..', 'fetchFiles.php')
            )
        )
    );
?>

Solution

  • First of all, don't ever allow the user the ability to control input that directly affects your code. This conflating of code and user-supplied-data is precisely what leads to insecure code.

    Instead of letting the user decide what directory your PHP should look in, let PHP decide what directory it should look in.

    Instead of:

    scandir($_GET['dir'], SCANDIR_SORT_ASCENDING);
    

    Do this:

    const PICTURES_DIR = '/path/to/pictures/';
    scandir(PICTURES_DIR, SCANDIR_SORT_ASCENDING);
    

    If you must let the user supply some part of the input the least you can do is use a Whitelisting approach rather than just opening up your entire code to all sorts of vulnerabilities.

    $whiteList = ['/path1/', '/path2/', ...];
    
    if (in_array($_GET['path'], $whiteList)) { // It's OK
    
    } else { // Ohnoes :(
    
    }
    

    Now, PHP has something called a open_basedir restriction which prevents PHP from being able to go above a certain base directory, but really if you find yourself doing this just to be so lazy as to allow arbitrary user input to control your code you're already setting yourself up for failure.

    Security is built in layers. It's not a silver-bullet.