As Web applications grow more complex, they also become more and more vulnerable. As with other areas of network security, it's best to have multiple levels of protection in place. Ideally, you'd have security controls in place on your router and firewall, as well as in your application and database servers.
As Web applications grow more complex, they also become more and more vulnerable. As with other areas of network security, it’s best to have multiple levels of protection in place. Ideally, you’d have security controls in place on your router and firewall, as well as in your application and database servers.
While networks and databases are easy to secure, application servers — for example, Apache and PHP or mod_perl — tend to be more difficult to secure, leaving them prone to attacks.
One of the most common targets is Open Source software like PHPNuke. With access to source code, would-be attackers can easily scan and exploit common coding mistakes (such as poorly implemented input validation). The two most popular security exploits are cross-site scripting and SQL injection.
To be sure, there’s lots to be paranoid about. Luckily, adding the Apache module mod_security to your defenses may let you sleep a little better at night. mod_security provides generic scanning facilities that examine user input (primarily URL parameters and form submissions), looking for suspicious patterns. The module filters, and optionally rejects, incoming requests based on a number of different criteria like CGI variables, HTTP headers, environment variables, and even individual script parameters. mod_security can also create an audit log, storing full request details in a separate file, including POST payloads (the audit feature can be turned on or off on a per-server or per-directory basis). Using mod_security isn’t a silver bullet, but it does offer a fair degree of protection against common attacks.
Here are some simple examples that illustrate the syntax and flexibility of mod_security:
- To protect against SQL injection, try the directive SecFilter “delete( |\n)+from”. This rule attempts to identify SQL DELETE queries that may be injected in a submission to your application. While it’s a good start, the regular expression isn’t bullet-proof. For example, it wouldn’t match this very destructive query: delete /* fool the filter */ from user. The SQL comments would allow it to slip right by and destroy your user table.
- To guard against operating system attacks, you can use directives such as SecFilter /etc/passwd. There’s still a lot of code out that trusts user input way too much, allowing filenames to be specified by the user. If you don’t carefully filter input, users can trick your application into reading files that it really shouldn’t. It’s an old hack, but still a good one, and mod_security can help guard against it.
mod_security has one important advantage over other security techniques: it can scan GET and POST requests. That’s important because POST data is often overlooked in quick security checks.
To enable POST scanning, simply put this in your httpd.conf file:
Of course it’d help to know when the bad guys visit. Simply enable mod_security‘s audit log, and it will record any incidents:
Finally, you also have control over the actions that mod_ security takes. A common configuration is:
That tells the module to deny and log any requests that match one of the mod_security SecFilter rules, and to return an HTTP 403 response to the bad guy.
You can also customize the behavior for individual rules, thus overriding the default action. Here’s how:
SecFilter expression deny,nolog,status:404
The Arms Race
Security is a constantly escalating battle. The bad guys work to automate their tools and make them smarter, while the good guys focus on improving their code and devising better detection and prevention tools. mod_security is a very useful component in securing Web-based applications.
This month’s “Do It Yourself” project was suggested by Ivan Ristic, a Linux Magazine reader. Do you have an idea for a project we should feature? Send your suggestions to firstname.lastname@example.org.