Mod_Rewrite Security
Here are some specific htaccess examples taken mostly from my WordPress Password Protection plugin, which does alot more than password protection as you will see from the following mod_rewrite examples. These are a few of the mod_rewrite uses that BlogSecurity declared pushed the boundaries of Mod_Rewrite! Some of these snippets are quite exotic and unlike anything you may have seen before, also only for those who understand them as they can kill a website pretty quick.
Directory Protection
Enable the DirectoryIndex Protection, preventing directory index listings and defaulting. [Disable]
Options -Indexes DirectoryIndex index.html index.php /index.php
Password Protect wp-login.php
Requires a valid user/pass to access the login page[401]
<Files wp-login.php> Order Deny,Allow Deny from All Satisfy Any AuthName "Protected By AskApache" AuthUserFile /web/askapache.com/.htpasswda1 AuthType Basic Require valid-user </Files>
Password Protect wp-admin
Requires a valid user/pass to access any non-static (css, js, images) file in this directory.[401]
Options -ExecCGI -Indexes +FollowSymLinks -Includes DirectoryIndex index.php /index.php Order Deny,Allow Deny from All Satisfy Any AuthName "Protected By AskApache" AuthUserFile /web/askapache.com/.htpasswda1 AuthType Basic Require valid-user <FilesMatch "\.(ico|pdf|flv|jpg|jpeg|mp3|mpg|mp4|mov|wav|wmv|png|gif|swf|css|js)$"> Allow from All </FilesMatch> <FilesMatch "(async-upload)\.php$"> <IfModule mod_security.c> SecFilterEngine Off </IfModule> Allow from All </FilesMatch>
Protect wp-content
Denies any Direct request for files ending in .php with a 403 Forbidden.. May break plugins/themes [401]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /wp-content/.*$ [NC] RewriteCond %{REQUEST_FILENAME} !^.+flexible-upload-wp25js.php$ RewriteCond %{REQUEST_FILENAME} ^.+\.(php|html|htm|txt)$ RewriteRule .* - [F,NS,L]
Protect wp-includes
Denies any Direct request for files ending in .php with a 403 Forbidden.. May break plugins/themes [403]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /wp-includes/.*$ [NC] RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ /wp-includes/js/.+/.+\ HTTP/ [NC] RewriteCond %{REQUEST_FILENAME} ^.+\.php$ RewriteRule .* - [F,NS,L]
Common Exploits
Block common exploit requests with 403 Forbidden. These can help alot, may break some plugins. [403]
RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC] RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ ///.*\ HTTP/ [NC,OR] RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\=?(http|ftp|ssl|https):/.*\ HTTP/ [NC,OR] RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\?\?.*\ HTTP/ [NC,OR] RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(asp|ini|dll).*\ HTTP/ [NC,OR] RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*\.(htpasswd|htaccess|aahtpasswd).*\ HTTP/ [NC] RewriteRule .* - [F,NS,L]
Stop Hotlinking
Denies any request for static files (images, css, etc) if referrer is not local site or empty. [403]
RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC] RewriteCond %{HTTP_REFERER} !^https://www.askapache.com.*$ [NC] RewriteRule \.(ico|pdf|flv|jpg|jpeg|mp3|mpg|mp4|mov|wav|wmv|png|gif|swf|css|js)$ - [F,NS,L]
Safe Request Methods
Denies any request not using GET,PROPFIND,POST,OPTIONS,PUT,HEAD[403]
RewriteCond %{REQUEST_METHOD} !^(GET|HEAD|POST|PROPFIND|OPTIONS|PUT)$ [NC] RewriteRule .* - [F,NS,L]
Forbid Proxies
Denies any POST Request using a Proxy Server. Can still access site, but not comment. See Perishable Press [403]
RewriteCond %{REQUEST_METHOD} =POST RewriteCond %{HTTP:VIA}%{HTTP:FORWARDED}%{HTTP:USERAGENT_VIA}%{HTTP:X_FORWARDED_FOR}%{HTTP:PROXY_CONNECTION} !^$ [OR] RewriteCond %{HTTP:XPROXY_CONNECTION}%{HTTP:HTTP_PC_REMOTE_ADDR}%{HTTP:HTTP_CLIENT_IP} !^$ RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC] RewriteRule .* - [F,NS,L]
Real wp-comments-post.php
Denies any POST attempt made to a non-existing wp-comments-post.php[403]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*/wp-comments-post\.php.*\ HTTP/ [NC] RewriteRule .* - [F,NS,L]
HTTP PROTOCOL
Denies any badly formed HTTP PROTOCOL in the request, 0.9, 1.0, and 1.1 only[403]
RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ .+\ HTTP/(0\.9|1\.0|1\.1) [NC] RewriteRule .* - [F,NS,L]
SPECIFY CHARACTERS
Denies any request for a url containing characters other than "a-zA-Z0-9.+/-?=&" - REALLY helps but may break your site depending on your links. [403]
RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC] RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/ [NC] RewriteRule .* - [F,NS,L]
BAD Content Length
Denies any POST request that doesnt have a Content-Length Header[403]
RewriteCond %{REQUEST_METHOD} =POST RewriteCond %{HTTP:Content-Length} ^$ RewriteCond %{REQUEST_URI} !^/(wp-admin/|wp-content/plugins/|wp-includes/).* [NC] RewriteRule .* - [F,NS,L]
BAD Content Type
Denies any POST request with a content type other than application/x-www-form-urlencoded|multipart/form-data[403]
RewriteCond %{REQUEST_METHOD} =POST RewriteCond %{HTTP:Content-Type} !^(application/x-www-form-urlencoded|multipart/form-data.*(boundary.*)?)$ [NC] RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC] RewriteRule .* - [F,NS,L]
Missing HTTP_HOST
Denies requests that dont contain a HTTP HOST Header.[403]
RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC] RewriteCond %{HTTP_HOST} ^$ RewriteRule .* - [F,NS,L]
Bogus Graphics Exploit
Denies obvious exploit using bogus graphics[403]
RewriteCond %{HTTP:Content-Disposition} \.php [NC] RewriteCond %{HTTP:Content-Type} image/.+ [NC] RewriteRule .* - [F,NS,L]
No UserAgent, Not POST
Denies POST requests by blank user-agents. May prevent a small number of visitors from POSTING. [403]
RewriteCond %{REQUEST_METHOD} =POST RewriteCond %{HTTP_USER_AGENT} ^-?$ RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC] RewriteRule .* - [F,NS,L]
No Referer, No Comment
Denies any comment attempt with a blank HTTP_REFERER field, highly indicative of spam. May prevent some visitors from POSTING. [403]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*/wp-comments-post\.php.*\ HTTP/ [NC] RewriteCond %{HTTP_REFERER} ^-?$ RewriteRule .* - [F,NS,L]
Trackback Spam
Denies obvious trackback spam. See Holy Shmoly! [403]
RewriteCond %{REQUEST_METHOD} =POST RewriteCond %{HTTP_USER_AGENT} ^.*(opera|mozilla|firefox|msie|safari).*$ [NC] RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.+/trackback/?\ HTTP/ [NC] RewriteRule .* - [F,NS,L]
Map all URIs except those corresponding to existing files to a handler
RewriteEngine On RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f RewriteRule . /script.php
Map any request to a handler
In the case where all URIs should be sent to the same place (including potentially requests for static content) the method to use depends on the type of the handler. For php scripts, use: For other handlers such as php scripts, use:
RewriteEngine On RewriteCond %{REQUEST_URI} !=/script.php RewriteRule .* /script.php
And for CGI scripts:
ScriptAliasMatch .* /var/www/script.cgi
Map URIs corresponding to existing files to a handler instead
RewriteEngine On RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d [OR] RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f RewriteCond %{REQUEST_URI} !=/script.php RewriteRule .* /script.php
If the existing files you wish to have handled by your script have a common set of file extensions distinct from that of the hander, you can bypass mod_rewrite and use instead mod_actions. Let's say you want all .html and .tpl files to be dealt with by your script:
Action foo-action /script.php AddHandler foo-action html tpl
Deny access if var=val contains the string foo.
RewriteCond %{QUERY_STRING} foo RewriteRule ^/url - [F]
Removing the Query String
RewriteRule ^/url /url?
Adding to the Query String
Keep the existing query string using the Query String Append flag, but add var=val to the end.
RewriteRule ^/url /url?var=val [QSA]
Rewriting For Certain Query Strings
Rewrite URLs like http://askapache.com/url1?var=val to http://askapache.com/url2?var=val but don't rewrite if val isn't present.
RewriteCond %{QUERY_STRING} val RewriteRule ^/url1 /url2
Modifying the Query String
Change any single instance of val in the query string to other_val when accessing /path. Note that %1 and %2 are back-references to the matched part of the regular expression in the previous RewriteCond.
RewriteCond %{QUERY_STRING} ^(.*)val(.*)$ RewriteRule /path /path?%1other_val%2
« Chmod, Umask, Stat, Fileperms, and File PermissionsDNS Round Robin Configuration using Rsync over SSH »
Comments