I'm currently working on a web project for a gaming group, and I'm trying to test myself and expand my general knowledge and toolbox. One of the features I'm working on requires me to "clean" the URL of a requested file. I have the system in place, and it works beautifully. Now, in order for my website to work 'flawlessly', I need to deny access to certain folders, and all files within, through htaccess. But there's a slight catch... It needs to operate without the user even realising.
My file structure, preferred access method, path, and status, are as follows:
rogue {allow} {direct} {%domain%/dashboard/} {200}
css {deny} {direct} {%domain%/css/} {403}
js {deny} {direct} {%domain%/js/} {403}
fonts {deny} {direct} {%domain%/fonts/} {403}
files {deny} {direct} {%domain%/files/} {403}
image {deny} {direct} {%domain%/image/} {403}
includes {deny} {direct} {%domain%/includes/} {403}
php {deny} {direct} {%domain%/php/} {403}
index.php {allow} {direct} {%domain%/dashboard/} {200}
html_footer.php {deny} {direct} {%domain%/dashboard/} {404}
html_header.php {deny} {direct} {%domain%/dashboard/} {404}
.htaccess {deny} {direct} {%domain%/dashboard/} {403}
The above list is actually an example of how I'd like the website to operate... The index.php
file controls the requested 'files' and displays them accordingly. For example, %domain%/get-in-touch/
would display the contact.php
file within the %domain%/includes/
directory. Calling index.php
directly displays the same as %domain%/dashboard/
.
The following code is from my .htaccess
file.
Please, ignore the # NN
snippets. These are for your benefit to reduce the need for me to add code snippets. I suppose it would help you, too... You could directly reference the line numbers should you need to.
DirectoryIndex index.php # 01
Options All +FollowSymlinks -Indexes # 02
# 03
<IfModule mod_rewrite.c> # 04
RewriteEngine On # 05
#RewriteBase /rogue/ # 06
# 07
RewriteCond %{REQUEST_FILENAME} !-d # 08
RewriteCond %{REQUEST_FILENAME} !-f # 09
RewriteRule ^(.*?)$ index.php [QSA,L] # 10
# 11
RewriteCond %{REQUEST_FILENAME} -d # 12
RewriteRule ^(.*?)(js|image|css|includes|php|files)(.*)$ index.php [QSA,L] # 13
</IfModule> # 14
I commented out line 06 as the system didn't seem to need it, but I kept it for my own reference and in the off chance that I may need it later. Lines 08 through 10 control redirection to index.php
when a file or a directory doesn't exist, and then the responding file controls the rest. The folders css/js/fonts/image/includes/php
all exist, so lines 12 and 13 prevent access to them and redirect to index.php
where the array of 'directories' can be located and the relevant files can be selected for inclusion. An example of the array is included at the bottom of the post. Lines 12 and 13 can be moved above line 08 and there would be no change, but removing them from the file causes a default 403 Forbidden error to fire.
Removing lines 08, 09, 12 and 13 causes the page to break by loading the files located in the image
, files
and fonts
directories as MIME type text/html
, however, the files within any other directories are seemingly unaffected.
Lines 12 and 13 perform as required, until you request access to a file within those directories. The file is displayed, and all of my secrecy is exposed to the world. As a result, certain files that have a great deal of importance are shown to the users. I want to prevent anybody from accessing the files within any folder I choose to deny access to, and have it redirect them to index.php
and show a 403
. I've attempted it by adding RewriteCond %{REQUEST_FILENAME} -f
between lines 12 and 13, but the page shows as broken and fails to load resources.
NOTE: I had to remove -Indexes
from line 02 as file requests from JavaScript files would be denied, doing this has also prevented lines 12 and 13 from doing as they were intended, regardless of their placement.
Directory Array [PHP]
$_INCDIRECTORY = 'includes/';
$_PATHINCLUDES = array(
'dashboard' => array(
'allow' => true,
'path' => $_INCDIRECTORY.'dashboard.php',
// The following must remain FALSE; This value will be changed 'on-the-fly';
'exists' => false,
),
'news' => array(
'allow' => true,
'path' => $_INCDIRECTORY.'news.php',
// The following must remain FALSE; This value will be changed 'on-the-fly';
'exists' => false,
),
'search' => array(
'allow' => true,
'path' => $_INCDIRECTORY.'search.php',
// The following must remain FALSE; This value will be changed 'on-the-fly';
'exists' => false,
),
// Excluded/Denied directories;
'css' => array(
'allow' => false,
'path' => 'css/',
// The following must remain FALSE; This value will be changed 'on-the-fly';
'exists' => false,
),
// Error pages;
'403' => array(
'allow' => true,
'path' => $_INCDIRECTORY.'errors/403.php',
// The following must remain FALSE; This value will be changed 'on-the-fly';
'exists' => false,
),
'404' => array(
'allow' => true,
'path' => $_INCDIRECTORY.'errors/404.php',
// The following must remain FALSE; This value will be changed 'on-the-fly';
'exists' => false,
),
);