htaccess to block file but not dir - .htaccess

I have an htaccess problem with it blocking my directory because of the filesmatch flag.
I'm trying to block log files, but on my site also maintain a blog.
What happens is that if people come to site.com/blog they get a 403 error vs site.com/blog/ works just fine. Also some other functions within the blog fail as well because of this error.
I guess i'm not sure if the filesmatch is correct/working properly or how to fix this. htaccess files have never been my friend :p
Options +SymLinksIfOwnerMatch
# Prevent Directoy listing
Options -Indexes
# Prevent Direct Access to files
<FilesMatch ".(tpl|log|ini)">
Order allow,deny
Deny from all
</FilesMatch>
# SEO URL Settings
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^site.com [NC]
RewriteRule ^(.*)$ http://www.site.com/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]

You need to escape your . in the <FilesMatch> container. It expects a regular expression and the . character means "any character that isn't a newline".
<FilesMatch "\.(tpl|log|ini)">
Order allow,deny
Deny from all
</FilesMatch>

Related

Htaccess, go through files until exists?

I have this .htaccess file:
Options +FollowSymLinks
Options -Indexes
RewriteEngine On
RewriteEngine On
RewriteRule \.(png|jpg|gif|jpeg|bmp|ico|flv|mpeg|mp4|mp3|swf|exe|WAgame|wsc|eot|svg|ttf|woff|woff2|rar|wav)$ - []
RewriteRule ^ entryPoint3.php
RewriteRule ^ entryPoint2.php
RewriteRule ^ entryPoint.php
RewriteRule ^robots\.txt$ http://www.example.com [R,NE,L]
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST} [L,R=301]
<Files .htaccess>
Order Allow,Deny
Deny from All
</Files>
If the entryPoint3.php exists, load it, otherwise load entryPoint2.php otherwise entryPoint.php. How to achieve this?
Have it this way:
Options +FollowSymLinks -Indexes
RewriteEngine On
RewriteRule \.(png|jpg|gif|jpeg|bmp|ico|flv|mpeg|mp4|mp3|swf|exe|WAgame|wsc|eot|svg|ttf|woff|woff2|rar|wav)$ - [L]
RewriteRule ^robots\.txt$ / [R,NC,L]
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
# if entryPoint3 exists then use it
RewriteCond %{DOCUMENT_ROOT}/entryPoint3.php -f
RewriteRule ^ entryPoint3.php [L]
# if entryPoint2 exists then use it
RewriteCond %{DOCUMENT_ROOT}/entryPoint2.php -f
RewriteRule ^ entryPoint2.php [L]
# if entryPoint exists then use it
RewriteCond %{DOCUMENT_ROOT}/entryPoint.php -f
RewriteRule ^ entryPoint.php [L]
<Files .htaccess>
Order Allow,Deny
Deny from All
</Files>
I solved it like that: DirectoryIndex entryPoint3.php entryPoint2.php entryPoint.php what's the difference?
...but remember it will try to open entryPoint files in every directory not just in site root
You can specify root-relative URL-paths as arguments to the DirectoryIndex directive, they do not need to be relative, as you have here. For example:
DirectoryIndex /entryPoint3.php /entryPoint2.php /entryPoint.php
This will search for files in the document root only, regardless of which directory is requested.
But also, this is quite different to #anubhava's solution using mod_rewrite (and similar to what you were attempting in the question). With DirectoryIndex, the necessary file will only be served if you are requesting a directory (which includes the document root, ie. https://example.com/). eg. example.com/ and example.com/directory/ will trigger the relevant entryPoint file, but example.com/something will not.
However, with the mod_rewrite solution as stated, the relevant entryPoint file is served for "any" requested URL (except for the few URL-extension exceptions as stated). eg. example.com/, example.com/something, example.com/file.php and example.com/directory/ will all trigger the relevant entryPoint file.
For the mod_rewrite solution to work the same way as DirectoryIndex you will need an additional condition that explicitly checks that the request maps to a directory (including the trailing slash). For example:
# When requesting a directing... if entryPoint3 exists (in the root) then use it
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}/entryPoint3.php -f
RewriteRule ^(.+/)?$ entryPoint3.php [L]
:
The RewriteRule pattern simply checks that the requested URL ends with a slash (or is the document root) - the same behaviour as DirectoryIndex. (If you request a directory without a trailing slash then mod_dir appends it with a 301 redirect.)
So the solution you choose really depends on your requirements. However, if DirectoryIndex is working for you then I assume you are only requesting filesystem directories, so DirectoryIndex would be the way to go.

.htaccess specific url changes

