How to Serve Documents from Outside the Web Root Using PHP

How to serve documents from outside the web root using PHP?

I think something like this would work:

<?php
$path = realpath(dirname(__FILE__) . '/../my_files/' . $_GET['file']);

$parts = explode('/', pathinfo($path, PATHINFO_DIRNAME));
if (end($parts) !== 'my_files') {
// LFI attempt
exit();
}

if (!is_file($path)) {
// file does not exist
exit();
}

header('Content-Type: ' . mime_content_type($path));
header('Content-Length: ' . filesize($path));

readfile($path);

Serving documents outside the web root folder.

readfile is used with the parameter of a file name - NOT text.

Two examples that would work (file_get_contents):

public function viewDoc($doc) {

$path_parts = pathinfo($_SERVER['REQUEST_URI']);
$file = $doc;
$fileDir = '/var/uploads/';
$filePath = $fileDir . $file;

if (file_exists($filePath))
{
$contents = file_get_contents($filePath);
header('Content-Type: ' . mime_content_type($filePath));
header('Content-Length: ' . filesize($filePath));
echo $contents;
}
}

or (readfile):

public function viewDoc($doc) {
$path_parts = pathinfo($_SERVER['REQUEST_URI']);
$file = $doc;
$fileDir = '/var/uploads/';
$filePath = $fileDir . $file;

if (file_exists($filePath))
{
header('Content-Type: ' . mime_content_type($filePath));
header('Content-Length: ' . filesize($filePath));
readfile($filePath);
}
}

I also added the $filePath variable for you, as there's no reason to concat the string multiple times.

Edit

As extra security, to Yazmat's comment, you can use $file = str_replace(array('..', '/'), '', $doc); as this would remove all references to other directories (however, with the slash it would also remove access to sub directories, so you might want to skip that, dependend on your code and file structure).

PHP - Security in accessing files outside of web root

You need to allow Apache (assumed) to access that folder with images using Directory directive (http://httpd.apache.org/docs/2.2/mod/core.html#directory).

Or you can move images under root directory and restrict direct access to them using .htaccess if you want to keep them protected.

Serving images from outside of document root

The most common way is an Alias:

Alias /data/ /wherever/your/data/are/

Access a file which is located before / outside the server root directory?

You cannot directly access any file outside your web directory. As your question includes the tag PHP as well, I assume you may want to use it.

What you can do is the following:

Inside your www directory, create a "image.php" file, with a similar content to:

<?php
header('Content-Type: image/png');
readfile("../img/" . $_GET['img']);
?>

And call your images with

<img src="image.php?img=myimage.png" />

Please be aware that your PHP file shouldn't be that simple :) As you may want to address multiple image formats (and providing the correct header for them), checking for malicious file path/inclusions (you don't want to use $_GET without validating/sanitizing the input), extra caching etc. etc. etc.

But this should give you an idea on how you can target your issue.

How to serve a video from a file outside the web root in PHP to a html5 video source

Your code looks correct, and when I've just tested a very similar script, it has worked perfectly.

A couple of thoughts:

  • Have you tried accessing your video script (serve_movie.php) directly within your browser to see if you get the video?
  • Do you have error reporting turned on, and set to display errors? If so, are you getting any? I'm wondering if reading in the content of your video is exhausting PHP's memory limit due to its size.

To enable error reporting, add the following to your video script (serve_movie.php) before any other code:

error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', true);

Downloading files outside the webroot

After much trial and error, I appear to have solved the problem.

The issue was in using jQuery/Ajax.

When I changed the way the downloadscript.php file is accessed to a direct $_GET request from the link on the page, it worked a treat.

Anyway, thanks for your help everyone!

Chris

PHP include file in webroot from file outside webroot

Full path should be:

include('/home/xx/xx/domains/mydomain/webroot/file-to-include.php');

Or you should set the path like:

include(__DIR__ . '/../webroot/file-to-include.php');  // php version >= 5.3
include(dirname(__FILE__) . '/../webroot/file-to-include.php'); // php version < 5.3

How to upload a file to a folder outside web root

By default files will be uploaded well above the web root for security and you have to move them to wherever you want. Take a look at move_uploaded_file().

Have a look at print_r($_FILES) and it will show you the location of each file you have uploaded.



Related Topics



Leave a reply



Submit