Edit HTACCESS file to prevent direct access to a particular file within a particular folder

1.1k views Asked by At

I am trying to prevent direct access to a particular file within a sub-folder.

I realize that there are MANY topics depicting similar issues here on this forum. But, mine seems to be a bit awkward........due to my already existing HTACCESS file.

Here is the file-path to the file :

www.example.com/PRINCIPAL/PROJECTS/my_file.php

(my_file.php is the file I want to restrict from direct access)

What I mean is : my_file.php is current accessible only if the user navigates through a particulae sequence of events within my website (such as : select radio-button here........click another button there, etc, etc)

I want it to stay that way.

Unfortunately, if the user attempts to access the file directly, by typing in the URL in his browser, he can also access my_file.php

Which is what I do not want.

The reason I say my situation is rather awkward is because : normally, this is an easy thing to fix :

(a) include a rule in the HTACCESS file which would prevent direct access to the file itself (b) place the file in a separate folder, and then simply use DENY ALL in the htaccess file (c) place the file in a separate folder, and then create an EMPTY INDEX file, right next to it

And so on, and so forth

The reason why none of these would work for me is ---- as I mentioned above ---- due to my current HTACCESS file. It already contains two rules :

(a) a rule to remove all PHP file extensions (b) a rule to hide the sub-folder "PROJECTS" from view (in the browser bar)

Here is my current HTACCESS file :

 Options -Indexes
 Options -MultiViews
 Options +FollowSymlinks

 <IfModule mod_rewrite.c>

 RewriteEngine On

 RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/?([^/]+)/([^/]+)/([^.]+)\.php [NC]
 RewriteRule ^ /%1/%3 [R=301,L]

 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule ^([^/]+)/([^/]+)/?$ $1/PROJECTS/$2.php [NC,L]

 </IfModule>

So, as I mentioned earlier, this is the path to my_file.php :

www.example.com/PRINCIPAL/PROJECTS/my_file.php

With those two rules in my HTACCESS file, the actual file-path becomes :

www.example.com/PRINCIPAL/my_file

Because of this, those 3 solutions I listed above ---- A, B, and C --- would not work for me.

I cannot find anything online which addresses my particular problem. I am still new to this, but I am guessing that I would need to :

(a) somehow modify my current HTACCESS file (b) create a new and separate HTACCESS file, and place it in a separate folder, together with my_file.php

Any help here would be greatly appreciated

Thanks

UPDATE

I should have mentioned : "my_file.php" opens in a new window (child-window). I already to solve the issue by using $_SESSION variables to check whether or not the user made a particular necessary selection. Unfortunately, it did not work. When I checked the error-logs, I saw this message : UNDEFINED INDEX XXXXX.

Apparently, when the child-window is opened, the session variable is not carried forward (which is weird)

UPDATE

Here is the code from the parent-page :

  if(isset($_POST['submit'])  {

  $_SESSION['response'] = $_POST['selection'];

(The user must select a radio button, to proceed further).

Then, at the top of the child-window, I have this code :

if (!(isset($_SESSION['login']) && $_SESSION['login'] != '') ||    
   (isset($_SESSION['login']) && !(isset($_SESSION['response']))

{

header ("Location: /PROJECTS/access_denied");

The first part checks to make sure that the user is LOGGED IN.

The second checks to make sure that the radio-button was indeed selected on the previous page.

UPDATE

Once again, something I should have mentioned : (my head is just all over the place now). The child-window is a questionnaire program; it asks a series of questions, one at a time. Each time a new question is asked, the window refreshes. And it is the SAME php file (my_file.php). It refreshes each time, but displays a new question, depending on what the user selects on each preceeding page.

For this reason, the $_SESSION "check" needs to be valid, each time the child window refreshes.

If I UN-SET the session at the beginning of the first child-window, the next question will display the "Access_Denied" page !

And, you may ask : why bother to open this questionnaire program in a child window? Well, amongst other reasons, I disabled "Back button" and "Page Refresh" on this child-window, because it is important that the user not refresh this window once the questionnaire has begun.

EDIT

As a last resort, I suppose I could simply HIDE the file-name (my_file) from the URL address bar, so that the user does not know the name of the file, and therefore, will not know to actually look for it.

I tried changing the filename to "index.php", but this still shows in the address bar.

I have tried many ways to hide the file-name, but nothing seems to work

2

There are 2 answers

0
Blackson On

You can re-write the filename for example

RewriteRule    ^thenameyouwant$     my_file.php             [L]     # Handle page rewrite URL
10
ahuemmer On

IMHO, allowing to access the PHP file only if the user goes a specific way to get there is not the right approach. A file on a web server should always be publicly accessible or not (and not sometimes yes, sometimes no).

My suggestion would be to collect information about the way the user took. You could, for example, store these data in the session and then analyze it, when your my_file.php is called. If you should observe, that the user has taken the "right" way up to now, you can execute your script as usual. If not, you should display an error message, or - if you want to - tell him, that he has no access.

Assuming you want to use a session for that purpose, you could place the following code on top of your my_file.php:

session_start();
if (!isset($_SESSION['login']) || ($_SESSION['login'] == '') || 
    !isset($_SESSION['response']))
{
    header ("Location: /PROJECTS/access_denied");
    exit;
}

//Process the request, as the user is now confirmed to be allowed to use this page

//In the end, possibly:
unset($_SESSION['response']);
//Now the user won't be able to use this page again until he "took the right way" again.

In your parent page, you would then use:

session_start();  
if(isset($_POST['submit'])  {
    $_SESSION['response'] = filter_input(INPUT_POST,'selection');
    //...
}

// I assume, that $_SESSION['login'] is set somewhere else.

This is just a very basic example. I think the key is gathering the information about how the user accessed your script.

When not using sessions, one might think about checking $_SERVER['HTTP_REFERER'] to check where the user came from, but then you should keep in mind, that many users don't send this information because of privacy considerations and even more, that the referer can be set to an arbitrary value by a client, so this is definitely not the right way.

Edit: Inserted code for using the session as in your example. Did you remember to call session_start() on both the pages? I think the if statement at the beginning was messed up a little, so I tried to make at more simple. :) Also, I used filter_input as a very basic security enhancement when reading the POST variable.