Reputation: 133
I have a question. I got a PHP script (PHP 5) which is saving a URL-Parameter $_GET['file']
to the variable $file
. Is there now a way to check if this variable is a valid filename (for example: hello.txt
and not /../otherdir/secret.txt
). Because without checking the $file variable a hacker would be able to use the /../
to get to my parent folder.
Upvotes: 13
Views: 19165
Reputation: 4598
Instead of checking valid characters why not looking for character you don't want. Also filenames are limited to 255 characters:
function valid_filename(string $filename)
{
if (strlen($filename) > 255) { // no mb_* since we check bytes
return false;
}
$invalidCharacters = '|\'\\?*&<";:>+[]=/';
if (false !== strpbrk($filename, $invalidCharacters)) {
return false;
}
return true;
}
valid_filename('hello'); // true
valid_filename('hello.php'); // true
valid_filename('foo:bar.php'); // false
valid_filename('foo/bar'); // false
Adapt $invalidCharacters
according to your needs/OS.
Source: https://www.cyberciti.biz/faq/linuxunix-rules-for-naming-file-and-directory-names/
Upvotes: 2
Reputation: 1095
POSIX "Fully portable filenames" lists these: A-Z
a-z
0-9
.
_
-
Use this code to validate the filename against POSIX rules using regex:
/
- forward slash (if you need to validate a path rather than a filename)\w
- equivalent of [0-9a-zA-Z_]
-
.
- dash dot space$filename = '../../test.jpg';
if (preg_match('/^[\/\w\-. ]+$/', $filename))
echo 'VALID FILENAME';
else
echo 'INVALID FILENAME';
If you want to ensure it has no path (no forwardslash) then change the regex to '/^[\w\-. ]+$/'
.
Upvotes: 8
Reputation: 4207
You may have a look in php's basename
function, it will return with filename, see example below:
$file = '../../abc.txt';
echo basename($file); //output: abc.txt
Note: basename
gets you the file name from path string irrespective of file physically exists or not. file_exists
function can be used to verify that the file physically exists.
Upvotes: 9
Reputation: 265
Would that work? http://php.net/manual/en/function.file-exists.php E.g, in your case,
if(file_exists(str_replace("../", "", $file))){
// valid
}
else{
// invalid
}
Files can be in subfolders but not in parent folders.
However, if you're just interested in the filename,
if(file_exists(pathinfo($file, PATHINFO_BASENAME))){
// valid
}
else{
// invalid
}
should work.
Upvotes: -2
Reputation: 310
i will like to combine kamal pal's and Pancake_M0nster's answers to create simple:
if(file_exists(basename($file))){
// valid
}
else{
// invalid
}
Upvotes: -3