What's New in ModSecurityby Ivan Ristic, author of Apache Security
Two years ago, almost to the day, O'Reilly Network published my first article, Introducing ModSecurity. ModSecurity was stable and useful before the article went out, but it was not widely known. The publication of the article marked a new phase in the life of ModSecurity, introducing it to a much wider audience. As I write the second article, I can't help but feel another phase is about to start. I feel we are entering the phase of maturity.
ModSecurity 1.9 was released in early November 2005, more than a year after the previous stable release, version 1.8. The delay between the two releases was much longer than I had anticipated. Looking back, I really should have released 1.9 back in April, but it so happened that I skipped that release and continued adding new features. This resulted in a release that contains double the features and more than a 40 percent increase of the source code size.
This article describes the most important new features in ModSecurity 1.9. This is somewhat difficult to do, because there are so many of them, but I have decided to group the enhancements into three major areas:
- Rule engine enhancements
- Real-time audit log aggregation
- Stateful request monitoring
Rule Engine Enhancements
Arguably, the rule engine is the part of ModSecurity that received most of the attention in the 1.9 release. Most of these improvements went toward making the rule engine capable enough to support third-party rule databases. Although I had decided to delay the "official" ModSecurity rule database until infrastructure to share rules between multiple web application firewalls exists (for more details, have a look at the Portable Web Application Firewall Rule Format project), others (for example, Michael Shinn from Got Root) started efforts that focused on ModSecurity only.
As a first step, I decided to provide a way to associate meta-data with each rule (note that when I say "rule," I mean either a single filter statement or several statements chained together to form a single expression). I added four new actions:
- id, a unique rule identifier; a positive integer chosen from a reserved range (explained later).
- rev, a revision; a positive integer. A rule's revision starts at one and increases by one with every update.
- msg; a message associated with the rule, free form.
- severity, the rule's severity; a positive integer from 0 to 7 (to match the syslog and the Apache error levels).
Here is an example of all four new actions in use:
SecFilterSelective ARGS "<.+>" \ "id:1001,rev:2,severity:2,msg:'XSS attack attempt'"
To avoid collisions between rule identifiers, each publisher must only use the numbers from the range allocated to him. A special range is reserved for local use:
- 0-99,999; reserved for local use; rules with these IDs cannot be distributed.
- 100,000-199,999; reserved for internal use by the ModSecurity engine.
- 200,000-299,999; reserved for the rules that will be published on www.modsecurity.org.
- 300,000-; range not yet allocated.
The rule meta-data will appear with each log entry, making it very easy to correlate messages with the rules that caused them:
[Sun Nov 13 18:49:39 2005] [error] [client 192.168.2.11] mod_security: Access denied with code 403. Pattern match "<.+>" at QUERY_STRING [id "1001"] [rev "2"] [msg "XSS attack attempt"] [severity "2"] [hostname "www.example.com"] [uri "/?p=%3Cscript%3E"] [unique_id "0RdXKX8AAAEAAENXACQAAAAA"]