FREE THOUGHT · FREE SOFTWARE · FREE WORLD

Home  »  Htaccess  »  Mod_Security .htaccess tricks

by 13 comments

.With over 70% of all attacks now carried out over the web application level, organizations need as much help as they can get in making their systems secure. WAFs are deployed to establish an external security layer that increases security, detects, and prevents attacks before they reach web applications.

Target Audience:

  • Web Server Administrators
  • Web security Adminis
  • Security consultants and other ballers.
  • Web Developers

Laying the smack down on attacks

mod_Security sits in front of ApacheModSecurity is an Apache Module just like mod_rewrite that is in fact a Web Application Firewall, providing access to every tiny bit of a HTTP Connection. HTTP Headers, Cookie and Post Payloads in their entirety, XML-RPC calls from Ajax, protocol and connection information, etc... its totally stacked.

Mod_Security uses Regex and .htaccess / httpd.conf directives similar to mod_rewrite, allowing for complete control from within .htaccess files and httpd.conf blocks.

mod_security + mod_rewrite

mod_security is the missing piece if all you know is mod_rewrite. This gives you the ability to scan ALL messages received by your website, including POST, Trackbacks, Pings, Ajax XMLHTTP calls, etc. It lets you create your own rules so that you can stop spam and prevent web application, protocol, and server attacks.

Mod_Security has the ability to parse entire POST_PAYLOADS, specific and individual POST/GET arguments... This is a spammers worst nightmare, and I'm going to make that nightmare reality for them.

Block Spam by examining POST form fields

mod_security gives you the option to block, redirect, handle using an errordocument, PAUSE, close, and chain connections. If someone is spamming your blog from many different IP's, but they often use the same keywords in a certain field of your form (like .blackjack. in the url field) mod_security lets you examine that specific url field and block all connections that contain the regexp pattern of your choice.

Enable mod_security - DreamHost

To enable mod_security, login to the DreamHost panel and navigate to the "Manage Domains" area, Edit your site and enable the extra security option.

Mod_Security Step 2

DreamHost, has set itself apart as being the top web host IMHO. They've provided the option to enable an Apache module called mod_security for any of your hosted domains. The sysops and tech over there are really doing a great job of staying true to the industry, they are web hosts, not some corporate outsourced bought-out thing. Anyways thanks DH!

Disabling mod_security conditionally per IP

This will make sure that you aren't processed by mod_security, but this only works if you have a static IP (Get your IP information). Just add this towards the top of your .htaccess file. before your mod_security code. Setting this variable causes the module to be disabled for this specific IP address, this means you won't run into any problems while posting yourself..

SetEnvIfNoCase Remote_Addr ^208.113.183.103$ MODSEC_ENABLE=Off
 
# You can use multiple SetEnvIf directives to control it further.
# This only turns it off for your IP + a POST request method.
#
# SetEnvIf Remote_Addr ^208.113.183.103$ MODSEC_ENABLE=Off
# SetEnvIf Request_Method !^POST$ MODSEC_ENABLE=On

Disabling mod_security with .htaccess Authorization

So I did some experimenting to see if there was an alternative way to disable mod_security for the users out there without a static IP address. I found a couple silly solutions that suggested you simply modify your browsers User Agent request header, but thats not very safe is it? No. So I came up with using Basic Authorization.

First you need to setup password protection for the directory that you want mod_security disabled for. In the case of WordPress blogs, you can use the AskApache Password Protect Plugin to get setup. Or you can generate a new htpasswd.

Adding password protection for mod_security bypass

AuthName "htaccess password prompt"
AuthType Basic
AuthUserFile /fullpath-to/.htpasswd
Require valid-user

Magic Authorization shut-off using .htaccess

When you login using this authentication, the environment variables REMOTE_USER and AUTH_TYPE are set (though its hard to find them). Since these are unique to you specifically and hard to spoof, use them to turn off mod_security only after you login. This is added up at the top of your mod_security rules.

SecFilterSelective REMOTE_USER "^yourusername$" "allow"
 