I've a small, but hard to understand problem with .htaccess in CMS system.
I've mod expires, that cache stuff on whole website, but I don't want to cache stuff in /admin URL, I can't make another .htacess, couse I've MVC structure and no real directory that could hold all my admin stuff.
I've found directive, but it only works in server configuration and I want it to work on different hostings, so only in htaccess file.
EDIT- Rewrite
# Turn on URL rewriting
RewriteEngine On
# Installation directory
RewriteBase /
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteCond %{HTTP_HOST} ![0-9]$ [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [L,R=301]
# Protect hidden files from being viewed
<Files .*>
Order Deny,Allow
Deny From All
</Files>
# Protect application and system files from being viewed
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php/$0 [PT]
You can apply your Expires directive using a <if> directive with an expression to match against /admin:
<If "%{REQUEST_URI} =~ /^\/admin\//">
# Your expiry directives
</If>
If you know the exact URL then you can try this pattern.
RewriteRule ^facebook/get/(.*)?$ http://$1 [NC,R]
RewriteRule ^wrapper/share/(.*)?$ http://example.com/wrapper/share/$1 [NC,R]
This will check for URL where <-any-value->facebook/get/<-any-value2-> and then will send to the <-any-value2->
Like
RewriteRule ^stats/(.*)$ admin/dashboard.php?mode=openstats&event_id=$1 [NC,L,QSA]
**If URL has stats/<--any-value--> then it will redirect/open admin/dashboard.php **
If your URLs doesn't have exact value but you do know the URL slot pattern then you can try this.
RewriteRule ^([^/.]+)/([a-zA-Z0-9_-]+)/$ wrapper/index.php?id=$2 [NC,L,QSA]

Only ignore htaccess rule if file and filetype exists

I've done some code so that the url gets passed to the index page and the index page then decides which page to load in. Initially it would redirect unless a file or directory existed, which was fine for most cases, but things like the php files I wanted to keep private, as they should only be referenced by index.php, and not actually called themselves.
With a bit of help, I managed to switch it so that it would redirect everything, aside from certain extensions, such as images and css files. I've only just noticed it'll still attempt work on files that don't exist, and come up with the default 404 page, but I'd prefer it to be passed to my code like all the other pages.
How would I merge these two rules, so that the redirect will only not happen if both the file exists, and its extension is allowed?
1. RewriteCond %{REQUEST_FILENAME} !-f
2. RewriteCond %{REQUEST_URI} !\.(?:jpe?g|gif|txt|php|bmp|png|ico|tiff|css|js)$
Here were the old rules (specific to the redirecting):
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?_page_location=$1 [L,NC,NE]
And here is it as it currently stands:
Options -Indexes
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L,NC]
# Add trailing slash to directories
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=301,NE]
# If the request is not for known file types
RewriteCond %{REQUEST_URI} !\.(?:jpe?g|gif|txt|php|bmp|png|ico|tiff|css|js)$
RewriteRule .* index.php?_page_location=$0 [L,QSA]
<FilesMatch "^(.*)\.php$">
Order Deny,Allow
Deny from all
</FilesMatch>
<FilesMatch "index\.php|info\.php">
Order allow,deny
Allow from all
</FilesMatch>

htaccess rewriterule ignore index.html

I'm using CodeIgniter and .htaccess to rewrite the URLs but I want it to ignore index.html.
This is so we can upload an index.html at any time as this will be a temporary landing page. With a link through to the main site on the index.php.
This is what is currently in .htaccess and I have set the server's directory index to index.html index.php
RewriteEngine on
RewriteCond $1 !^(index\.html|index\.php|js|img|fonts|data|css|uploaded|mobile_devices|audioplayer|emails|robots\.txt|archive_blog)
RewriteRule ^(.*)$ /index.php/$1 [L]
Thanks for any help
that rather looks like you want to rewrite everything that does not really exist in your directory.
try this instead of your current RewriteCond:
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1
Instead of using RewriteCond to ignore the index.html file, you could instead restrict access to it directly through using the FilesMatch directive. FilesMatch accepts a regular expression which could filter based on file name (e.g., index.html) or any regular expression.
Blocking access to the index.html file
<FilesMatch "index\.html$">
Order allow,deny
</FilesMatch>
That would completely deny access to the index.html file. I will admit, that I do not know the negative effects this would have on search engine crawling.
To read more about the FilesMatch Directive see http://httpd.apache.org/docs/current/mod/core.html#filesmatch
As for the rest of the directories in that list you currently have, you could just lock down all directory access regardless of name. It would give you a little more coverage going forward.
Options -Indexes
To read more about the Options Directive see http://httpd.apache.org/docs/current/mod/core.html#options
In the end your new .htaccess file would look something like this:
# Protect specific files from access
<FilesMatch "index\.html$">
Order allow,deny
</FilesMatch>
# Hide directory listing for URL's mapping to a directory
Options -Indexes
# Follow all symbolic links in this directory
Options +FollowSymLinks
# General rewrite rules
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
</IfModule>
Why don't you use the built in environment function?
You could create a 'maintenance' environment and set the base controller to whatever you want. Then you would just need to edit the index.php file to specify the environment you want.

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.
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]
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.

Resources