Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deny direct access to files or directory using .htaccess

I'm playing with .htaccess and I was wondering if with just an .htaccess inside the root directory is possible to block all the request from a browser directed on existing files or directories.

Let's try this example:

RewriteEngine On

RewriteBase /~my_user/my_base/

RewriteRule ^list/$ list.php [L]
RewriteRule ^element_of_list/([a-zA-Z0-9\-]+)/$ element.php?elem_id=$1 [L]

Now, if I write http://127.0.0.1/~my_user/my_base/list/, this is wroking fine but if I write http://127.0.0.1/~my_user/my_base/list.php it's still working. I don't want that. I want the user to obtain a 404 error in the last case.

We have /etc/apache2/mods-enabled/userdir.conf

<IfModule mod_userdir.c>
        UserDir public_html
        UserDir disabled root

        <Directory /home/*/public_html>
                AllowOverride All
                Options Indexes FollowSymLinks
                <Limit GET POST OPTIONS>
                        Order allow,deny
                        Allow from all
                </Limit>
                <LimitExcept GET POST OPTIONS>
                        Order deny,allow
                        Deny from all
                </LimitExcept>
        </Directory>
</IfModule>

My first try was to use RewriteCond:

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ 404.php [L]

But it's not working. Every request ends up redirected to 404.php

UPDATE

So I've managed to create the filter for directories:

RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !^/~my_user/my_base/$ [NC]
RewriteRule ^(.*)$ 404.php [L]

What it does is to check if the requested path (REQUEST_FILENAME) exists and it's a directory AND if it's not my RewriteBase which is basically index.php, then redirect to 404.php

I'm still trying to find something that does the same thing for files. I know I can selectively do that using extensions filename but I want an universal filter for files.

like image 895
dierre Avatar asked Dec 16 '22 21:12

dierre


2 Answers

If I've understood your requirements correctly, you're looking to do something like this:

# This is a real directory...
RewriteCond %{REQUEST_FILENAME} -f [OR]
# Or it's a real file...
RewriteCond %{REQUEST_FILENAME} -d
# And it's not 404.php...
RewriteCond $0 !=404.php
# And it's not the root
RewriteCond $0 !=""
# And it's not any of the above due to an internal redirect...
RewriteCond %{ENV:REDIRECT_STATUS} ^$
# So cause a 404 response (you could redirect to 404.php if you want)
RewriteRule ^.*$ - [R=404,L]

# Set the 404 error document
ErrorDocument 404 /~my_user/my_base/404.php

Keep in mind that this blocks everything that exists, so any images, stylesheets, or scripts will be sent to the 404 page too. If you just want to block access to the PHP files, Gumbo's solution is more appropriate. I think in that case you'll need another RewriteCond though to prevent looping:

# Make sure the reason this request has a .php is because it was requested
# by the user (and not due to a redirect)
RewriteCond %{THE_REQUEST} ^[A-Z]+\s/[^\s]+\.php
# Make sure we aren't on 404.php already
RewriteRule %{REQUEST_URI} !404\.php$
# We aren't, so redirect to 404.php
RewriteRule ^ 404.php [L]
like image 103
Tim Stone Avatar answered Jan 31 '23 13:01

Tim Stone


Try this rule:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /[^?\ ]*\.php[/?\ ]
RewriteRule .*\.php$ 404.php [L]

This will rewrite all requests whose paths contain a .php internally to 404.php.

like image 45
Gumbo Avatar answered Jan 31 '23 13:01

Gumbo