# More variables you can experiment with
# HTTP_Authorization|AUTH_TYPE
#
# You may have to add this to your mod_rewrite code
#RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]

MOD_SECURITY config for DreamHost

Custom mod_security .htaccess code

Heres how I start my mod_security code, keep in mind I have a lot to learn.

### ASKAPACHE MOD_SECURITY ###
# Turn the filtering engine On or Off or DynamicOnly for cgi/php/etc
SecFilterEngine On
 
# Only log suspicious requests
SecAuditEngine RelevantOnly
 
# Goes up to 9 but at 2 its overwhelming trust me
SecFilterDebugLevel 0
 
# Make sure that URL encoding is valid
SecFilterCheckURLEncoding On
 
# Unicode encoding check
SecFilterCheckUnicodeEncoding Off
 
# Should mod_security inspect POST payloads
SecFilterScanPOST On
 
# The default rule to apply to inherited rules
SecFilterDefaultAction "deny,log,status:500"

Minimal httpd.conf or .htaccess sample from source

 
# Enable ModSecurity
SecFilterEngine On
 
# Reject requests with status 403
SecFilterDefaultAction "deny,log,status:403"
 
# Some sane defaults
SecFilterScanPOST On
SecFilterCheckURLEncoding On
SecFilterCheckUnicodeEncoding Off
 
# Accept almost all byte values
SecFilterForceByteRange 1 255
 
# Server masking is optional
# SecServerSignature "Microsoft-IIS/5.0"
 
# Designate a directory for temporary files
# storage. It is a good idea to change the
# value below to a private directory, just as
# an additional measure against race conditions
SecUploadDir /tmp
SecUploadKeepFiles Off
 
# Only record the interesting stuff
SecAuditEngine RelevantOnly
# Uncomment below to record responses with unusual statuses
# SecAuditLogRelevantStatus ^5
SecAuditLog logs/modsec_audit.log
 
# You normally won't need debug logging
SecFilterDebugLevel 0
SecFilterDebugLog logs/modsec_debug.log
 
# Only accept request encodings we know how to handle
# we exclude GET requests from this because some (automated)
# clients supply "text/html" as Content-Type
SecFilterSelective REQUEST_METHOD "!^(GET|HEAD)$" chain
SecFilterSelective HTTP_Content-Type "!(^application/x-www-form-urlencoded$|^multipart/form-data;)"
 
# Do not accept GET or HEAD requests with bodies
SecFilterSelective REQUEST_METHOD "^(GET|HEAD)$" chain
SecFilterSelective HTTP_Content-Length "!^$"
 
# Require Content-Length to be provided with
# every POST request
SecFilterSelective REQUEST_METHOD "^POST$" chain
SecFilterSelective HTTP_Content-Length "^$"
 
# Don't accept transfer encodings we know we don't handle
SecFilterSelective HTTP_Transfer-Encoding "!^$"

Block WordPress Spam Forever!

Ok this is my first attempt at this, and I am really excited about the possibilities! This example goes inside your mod_security block towards the bottom, and it sets up a default action for each of the filters below it. This denies the connection, doesn't log it, and issues a 403 Forbidden Status code, which causes my Apache ErrorDocument to be displayed. This ErrorDocument can be a blank page to minimize bandwidth, or it can be a cgi perl type of script that send you an email, whatever. Many people use different Status Codes for different situations, some like 400, 412, 406, and 410 for spammers. Others prefer 503. You can see all 57 that are available for anyone running Apache and choose your own.

block-spam.txt

  • The FilesMatch Directive specifies that these rules only apply to these files.
  • The ARG_url line says that if those words appear in the form field with the id/name of "url", than deny them.
  • The ARG_comment_post_ID line denies requests that have an empty comment_post_ID field, which a surprisingly large number of spammers forget to add.
  • The final multi-line section searches ALL get and post items for any of these keywords.

Force Any Connections to be Paused a set number of ms

