Excluding one directory in .htaccess (not just rewrite rules) - apache

Excluding one or more directories from rewrite rules in .htaccess files seems to be a common question. However, my .htaccess does more than just set rewrite rules. I've also set some server changes (we don't have suPHP on this server) as well as set some prepending of some php files. For example these are a few examples:
# Make files ending in .php, .html and .xml files etc. parsed by php.
AddType application/x-httpd-php .php .html .xml .css .js .le .txt
<FilesMatch "\.html$">
php_value auto_prepend_file "/home/2427/spwebsites/www.spwebsites.co.uk/incs/phps/config.php"
</FilesMatch>
# Internal Server Error
ErrorDocument 500 /admin/errors.html?code=500
RewriteEngine On
RewriteRule ^([a-zA-Z0-9-]+)/$ $1.html [L]
I don't want any of these set for one directory (where my word press installation is), is there a way I can do this? Can I set a conditional statement for the whole .htaccess file?
Adding a blank .htaccess file in the word press directory won't work because this won't undo the settings in the parent directory.

I was just looking into your dilemma and it is a tricky one. It would be nice to be able to have the DirectoryMatch directive available in .htaccess ...
What you can try is to reset your values in the specific directory via another .htaccess file.
So in the case of the AddType perhaps, resetting it back to just ".php" might work (assuming it doesn't inherit the other values). Definitely not an ideal solution with out access to the main config file/ virtual host.
Here is a weird idea that you can try/test ... place the "wordpress" dir outside of the main root (or whereever you have the offending .htaccess file). Now route all requests to the wordpress (inner dir) to the outer dir. I wonder if Apache would not use the offending .htaccess considering the requests are being routed?

Related

.htaccess fail if X-Header not present for png, gif and jpg's

I'm trying to filter requests for certain web assets (png, gif, jpg, jpeg and mp4 files) based on a specific x-header/value, and fail if not present in the request.
RewriteCond %{HTTP:X-Pull} !secretkey
RewriteRule \.(png|gif|jpg|jpeg|mp4)$ - [F]
It is expected to throw a 403/forbidden error for these file types, if a request does not contain the x-header/secretkey pair, regardless the full path to the file on the website.
I have tried several variations in my .htaccess file, but for *.png, *.gif, *.jpg and *.jpeg files it only works if the files reside in the website's root. However, the same rule works for *.mp4 files, regardless of where they are located (which is how it should work for all the file types in the list).
The site uses mod_pagespeed.
Since Pagespeed is deployed on this server, the .htaccess directives for rewriting the same asset types doesn't work. Here is one way I tried to handle the issue (by updating virtual host configuration file):
<IfModule pagespeed_module>
<If "req('X-Pull') != 'secretkey'">
ModPagespeed off
</If>
<Else>
ModPagespeed on
</Else>
...
</IfModule>
I also moved the rewrites to the virtual host configuration file due to the "significant per-request overhead from processing .htaccess files", as noted in the Pagespeed documentation.

.htaccess rule FilesMatch to all subfolders (subfolders was randomly created)

I tried to find solution here, but I don't. I working with htaccess every day but I have one problem which I can't solve.
I have directory structure:
/cmd/user_files/**[random_folder]**/avatars/pic.jpg
In /cmd/user_files/ I have more folders which randomly created over some app. Under every that randomly created folders I have some files and pictures which I don't want to access from public, and I have one subfolder "avatars" for which I want to show only .jpg
I created .htaccess in /cmd/user_files/ and I added this:
order allow,deny
deny from all
allow from 127.0.0.1
With this I deny access to every file and subfolder under /cmd/user_files/.
Now, what I need to add to this .htaccess that I can show .jpg from
/cmd/user_files/[random_folder]/avatars/*.jpg
Instead of using mod_auth... it may be easier to use mod_rewrite instead. For example, in the /cmd/user_files/.htaccess file:
RewriteEngine On
RewriteRule !^[^/]+/avatars/.*\.jpg$ - [F]
This blocks (403 Forbidden) access to all files/folders except the URL-path that matches the regex ^[^/]+/avatars/.*\.jpg$ (relative to the /cmd/user_files/ subdirectory).
UPDATE: Note the ! prefix on the RewriteRule pattern - this negates the regex. This is an Apache operator, it's not part of the regex itself.
Side note... order allow,deny are Apache 2.2 directives. If you are on Apache 2.4+ then there is a different syntax.

Which ErrorDocument request will take precedence?

I have a domain which contains within it multiple sites with multiple .htaccess files (it's for clients to check their own projects out before they go live to their own servers, so each .htaccess file controls its own site).
If I have a .htaccess file in the root, it will control the domain. If mydomain.com/doesntexist is entered and it doesn't exist, the root's 404 page will come up. If mydomain.com/doesexist/doesntexist is entered, the .htaccess file in the "doesexist" directory would take priority, as opposed to the root's .htaccess file ... correct?
You are correct.
I suggest you to read Apache HTTP Server Tutorial: .htaccess files
The configuration directives found in a .htaccess file are applied to
the directory in which the .htaccess file is found, and to all
subdirectories thereof. However, it is important to also remember that
there may have been .htaccess files in directories higher up.
Directives are applied in the order that they are found. Therefore, a
.htaccess file in a particular directory may override directives found
in .htaccess files found higher up in the directory tree. And those,
in turn, may have overridden directives found yet higher up, or in the
main server configuration file itself.
ROOT htaccess
ErrorDocument 404 /index.php
subfolder htaccess
ErrorDocument 404 /subfolder/index.php
http://domain.com/does_not_exist --> (404 error) /index.php
http://domain.com/subfolder/does_not_exist --> (404 error) /subfolder/index.php

Use .htaccess to whitelist two files for execution

I have a website that has a folder for images.
I have two problems:
I want to disable all script execution in that directory (i.e. no PHP/Perl/Python
anything.)
There are two php files in my images folder called gradient.php and rgba.php – I do what those to run as per usual.
How do I set up my .htaccess file to do that. Also, rather than placing a new .htaccess in the images directory, is it possible to incorporate these directives in the one in the site root?
You can add these rules to the htaccess file in your site root:
# check if the request is for the images folder
RewriteCond %{REQUEST_URI} ^/images/
# check that it isn't a request for an image
RewriteCond %{REQUEST_URI} !\.(jpe?g|png|gif|bmp)$ [NC]
# check that it isn't a request for the 2 ok php files
RewriteCond %{REQUEST_URI} !^/images/(gradient|rgba)\.php$
# forbid access
RewriteRule ^ - [L,F]
This should make it so any request for /images/ that doesn't end with jpg/jpeg/png/gif/bmp (or whatever other extension you want to add to the regular expression) or isn't gradient.php or rgba.php, will result in a 403 forbidden.
EDIT:
I don't want them to be forbidden, I just want them to not execute – it's an upload folder, so I basically want it that if someone uploads a JPG that is secretly PHP code that I haven't detected, that it won't run
as long as jpg and other images are mapped to the correct mime/type (via AddType image/jpeg .jpg) then it won't get handed to the php handler and whatever code is there won't get executed. If you want to serve all files using the default handler, you need to set AddHandler default-handler php in the htaccess file in your images directory. You'll then need to move the gradient and rgba files out to some other directory. You can't selectively set handlers from an htaccess file, though you may be able to use <Location> blocks to set handlers in your vhost config.
EDIT 2:
I was wrong, you can use the H flag to set a custom handler using a rule. So in the above rules, instead of [L,F], you can do [L,H=default-handler] so that anything that isn't an image or gradient.php or rgba.php will get sent to the default-handler (e.g. php files will get sent as-is, and not handled and executed by mod_php).
So you can just do:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/images/(gradient|rgba)\.php$
RewriteRule ^ - [L,H=default-handler]

Set path to php.ini

Is it possible to have just a single php.ini file, for example in the webroot (or even outside of it to prevent people accessing it via GET), and tell PHP quickly and easily where it is?
I know you can set php.ini directives in .htaccess, but is it possible to define a specific php.ini file to be used?
Add this to your server configuration...
<VirtualHost 1.2.3.4:80>
PHPINIDir /path/to/new/php_ini
</VirtualHost>
Make sure to just include the path to the directory, not the entire path to the file.
Then restart Apache.
Check it worked with phpinfo().
Have a look at .user.ini section at the php docs.
Since PHP 5.3.0, PHP includes support for .htaccess-style INI files on
a per-directory basis.
But beside the .unser.ini solution you can place an additional ini file in the "additional .ini files parsed" directory. There you can use one single ini file to overwrite all other settings. Name it with zzz at the beginning and it will be parsed at last. This is also easy for your hoster to deploy without destroying his settings.
Kolink, I suspect that you are on a shared hosting service, in which case your host may be using something called suPHP. In this case -- as you describe -- the PHPINIDir directive doesn't work, in which case there is a suPHP_ConfigPath directive.
In terms of access, I have a standard mod_rewrite in my DOCROOT/.htaccess:
RewriteEngine On
RewriteBase /
# if a forbidden directory or file name (starting with a . or /) then raise 404 Fatal
RewriteRule (^|/)[_.] - [F]
What this does is forbid any request for any filename or directory prefixed by . or _. I have a DOCROOT/_private where I keep this stuff for me:
suPHP_ConfigPath DOCROOT/_private
where you will need to replace DOCROOT by your local setting on your service. Look for DOCUMENT_ROOT in a phpinfo() listing.