Simple file downloader

Posted on

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.

Leave a Reply

Your email address will not be published. Required fields are marked *