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')
)
)
);
?>
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.
scandir($_GET['dir'], SCANDIR_SORT_ASCENDING);
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.