I'm trying to block all calls to php files in a specific folder and subfolders except for one specific folder and its subfolders.
I've tried a number of different regex permutations and I can get the regex to match properly, it's implementing in htaccess where I have a problem.
This is the htaccess file as it is now:
<FilesMatch "\.(?i:php)$">
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
and this is the regex expression that matches properly outside of htaccess:
^(?!.*(thedirectory)).*(?i:php)$
When I check that regex against index.php it matches. When I check against /thedirectory/index.php it does not match. When I check against /someotherdirectory/style.css it does not match.
How I'd like it to work is:
domain.com/folder/index.php -> 404 Error
domain.com/folder/thedirectory/index.php -> resolves
domain.com/folder/someotherdirectory/index.php -> 404 Error
domain.com/folder/someotherdirectory/afunction.php -> 404 Error
domain.com/folder/someotherdirectory/style.css -> resolves
Turned out to be a lot more straightforward than I thought it would be:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} ^(?!.*(thedirectory)).*(?i:php)$ [NC]
RewriteRule "(.*)" /404.php
</IfModule>
The <Files> and <FilesMatch> sections match just the filename, not the directory path. So attempting to do so will naturally fail.
An alternative approach is to simply create an additional .htaccess file in the directory you want to allow access, which will override the parent:
Require all granted
Related
I have two problems actually:
First, I’m trying to redirect several short URLs to a single page with more actions, like this:
RewriteEngine On
RewriteRule ^/login?$ ^login.php?action=login&next=$1 [L]
RewriteRule ^/reset?$ ^login.php?action=reset&next=$1 [L]
This is being written in the .conf file inside <Directory>. The problem is that the first rule gets executed, while the second doesn’t and I can’t figure why.
I also tried writing them like this:
RewriteCond %{REQUEST_URI} /login$
RewriteRule ^login.php?action=login&next=$1 [L]
RewriteCond %{REQUEST_URI} /reset$
RewriteRule ^login.php?action=reset&next=$1 [L]
I should probably mention that login.php does not reside in the root directory, but in different subdirectories.
What am I doing wrong and how can I fix it?
The second issue I have is that if I put an .htaccess file inside the root directory, the rules in the .conf file don’t get executed anymore.
Inside the .conf file I have these rules:
<Directory>
Options Indexes FollowSymLinks ExecCGI Includes MultiViews
AllowOverride All
Order allow,deny
Allow from all
RewriteEngine On
</Directory>
Why is this and how can I fix it?
Just to extend on from my comments above. Place these rules in your site root .htaccess or in httpd.conf file:
Options -MultiViews
RewriteEngine On
RewriteRule ^/?login(?:/(.*))?$ subdir1/login.php?action=login&next=$1 [L,NC,QSA]
RewriteRule ^/?reset(?:/(.*))?$ subdir1/login.php?action=reset&next=$1 [L,NC,QSA]
Option MultiViews (see http://httpd.apache.org/docs/2.4/content-negotiation.html) is used by Apache's content negotiation module that runs before mod_rewrite and makes Apache server match extensions of files. So if /file is the URL then Apache will serve /file.html.
I want to block HTTP access to every file in my project directory except PHP scripts located in the root folder (not subfolders).
My current .htaccess file looks like this :
# Disable Directory Listings in this Directory and Subdirectories
# This will hide the files from the public unless they know direct URLs
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^api/(.*)$ api.php/$1 [QSA,L]
</IfModule>
# Deny all files from being accessed with Apache
Order Deny,Allow
Deny from all
# Allow specific PHP files at root
<FilesMatch "/(api|cron|status)\.php$">
Order Allow,Deny
Allow from all
</FilesMatch>
This mostly works, except for the URL rewriting on the api.php script. I've tried changing the FilesMatch regexp to /(api|cron|status)(\.php)?$, but it keeps on throwing me a 403 response.
Anyone can explain to me what I did wrong here ? I'm usually OK with regexp, but this has got me thinking Apache doesn't process them like everyone else...
Deny from all
<FilesMatch "^(api|cron|status)\.php$">
Order Allow,Deny
Allow from all
</FilesMatch>
And I guess make sure your .htaccess is on the root level.
desired:
user calls domain.tld/download/file_01.zip
htaccess calls private/download.php
file_01.zip starts to download
Note: file_01.zip must be protected from direct access.
Simplified folder structure:
root/
public/
.htaccess
index.php
private/ <<< this area is blocked from direct access >>>
files/
file_01.zip
file_02.zip
.htaccess
download.php
public/.htaccess
RewriteRule ^download/(.*)?$ ./../private/download.php?file=$1 [NC,L]
private/.htaccess (Edit)
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
download.php
$file = 'files/'.$_GET['file'];
// check: user allowed to download?
// check: more stuff (security, etc.) ...
forceDownload($file);
The RewriteRule works, but I'm getting the error Forbidden: You don't have permission to access [...] on this server, probably because the user calls the request, not the server.
Any idea?
Thanks in advance!
There is one more approach. Rename particular directory (add a single dot before it's current name, .private for example) and place this inside .htaccess file.
RewriteRule (^\.|/\.) - [F]
After adding this rule, each and every file and directory that begins with one . will be forbidden/protected, just like .htaccess it self is. :)
This will prevent access to anyone but PHP to open, view, modify file/dir contents.
Here is sample of (very common I believe) basic .htaccess *(sitting in DOCUMENT_ROOT directory) mod_rewrite rules.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule (^\.|/\.) - [F]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ /$1.php [QSA,L]
</IfModule>
Once that this is being done, You don't serve direct links to .zip or whichever file ext. You have in mind, but do that in some other fashion with favorite PHP 'tricks' of Yours. :)
If You feel that this will give You a lot of code refactoring, just because one directory, You can add those dots to zip files, and move them elsewhere, direct access to dotted files, still won't be possible.
As RiggsFolly stated in their comment.
You need to modify that private/ .htaccess file to something like:
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
Allow from 127.0.0.1 #or your server address/etc
</IfModule>
Here is another solution, giving that your Apache version is >=2.4. (via using Require)
<IfModule !mod_authz_core.c>
Require all granted
Require ip 127.0.0.1
</IfModule>
here is my code in .htaccess
<Directory "/">
AllowOverride All
</Directory>
RewriteEngine on
RewriteRule ^custom contactus.php[NC L]
Remote site path or my all website files contains in /www
current url : example.com/contactus.php
expected output url: example.com/custom
Try the following rule.
RewriteEngine On
RewriteRule ^custom$ /contactus.php [L]
Invalid htaccess file
A Directory directive is invalid in a .htaccess file:
Description: Enclose a group of directives that apply only to the
named file-system directory, sub-directories, and their contents
Context: server config, virtual host
Note that .htaccess is not a valid context. Similarly, AllowOverride is also invalid in a .htaccess file:
Description: Types of directives that are allowed in .htaccess files
Context: directory
Were it valid in a .htaccess file, it would defeat the purpose of what the directive is for.
Valid example
The entire contents of the .htaccess file to do what's in the question are:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^custom contactus.php [NC,L]
</IfModule>
I.e. If mod rewrite is enabled, apply that rewrite rule. Note that the syntax for rewrite flags is a comma separated list.
I have nearly 30 php files, 4 sub directories in my directory. I want to block some php files and sub directories from user in direct viewing like http://bhavani.com/hai.php
My currect htaccess file
## Enable Mod Rewrite, this is only required once in each .htaccess file
RewriteEngine On
RewriteBase /
## Test for access to includes directory
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /includes/ .*$ [NC]
## Test that file requested has php extension
RewriteCond %{REQUEST_FILENAME} ^.+\.php$
## Forbid Access
RewriteRule .* - [F,NS,L]
How to do it?
You can filter the files like this
<Files ~ "\.php$">
Deny from all
</Files>
And directory like this
<Directory "/subdirectory">
Deny from all
</Directory>
You don't need mod_rewrite to accomplish this. A much simpler way of doing this would be with RedirectMatch directive from mod_alias:
RedirectMatch 403 ^.*/include/*\.php$
This will automatically respond with 403 Forbidden to a direct request for any PHP file inside include subdirectory, however you would still be able to include them from inside other php files.
I think you can use only RewriteRule without RewriteCond
For example:
RewriteRule ^/hai\.php - [F, NS, L]
This rule forbid access to file hai.php
For other files you can use other Rule or use mask.