ModSecurity 2.5 Status

The ModSecurity 2.5 release is scheduled for early/mid February. With the ModSecurity 2.5 release just around the bend, I have been spending my time doing a lot of testing, tweaking and polishing. I would like ModSecurity 2.5 and the core rule set (or any of the commercial rule sets Breach offers) to be easier to integrate into your environment. Ofer Shezaf and Avi Aminov are hard at work developing and tuning the core rule sets. Along with this comes requests from them for features to make integration and configuration easier. Because of this, I have included a few new features in ModSecurity 2.5 to make things easier for rule set authors. What this means is that it is time for the next release candidate of ModSecurity 2.5, 2.5.0-rc2. This release focuses primarily on making generic rule sets (such as the core rule set) easier to configure and customize for your sites.

Taming the Rule Set

ModSecurity does not give you much without a good rule set. However, good rule sets are time consuming to develop and require a lot of testing and tuning. More people benefit from a generic rule set, but these can be time consuming to customize for your sites while still allowing an easy upgrade path when new rule sets are released. For those of you who keep track of the community mailing list, you have undoubtedly seen the many false positive comments and requests for help getting generic rules to fit in a custom environment. A generic rule set will not work for everyone out of the box and will need to be tailored to fit. But tailoring can mean local modifications. And that may mean a lot of extra time spent retesting and reapplying modifications when it comes time to upgrade the rule set. Ryan Barnett has some excellent articles on how to deal with modifying a rule set in the least intrusive manner. However, I want to introduce some new functionality I have added to ModSecurity 2.5 to help deal with customizing rule sets without actually touching the rules -- making upgrades easier and require less time.

One of the biggest concerns over a generic third party rule set is that of policy. To block or not to block, that is the question. Some installers preferred just logging, others blocking via HTTP 403, some via HTTP 500, others preferred dropping the connection altogether with a TCP reset. In past versions of ModSecurity, this usually meant rule set authors had to include two versions of their rules, one for logging only and another for blocking. If this was not done, then the rule set installer would have to manually change all the actions in a rule set if not to the installer's liking. With ModSecurity 2.5, this blocking decision can now more easily be that of the rule set installer instead of the rule set author.

A new "block" action has been added to ModSecurity 2.5 to allow a rule set to specify where blocking is intended, but not actually specifying how to perform the blocking. The how is left up to the rule set installer, including the choice of not blocking at all. Currently this is done via inheritance (existing SecDefaultAction directive), but is also enhanced via the new SecRuleUpdateActionById directive. Future versions of ModSecurity will make this even more flexible.

Take the following rule set as an example. This will deny and log any request not a GET, POST or HEAD. So, things like PUT, TRACE, etc. will be denied with an HTTP 500 status even though the installer specified a default of "pass".

# Default set in the local config
SecDefaultAction "phase:2,pass,log,auditlog"

# In a 3rd party rule set
SecRule REQUEST_METHOD "!^(?:GET|POST|HEAD)$" "phase:1,t:none,deny,status:500"

With the new "block" action, this could be rewritten as in the following example. In this example the blocking action is, well, not to block ("pass" specified in the SecDefaultAction). This could easily be changed by the installer to "deny,status:501", "drop", "redirect:http://www.example.tld/", etc. The important thing to note here is that the installer is making the choice, not the rule set author.

# Default set in the local config
SecDefaultAction "phase:2,pass,log,auditlog"

# In a 3rd party rule set
SecRule REQUEST_METHOD "!^(?:GET|POST|HEAD)$" "phase:1,t:none,block"

So now some of you are (or maybe should be) questioning how this new "block" action differs from just not explicitly specifying a disruptive action in the rule to begin with and just letting the inheritance work as designed. Well, there is not really that much different at first glance. The named action is a little bit cleaner to read, but there are really two main differences. The first is that future versions of ModSecurity can expand on how you define and customize "block" in more detail. The second reason lies in what "block" is doing. It is explicitly reverting back to the default disruptive action, which leads into the next new feature.

Let me start off with another example (okay, it is the same example, but it is easy to follow). Below, there is no way to change the disruptive action other than editing the third party rule in place or replacing the rule with a local copy. The latter is better for maintenance, but it means keeping a local copy of the rule around which may require maintenance during a rule set upgrade.

