Access a File Which Is Located Before/Outside the Server Root Directory

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.

What's the safest method to access a php file thats outside the root directory?

This isn't going to directly answer your question, but maybe it will get you to look at your app structure differently. I think it's a misconception that it's not safe to include files from outside of your webroot.

On the contrary, many people have a structure where most if not all of their application logic is outside of the public_html or similar directory. Especially with catch-all router type systems.

You can have a structure like:

var
www
public
something.js
happy.jpg
index.php
application
bootstrap.php
AwesomeClass.php
Router.php

Now with your index.php you can work out the real root of your application.

Something like:

define('WEB_ROOT', __DIR__);
define('APP_ROOT', dirname(__DIR__));
define('PHP_ROOT', APP_ROOT . DIRECTORY_SEPARATOR . 'application');

You now have constants that point to the real filesystem path of your public html directory and where your php files are, and can now safely include files like:

include(PHP_ROOT . DIRECTORY_SEPARATOR . 'bootstrap.php');

This is perfectly safe, and many people have apps structured like this. It also prevents people being able to browse to any php files you have laying around, in the event that you don't have any .htaccess or similar voodoo in place.

How do I access files placed outside of the site root?

Have a look at the answers to this question, which seem to be doing more or less the same thing.

A quick summary: readfile() or file_get_contents() are what you're after. This example comes from the readfile() page:

<?php
$file = 'monkey.gif';

if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>

I don't recommend allowing the $file variable to be set using user input! Think about where the filenames are coming from before arbitrarily returning files in the response.

Is it possible to shield a directory/file on a server from the outside world, but make it accessible to PHP?

Absolutely-- in fact, you don't need to use .htaccess. Simply put the protected directory above your document root (that is, store it next to the folder where your PHP scripts are store, typically "htdocs," "httpdocs" or sometimes just "www').

So your web files would be in /my/folders/httpdocs/, and your "protected" files would be in /my/folders/protected_folder/

The idea here is that PHP can access any folder on the server, but Apache won't let the user navigate "above" the root directory.

To access the directory, you can use:

$protected_path = $_SERVER['DOCUMENT_ROOT'].'/../protected_folder/';

(Incidentally, you mentioned you're doing this to cache pages-- you might want to look at Smarty, the PHP template engine, which pre-compiles your templates and also supports really smart caching. And in fact, one of the Smarty "best practices" is to configure your structure so the template and cache files are not in or below the document_root folder, so users coming in from Apache can never get to them, but the Smarty PHP code can easily grab whatever it needs from there.)

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.

How can i show the images outside the web root directory in my php application?

PHP by default can already access files outside the web root, unless restricted with an open_basedir directive (or safe mode, but hope you're not in that cage).

It's normally a good practice to insert within a VirtualHost configuration an open_basedir restriction. You can specify multiple directories separated by : on Linux and ; on windows.

php_admin_value open_basedir /var/www/s/stage:/usr/share/php:/your/dir

To access those files either use an absolute path or a path relative to the position of the PHP file called. (So you'll have to ../ to reach levels above).

Also be sure that directories in which you want to write to are assigned to the webserver user and have write permission.

Otherwise you have second option:

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.



Related Topics



Leave a reply



Submit