Problem
On my website I want to offer some PDFs, ZIP files and images for download. They are all in the same folder and I could simply link to them like <a href="download/file.pdf">download file</a>
. But instead I want to invoke a download dialog by sending an attachment header via php. The link would change into <a href="download/load.php?f=file.pdf">download file</a>
:
<?php
/***
* download/load.php
* Simple file downloader including mime type
*
* @param string $f name of file in download folder
* @return file with corresponding HTTP header
*/
// check whether parameter was sent
if ( !isset($_GET['f']) ||
// check whether it is not `load.php` (this file)
$_GET['f'] === "load.php" ||
// check whether file exists
!is_readable($_GET['f']) ||
// make sure file is in the current directory
strpos($_GET['f'], '/') ) {
header("HTTP/1.0 404 Not Found");
die();
}
$file = $_GET['f'];
// check mime type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file);
finfo_close($finfo);
// send mime type
header('Content-type: ' . $mime);
// invoke download dialog
header('Content-Disposition: attachment; filename=' . $file);
// send file
readfile($file);
?>
Is this script okay or does it have security vulnerabilities? If so, how could I improve it?
Solution
Take care to call strpos()
correctly. If the f
parameter contains a leading /
, it sneaks through.