# Default set in the local config
SecDefaultAction "phase:2,pass,log,auditlog"

# In a 3rd party rule set
SecRule REQUEST_METHOD "!^(?:GET|POST|HEAD)$" "id:1,phase:1,t:none,deny,status:500"

# Replace with a local copy of the rule
SecRuleRemoveById 1
SecRule REQUEST_METHOD "!^(?:GET|POST|HEAD)$" "id:1,phase:1,t:none,pass"

With ModSecurity 2.5, you can instead update the action to make it do something else. This is done via the new SecRuleUpdateActionById directive. It has the added benefit where if the third party rule set is upgraded later on (provided the id is the same, which it should be - hint) there is no editing required for the local copy of the customization. In fact, there is no local copy to edit at all.

# Default set in the local config
SecDefaultAction "phase:2,pass,log,auditlog"

# In a 3rd party rule set
SecRule REQUEST_METHOD "!^(?:GET|POST|HEAD)$" "id:1,phase:1,t:none,deny,status:500"

# Update the default action explicitly
SecRuleUpdateActionById 1 "pass"

You should notice in the last example that what I did was to change the third party rule back to what I originally specified in the SecDefaultAction. If only there was a way to just tell the rule to use the default. This is where the second reason for "block" comes into play (thought I forgot about that, eh). Instead of explicitly specifying the disruptive action, you can just specify it as "block" and it will instead force the rule to revert back to the last default action. In this example that is a "pass". This is just as if the rule author had specified "block" instead of "deny".

# Default set in the local config
SecDefaultAction "phase:2,pass,log,auditlog"

# In a 3rd party rule set
SecRule REQUEST_METHOD "!^(?:GET|POST|HEAD)$" "id:1,phase:1,t:none,deny,status:500"

# Revert the rule back to the default disruptive action, "pass"
SecRuleUpdateActionById 1 "block"

The new SecRuleUpdateActionById directive is not limited to only disruptive actions. You can update nearly any action. The only imposed limit is that you may not change the ID of a rule. However, some care should be taken for actions that are additive (transformations, ctl, setvar, etc.) as these actions are not replaced, but appended to. For transformations, however, you can "replace" the entire transformation chain by specifying "t:none" as the first transformation in the update (just as you would when inheriting from SecDefaultAction).

New Build Method and Automated Tests

Another big change in this release is the build process. ModSecurity 2.5 is now built with a more automated method. No more editing a Makefile. Instead, a configure script was added to automate the creation of a Makefile by searching for the location of all dependencies. Additionally, I added a number of automated tests to ensure operators and transformations are working as expected (executed via "make test").

# Typical build proceedure is now:
make test
sudo make install

Other Notable Changes in this Release

There are a few other minor additions and changes in this second release candidate as well.

  • The mlogc tool is now included with the ModSecurity 2.5 source.
  • To help reduce assumptions, the default action is now a minimal "phase:2,log,pass" with no default transformations performed.
  • A new SecUploadFileMode directive is available to explicitly set the file permissions for uploaded files. This allows easier integration with external analysis software (virus checkers, etc.).
  • To help reduce the risk of logging sensitive data, the query string is no longer logged in the error log.
  • Miscellaneous fixes for removing rules via SecRuleRemoveBy* directives.

How You Can Help

As you can see there are a lot of new features and enhancements in ModSecurity 2.5. I hope to see some good feedback from the release candidates so that we can get ModSecurity 2.5 polished up and the stable 2.5.0 available as soon as possible. Installing and testing in your environment is a great help, but there are other ways you can help.

  • Read through and give suggestions for improvements to the documentation.
  • Run through the new build/install procedure and give suggestions on how it can be improved.
  • Tell us how you are using ModSecurity and where your biggest challenges are and where you might be hitting limitations.

Getting ModSecurity

As always, send questions/comments to the community support mailing list. You can download the latest releases, view the documentation and subscribe to the mailing list at

Trustwave reserves the right to review all comments in the discussion below. Please note that for security and other reasons, we may not approve comments containing links.