This is just an example to show you how cool this module is, you really shouldn't every do this except for very specific instances, because it will end up consuming your servers resources and making a ddos attack more likely. This example forces anyone who doesn't come from the askapache.com site to have their connection delayed 5000 ms, then processing continues.

SecFilterSelective "HTTP_REFERER" "askapache.com" log,pass,pause:5000

Only Allow Certain REQUEST_METHODS

I've created a free online scanner that you can use to scan your site and see how it handles all 27 REQUEST_METHODS.

# Sends matching requests a 405 Method Not Allowed Status Code
SecFilterSelective REQUEST_METHOD "!^(GET|HEAD|POST|OPTIONS)$" "deny,auditlog,status:405"

Debugging and Logging

First its my best guess that DreamHost is running ModSecurity v1.9.4 so its pretty darn difficult to find information about this modules directives and how to use it. So debugging through the use of trial and error and logging is the best or only way to figure it out.

On DreamHost we lucked out

If you have already been using DreamHosts "extra security" option and use your shell or check your error logs, you will have seen plenty of verbose messages about something or other being blocked. Thats mod_security doing its thing but it takes up resources on everyones servers and makes your error log close to unusable.

Control mod_security logging to your error log

Each filter can have its own actions, so turn logging on (log, auditlog) only for those you want, turn off (nolog, noauditlog) for anything else.

# Not logged
SecFilterDefaultAction "deny,nolog,noauditlog,status:500"
 
# Logged but not as verbose.
SecFilterDefaultAction "deny,nolog,auditlog,status:500"
log
Indicates that a successful match of the rule needs to be logged.
noauditlog
Indicates that a successful match of the rule should not be used as criteria whether the transaction should be logged to the audit log.
nolog
Prevents rule matches from appearing in both the error and audit logs.

Turn Off/On Logging JUST for your IP Address

This is handy when you want to test your rules.

# Turn logging of for your IP
SecFilterSelective REMOTE_ADDR "208.113.183.103" "nolog,noauditlog,pass"
 
# Turn logging on just for your IP
SecFilterSelective REMOTE_ADDR "!^208.113.183.103" "nolog,noauditlog,pass"
SecFilterSelective REMOTE_ADDR "208.113.183.103" "log,auditlog,pass"

Mod_Security Directives for DreamHost

SecFilter
The filtering expression
SecFilterDebugLog
The filename of the filter debugging log file
SecFilterDebugLevel
The level of the debugging log file verbosity
SecFilterSelective
The variable representing areas where filtering is wanted, the filtering regular expression and optional action to take on match
SecFilterEngine
On, Off, or DynamicOnly to determine when will request be filtered
SecServerResponseToken
On or Off to set whether the mod_security token will appear in the server signature
SecFilterScanPOST
On or Off to set whether a request body will be processed
SecFilterDefaultAction
The default action to take on rule match
SecFilterSignatureAction
Base action template for signatures that follow this directive
SecFilterInheritance
On or Off to set whether rules from the parent context will be inherited
SecAuditEngine
On, Off, RelevantOnly or DynamicOrRelevent to determine the level of audit logging
SecAuditLog
The filename of the audit log file
SecUploadDir
The path to the directory where uploaded files should be stored
SecUploadKeepFiles
On or Off to choose whether to keep the uploaded files or not
SecUploadApproveScript
The path to the script that will be called to approve every uploaded file
SecFilterCheckURLEncoding
On or Off to set whether URL encoding validation will be performed
SecFilterCheckUnicodeEncoding
On or Off to set whether Unicode encoding validation will be performed
SecFilterForceByteRange
The first and the last byte value of the range that will be accepted
SecChrootDir
The path of the directory to which server will be chrooted
SecChrootLock
The filename of the lock file used during the chroot process, defaults to "logs/modsec_chroot.lock"
SecServerSignature
The new signature of the server
SecFilterNormalizeCookies
On or Off to determine whether cookie values will be normalized for testing, defaults to On
SecFilterCheckCookieFormat
On or Off to determine whether cookie format will be checked. Defaults to On
SecFilterCookieFormat
version of the Cookie specification to use for parsing. Possible values are 0 and 1.
SecCharset
Configures the charset
SecFilterImport
imports a rule from the parent configuration context.
SecFilterRemove
removes a rule that was inherited from the parent configuration context.
SecFilterInheritanceMandatory
when this directive is set to On then the rules in the parent context cannot be removed from a child context.
SecAuditLogType
whether to use the old audit log format (Serial) or new (Concurrent)
SecAuditLogStorageDir
path to the audit log storage area; absolute, or relative to the root of the server
SecAuditLogParts
list of audit log parts that go into the log.
SecAuditLogRelevantStatus
regular expression that will be used to determine if the response status is relevant for audit logging
SecFilterActionsRestricted
whether to allow rules to override SecFiltersDefaultAction configuration

