I am looking to find a way I can secure admin area, especially the folder itself from outside access (These include folders with images and css). I have read a lot of suggestions but they all feel rather a compromise or work around than a bullet proof method or I am not understanding which is best for security and hidden from outside world, I want to be the only one that knows about it or access it. Hoping someone can shed some light what they would use, when they want the area completely hidden from outside world, whilst still accessible to you.
Some of the methods I have come across involve:
- Moving folder outside of root
- Using Htaccess Deny all. (also means I can't login unless I apply a static IP address which I do not have)
- Another way I thought of could be to use session variable to store admin, recognize and grant access based on session ID. (This does mean all other css files and image folders are viewable).
- Adding an index page in the folder which I see alot of sites do.
I currently have my login script to redirect me to my admin area, so is there anyway for the whole folder to recognize it's me and grant access and serve files on if a logged in admin php file is requesting it?, if not to decline access including images and css etc?
Can't figure out how best to protect this area? Is using session a secure way of identifying an admin?
The easiest way to ensure content is not exposed to the web is to place it above the site folder in your directory structure.
so for example in your Apache configuration mount the site at
/var/www/sites/site/content/
and place the restricted content at
/var/www/sites/site/
that way the content will not be exposed but php can still read it if required.
Obviously this will not stop users from seeing what is in your css files if php reads them and echoes them out but I dont see why a css file should need to be secure
Edit
Supposing you have a folder on your server at /var/www/sites/site/content/some_folder
and you enter www.yoursite.com/some_folder
into a browser, assuming you have indexes open in your site you will see a list of files in some_folder
But how can you get to /var/www/sites/site/
from a web brower ? ... you can't!!
but what you can do is some thing like this:
And this would be a php file inside the main site folder (visible to public)
<?php
session_start();
if(isset($_SESSION['admin_logged_in'])){
include '/var/www/sites/site/secret_content.php';
}
The first step would indeed be to move all files you want to prevent public access to to outside the document root. This way there is no way to access the files directly through your webserver.
If you are looking to prevent access for all resources (including images, scripts, stylesheets etc) you could implement a "proxy" which is responsible for serving the files (after checking whether the user is authorized).
The easiest and most flexible way to do this is to have a single entry point in the application. Using apache this can easily be achieved using the following rewrite rule:
RewriteEngine On
RewriteRule ^(.*)$ index.php [L,QSA]
This will make sure every request will go through your index.php file.
No you can easiy check whether you are allowed to access the resources using e.g.:
<?php
session_start();
if (!isset($_SESSION['user'])) {
header('HTTP/1.0 403 Forbidden');
exit; // important to prevent further execution of the script
}
// user is allowed access, do shit
The above is a very simplified example. Normally you may want to render an actual nice looking page telling the user he is not allowed to access you stuff / rendering a login page.
Now to render the protected resources you could do something like:
Directory structure
- Project
- public (docroot)
- index.php
- index.php
- other protected files
index.php in docroot
<?php
require_once __DIR__ . '/../index.php';
index.php in project
<?php
session_start();
if (!isset($_SESSION['user'])) {
header('HTTP/1.0 403 Forbidden');
exit; // important to prevent further execution of the script
}
$file = $_SERVER['REQUEST_URI']; // important to sanitize or possible check against whitelist the requested resource
$ext = pathinfo($path, PATHINFO_EXTENSION);
switch ($ext) {
case 'jpg':
case 'jpeg':
header('Content-type: image/jpeg');
imagejpeg('/path/to/protected/resources/' . $file);
break;
}
Now you will lhave total control over what you serve and to whom.
Note that whether it is secure depends entirely on what your implementation looks like, but in general:
- Always place your non public files outside of the document root
- Always sanitize / whitelist user input
- Always secure your data
Some generic, but related reads:
- Preventing Directory Traversal in PHP but allowing paths (very much related to the
$file = $_SERVER['REQUEST_URI'];
point)
- How can I prevent SQL-injection in PHP?
- Secure hash and salt for PHP passwords
Yes, you should move the content out of the document root. You could try using .htaccess to protect your files, but allowing overrides by .htaccess can itself be a security problem. It's certainly a performance problem.
Simply point your 404 handler at something like....
<?php
define('REQUEST_PATH', '/secure');
define('SECURED_CONTENT', '/var/www/restricted');
$req=parse_url($_SERVER["REQUEST_URI"]);
if ((0===strpos($req['path'],REQUEST_PATH))
&& $_SESSION['authenticated']) {
if (is_readable(SECURED_CONTENT . $req['path'])
&& is_file(SECURED_CONTENT . $req['path'])) {
header('Content-type: '
. mime_content_type(SECURED_CONTENT . $req['path']);
include(SECURED_CONTENT . $req_path);
} else {
header('HTTP/1.0 404 Not Found');
}
exit;
}
header('HTTP/1.0 403 Forbidden');