Securing Apache Web Server with mod_security
The Internet has its share of packet filters and proxy servers in order to increase the security for clients and servers alike. Filtering network traffic is never a bad idea since it provides a basic level of protection. When it comes down to protecting web servers your packet filter will most probably allow HTTP and HTTPS traffic to your server application. Unless you deploy an application proxy that inspects HTTP you can't do more. But you can equip your Apache web server with mod_security which in turns helps you to analyse any request thrown at it.
Application Layer Inspection
When you do any network traffic filtering or inspection you have to keep in mind that usually nothing understand the things that should be inspected better than the application in question. This is one of the reasons why proxy filters are "better" suited for this job. They know the protocol and can normalise fancily encoded requests. mod_security is in a very similar position. It sits right inside the Appache httpd process and inspects the HTTP requests. This is an important advantage over proxies since it can also see compressed or even encrypted content without difficulties.
So, what needs to be inspected? Apache's httpd surely does inspect HTTP requests. What do I need more? Well, there are some things mod_security can do for you.
- Better logging
The module can log the content of HTTP POST requests. Apache usually doesn't log that. Furthermore you can log complete HTTP transactions. This makes the job of a potential attacker harder. In addition to that you have a very fine control on what and when to log. - Real time operation
mod_security sees the requests directly and can act immediately. - Anomalies
The security module can act on anomalies in the web server operation by looking at request rates, IP addresses, HTTP sessions and user account. - Black-/whitelisting
You can use a signature-based approach and define what you want to allow and what you want to block. - Protects other web servers
You can even protect other web server software by combining it with mod_proxy. The Apache server can act as reverse proxy thus seeing all HTTP requests and applying rule sets.
Installation
The current released version is 2.x. It works well with Apache 2.0.x and 2.2.x. Apache 1.3.x is not supported anymore (you should really upgrade your Apache servers, seriously). mod_security has some more requirements.
- You'll need the module mod_unique_id installed.
- libxml2 and its development package is needed since the module can inspect XML and has to parse it.
- If you use an Apache web server from your distribution, make sure the development packages are installed as well.
- You'll need either the PCRE library for parsing regular expressions from your operating system or bundled with your Apache. mod_security's documentation has a special note in case the compilation goes wrong.
LoadFile /usr/lib/libxml2.so # optional LoadModule security2_module modules/mod_security2.soThere we go. The only thing we need is to configure the module and the rule sets.
Configuration
One word of caution: Every security measure must be applied with a specific purpose. You can't just add filters without thinking about the consequences for applications. You or your users may have web applications running that break when special security measures are activated. If you are not sure about not breaking something you can use all rule sets and actions in "audit mode". Then mod_security will only log but not block. This is a good idea to test everything until you are sure to switch to "live mode". It also keeps your users happy.
A very simple test is to add a single rule by using the following two lines:
SecRuleEngine On SecRule REQUEST_URI attackNow send your web server a request with the word attack in it. You should get the error code 403 Forbidden and the blocked request should generate an entry in Apache's error log file. If you set the first option to
SecRuleEngine DetectionOnlythen the module will only detect and block nothing. We will now take a look at the classes of different options available. Please make sure you take a look at mod_security's documentation and at the file in the sample core rules archive that can be downloaded.
General Options
mod_security has several groups of options. Here are some of the basic configuration directives.
SecRuleEngine On SecRequestBodyAccess On SecResponseBodyAccess OnThe first line switches request inspection on or off. The other two lines control whether request and response body data will be inspected by the module. Keep in mind that the data has to be buffered. This means that it is required for inspecting HTTP POST requests, but it has to be buffered and thus needs memory. You can reduce the amount of memory used by this directive.
SecRequestBodyInMemoryLimit 131072You can also limit the size of the HTTP request body data. This is very handy for disabling large data in HTTP POST requests.
SecRequestBodyLimit 10485760Every request bigger than 10485760 byte will be answered by the error code 413 Request Entity Too Large. The default is 134217728 bytes (131072 KB).
Web servers typically include the MIME type of data they put into responses. You can control the types you want to inspect. Usually you will not want to parse JPEG or PDF data.
SecResponseBodyMimeTypesClear SecResponseBodyMimeType (null) text/plain text/html text/css text/xmlThe first statement clears the list of types to be checked. The second line sets the types we are interested in. File uploads may be something you wish to control. You can redirect every file upload to a seperate directory. In addition you can collect all uploaded files to your server provided you have the disk space. This may be useful for forensic activities after something has gone wrong.
SecUploadDir /var/spool/apache/private SecUploadKeepFiles OffIt is good practice not to use the usual directories for temporary files for storing uploads. Create a directory for this purpose and set the permissions accordingly. Only Apache needs to access this space.
Logging
You can enable audit logging which can help you a lot during debugging or worse situations. You have the choice of logging everything or only events that triggered one of mod_security's internal checks. This includes the rule sets.
SecAuditEngine RelevantOnly SecAuditLogRelevantStatus "^[45]"We want to log only relevant events and concentrate on responses that generate 4xx or 5xx status codes. That's what the regular expression is for. You can do a full logging if you need to. The log can be written into a single file or into a directory with one file per log event. The latter is usually only for high volume sites.
SecAuditLogType Serial SecAuditLog /var/log/www/modsec_audit.log # SecAuditLogStorageDir /var/log/www/modsec_auditAs mentioned before the content that can be logged is extended. You can log portions of the original HTTP request along with the response.
SecAuditLogParts "ABEIFHZ"This means we want to log the audit header and trailer (options A and H), the original request (option B), an intermediate response body (option E), the modified request body (option I), the final response header (option F) and the final boundary of the log event (option Z, which is mandatory). The intermediate response body is either the original response or the modified response by mod_security. The modified request body is either the original request body or a shortened variant whenever multipart/form-data encoding was used. The default options are "ABIFHZ".
Rules
The security module uses five distinct phases for processing requests to and responses from the web server.
- Parse request headers
- Parse request body
- Parse response headers
- Parse response body
- Do logging
SecRule VARIABLES [OPERATOR] ACTIONSWhen written in this form mod_security will
- expand the variables,
- apply the operator if present,
- trigger once for a match in every variable,
- and execute
- the default action or
- the actions described in the rule.
SecRule "REQUEST_URI|QUERY_STRING" attackThis does the same but with two different variables. The action will be triggered if the string fragment is found in either variable. You can use well known operators inside rules. Matching of regular expressions is done by the PCRE library, so you can use any constructs PCRE understands (which is basically everything you can do in Perl's pattern matching). Long lines can be split by using "\" just as in Bash shell scripts.
Keep in mind that the VARIABLES section contains variables. Their content changes. If the variable is empty or not present, the rule doesn't match. This is importent and desired for parameter checking. Variables can be ARGS, FILES, FILES_TMPNAMES, ENV, REMOTE_PORT, QUERY_STRING, SCRIPT_BASENAME, AUTH_TYPE, REQUEST_COOKIES, SESSIONID, TIME and many more. The reference has a complete list.
Operators
mod_security rules can contain operators. They are used to validate the request or look for special anomalies. The "@" indicates that an operator follows.
SecRule ARGS "@validateUtf8Encoding" SecRule ARGS "@validateByteRange" 10,13,32-126The first rule checks the request for valid UTF-8 encoding. The second example checks for a specific range of characters in the request. If the request contains other characters than linefeed, carriage return or the US ASCII characters then the action is triggered. You can also invoke additional scripts.
SecRule FILES_TMPNAMES "@inspectFile /usr/local/bin/check_file.pl"This redirects any uploaded files to the Perl script for further checks. The exit code of the script tells mod_security whether to invoke the action or not. You can even use realtime blacklists for your rules.
SecRule REMOTE_ADDR "@rbl bad.guys.and.girls.example.net"
Actions
There are five general types of actions.
- Disruptive actions - abort current transaction.
- deny - stops transaction and generates an error.
- drop - drops transaction without error.
- redirect - responds with a redirection (such as 301 or 302).
- proxy - forwards the request to another server.
- pause - slows down the execution of the request.
- Non-disruptive actions - change the state of the current transaction.
- Flow actions - change the flow of the rules.
- allow - stops processing of subsequent rules.
- chain - combines the active rule with the next one.
- pass - ignores a match in the current rule; useful for commenting rules out, but leave them still active.
- skip - skip the next or more rules.
- Meta-data actions - contain meta data for rules as additional information; useful for logging.
- Data actions - are placeholders for other actions.
SecRule REQUEST_FILENAME|ARGS|ARGS_NAMES|REQUEST_HEADERS|XML:/* "[\n\r]\s*(?:to|bcc|cc)\s*:.*?\@" \ "t:none,t:lowercase,t:urlDecode,capture,ctl:auditLogParts=+E,log,auditlog,msg:'Email Injection Attack. Matched signature <%{TX.0}>',,id:'950019',severity:'2'"</%{TX.0}>Note that I inserted a line break for better readability. The action parameter is a single string and tell the module to log every match to the normal log and the audit log with the message text Email Injection Attack along with some parameters of the request. The core rules have more examples for other attacks such as cross-site scripting, SQL injection, HTTP anomalies and the like.
Rule Management
Make sure that you keep your rule files in good order and make sure that you document every change. This is very important. Any kind of filter can break whole applications and protocols. Therefore you need to now what changes caused which effects. You will also need this information when developing your own rules. Bear in mind that custom web applications need custom rules. Some attacks may be the same, but customised applications have their peculiarities that have to be considered. A good place to start are the core rule sets. You can disable rules without deleting them from the configuration. This is extremely useful in case you wish to distribute rules to multiple servers. You can do that by splitting your rule into multiple files and have a master configuration that enables or disables selected sets.
Performance and Deployment
Everything has a price and so does filtering HTTP requests. mod_security needs to holds the request in a buffer or has to store it to a temporary file. You have to take this into account. The parsing add a little overhead in terms of CPU cycles to the web server as well. If you install the module on a server that already has performance issues things won't get better. That's what the reverse proxy method is for. Hard hit sites probably won't go anywhere without additional proxies.
One last thing to keep in mind are your own web applications. Don't just set up the core rules and accept all defaults. Inspect the rule sets and decide for yourself if you need all the rules. Things can break if you are not careful enough. No one knows your web apps better than you. Use this knowledge to your advantage.
Useful resources
- mod_security web site
- Apache Security
- Hardened PHP Project - Suhosin
- Application Layer Packet Classifier for Linux
- Squid reverse proxy
- Snort
Talkback: Discuss this article with The Answer Gang
René was born in the year of Atari's founding and the release of the game Pong. Since his early youth he started taking things apart to see how they work. He couldn't even pass construction sites without looking for electrical wires that might seem interesting. The interest in computing began when his grandfather bought him a 4-bit microcontroller with 256 byte RAM and a 4096 byte operating system, forcing him to learn assembler before any other language.
After finishing school he went to university in order to study physics. He then collected experiences with a C64, a C128, two Amigas, DEC's Ultrix, OpenVMS and finally GNU/Linux on a PC in 1997. He is using Linux since this day and still likes to take things apart und put them together again. Freedom of tinkering brought him close to the Free Software movement, where he puts some effort into the right to understand how things work. He is also involved with civil liberty groups focusing on digital rights.
Since 1999 he is offering his skills as a freelancer. His main activities include system/network administration, scripting and consulting. In 2001 he started to give lectures on computer security at the Technikum Wien. Apart from staring into computer monitors, inspecting hardware and talking to network equipment he is fond of scuba diving, writing, or photographing with his digital camera. He would like to have a go at storytelling and roleplaying again as soon as he finds some more spare time on his backup devices.