Just remember each version is different, I think most of the directives in the above list are allowed on DreamHosts install, but I'm not 100%, I'm sure they'll be upgrading soon anyway.

How I got Started with mod_sec

Subject: mod_security denying blog post

Is there any way you could modify the mod_security rules for me? For the past 2-4 months I have been having a problem on WordPress where I go to edit a post and when I hit submit and POST the changes it gives me a 503 Message, which is odd to use a 503 Service Temporarily Unavailable, that threw me off for at a month thinking the service was unavailable.

Basically this only happens to about 5 of my posts, and almost all of them have something to do with php code, or some other type of programming language. An example is when I try to edit custom-phpini-tips-and-tricks. So what I've had to do is go into phpmyadmin and manually edit the database.. I don't want to turn off the mod_security for my site because I am getting hit all the time by malicious looking bots, is that the only way around this? I have no clue, but if it helps that IP 64.233.167.99 is static for me, and this problem only occurs when posting to the /wp-admin/post.php file.

Reply from DreamHost Support
Unfortunately, the mod_security rules need to be changed on all machines and Apache instances if they are changed on just one as our admins like to keep the servers in sync. So getting mod_security modified isn't really something that can be done easily. I'll put in a suggestion as we do host a lot of WordPress blogs, but I can't guarantee that we'll be able to do it very quickly.I know you don't want to turn mod_security off, but honestly it's your best bet if you want to be able to post without 503's right now. If "64.233.167.99" is always your IP, might I suggest setting up an .htaccess rule in your wp-admin folder to deny all traffic to that folder except for your IP address? I know that doesn't work if you're on the road - although adding IPs to allow to an .htaccess file is pretty easy to do - but it will keep the malicious folks out.

Example httpd.conf mod_security rules


Reprint: The old modsecurity malware-blacklist-high.txt file contained on this site used to list ThankfulPraise.com as a malware site, this site is not a malware site.


Some of the attacks this Apache module has the ability to smack with its unique positioning within Apache HTTP.

  1. HTTP protection - detecting violations of the HTTP protocol and a locally defined usage policy
    • SQL Injection
    • Cross-Site Scripting (XSS)
    • OS Command execution
    • Remote code inclusion
    • LDAP Injection
    • SSI Injection
    • Information leak
    • Buffer overflows
    • File disclosure
  2. Common Web Attacks Protection - detecting common web application security attack
  3. Automation detection - Detecting bots, crawlers, scanners and other surface malicious activity
  4. Trojan Protection - Detecting access to Trojans horses
  5. Errors Hiding - Disguising error messages sent by the server

mod_security links

  1. DreamHost Version 1.9.5 Manual
  2. Reference of Actions, Commands, etc. - Official Site
  3. version 1.9 got_root rules
  4. mod-security-users - mailing list
  5. mod_security online rules generator - Noel Jackson
  6. An Intro to mod_security - Atomic Playboy
  7. Get mod_sec training

MOD_SECURITY: The Most Powerful Server-Side Security Technology I've Seen


htaccess Guide Sections

Tags

April 23rd, 2008

