Mod_Security .htaccess tricks
.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
ModSecurity 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.
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.
- 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 theid/name
of"url"
, than deny them. - The
ARG_comment_post_ID
line denies requests that have an emptycomment_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 outIf 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
- mod_sec-httpd.conf
- got_root example rules for httpd.conf
- Parent Directory
- modsecurity_crs_21_protocol_anomalies.conf
- modsecurity_crs_20_protocol_violations.conf
- README
- modsecurity_crs_45_trojans.conf
- modsecurity_crs_35_bad_robots.conf
- modsecurity_crs_10_config.conf
- modsecurity_crs_50_outbound.conf
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.
- 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
- Common Web Attacks Protection - detecting common web application security attack
- Automation detection - Detecting bots, crawlers, scanners and other surface malicious activity
- Trojan Protection - Detecting access to Trojans horses
- Errors Hiding - Disguising error messages sent by the server
mod_security links
- DreamHost Version 1.9.5 Manual
- Reference of Actions, Commands, etc. - Official Site
- version 1.9 got_root rules
- mod-security-users - mailing list
- mod_security online rules generator - Noel Jackson
- An Intro to mod_security - Atomic Playboy
- Get mod_sec training
MOD_SECURITY: The Most Powerful Server-Side Security Technology I've Seen
htaccess Guide Sections
- htaccess tricks for Webmasters
- HTTP Header control with htaccess
- PHP on Apache tips and tricks
- SEO Redirects without mod_rewrite
- mod_rewrite examples, tips, and tricks
- HTTP Caching and Site Speedups
- Authentication on Apache
- htaccess Security Tricks and Tips
- SSL tips and examples
- Variable Fun (mod_env) Section
- .htaccess Security with MOD_SECURITY
- SetEnvIf and SetEnvIfNoCase Examples
« Search And Replace shell script helpful for UpgradesSmart HTTP and HTTPS .htaccess Rewrite »
Comments