Comments Welcome

  • Eric

    How does one disable mod_security for one particular file? i.e. a flash file?

  • AskApache

    @ Eric

    You can disable mod_security for a single file by using the FilesMatch directive and disabling the MODSEC_ENABLED variable. Or unset it with SetEnvIf.

    Of course, mod_security's own SecFilterSelective would work quite well when pared with the Request_Uri.

  • Nizzy

    A challenging .htaccess question!

    How to create a random string by .htaccess? This is what I want to accomplish, any idea?

    http://site.com -> redirects to -> http://site.com/.xyz123/
  • DH TS

    I work in Dreamhost`s Tech Support, and I came across this page while researching a ticket. You are now bookmarked my friend. Awesome stuff!

  • AskApache

    Thank you anonymous DreamHost support staff. Maybe you could help me get my affiliate account unbanned? Did I mention I tell everyone how incredibly fast and helpful the DreamHost Support Staff are?

  • Win/32 banning ips

    Hi guys , Gals I enabled the auth-z module and I still can't ban ips with the order deny function in the .htaccess file any suggesttions?

    I go to restart the server after .htaccess file has been modified and it crashes but then loads when I remove it.

  • Jehzeel Laurente

    Thank you so much for sharing this. However, I still can't disable mod_security. :( I also contacted the host and they seem to have no idea how to disable it. Weird. I still can't in my WP post with the words: WHERE, SELECT, JOIN and FROM. :(

  • Pradyumna Dandwate

    Does this apply to mod_security version 2.1 as well. I had tried putting the Off filter but it didn't work. Drupal sucks a big time and my IP gets banned on my website everyday. can you help? The webhost guys won't disable mod_security from their end. Is there any way to deal with this situation?

  • mistaecko

    Starting from mod security version 2 htaccess files cannot be used to configure mod_security any more. It seems this decision was made out of security concerns - it allowed weakening / circumventing security rules defined higher up in the directory hierarchy and on server level.

  • Aziz

    Nice write up, a bit optimistic for non-cms like platforms, but nevertheless informative. I've been in the trenches with mod_security and WordPress for the past week or so. Let me tell you that after debugging mod_security at level 5, you start dreaming in code. In any case I had to disable a lot of rules just to be able to login to the WordPress back-end; nevertheless, it was definitely worth it.

  • Juanda Saputra

    can i get help from you?.. i just looking for how to create rules in mod_security email alert automatically
    when I get interference from outside, then mod_security will automatically send alerts to my email,
    how do I make it?
    Can you explain step by step?
    im newbie at this, i need help from you
    maybe you'll email me to juandasaputra2727@yahoo.com
    thank you alot!

  • Juanda Saputra

    can i get help from you?.. i just looking for how to create rules in mod_security email alert automatically
    when I get interference from outside, then mod_security will automatically send alerts to my email,
    how do I make it?
    Can you explain step by step?
    im newbie at this, i need help from you
    maybe you'll email me to juandasaputra2727@yahoo.com
    thank you alot!

  • AskApache

    The only way to do that would be to setup your syslog-ng, rsyslog, logwatch, logrotate, etc.. to parse the mod_security log files, then using that 3rd-party software you would trigger the logs. Could also do this with a simplistic bash shell script that runs via a cron job.

My Online Tools


Popular Articles



Hacking and Hackers

The use of "hacker" to mean "security breaker" is a confusion on the part of the mass media. We hackers refuse to recognize that meaning, and continue using the word to mean someone who loves to program, someone who enjoys playful cleverness, or the combination of the two. See my article, On Hacking.
-- Richard M. Stallman



Related Articles

Twitter









[hide]

It's very simple - you read the protocol and write the code. -Bill Joy

Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 3.0 License, just credit with a link.
This site is not supported or endorsed by The Apache Software Foundation (ASF). All software and documentation produced by The ASF is licensed. "Apache" is a trademark of The ASF. NCSA HTTPd.
UNIX ® is a registered Trademark of The Open Group. POSIX ® is a registered Trademark of The IEEE.

+Askapache | askapache

Site Map | Contact Webmaster | License and Disclaimer | Terms of Service

↑ TOPMain