Tag Archive for 'apache'

17
Aug

mod_rewrite + mod_proxy + spaces in URI = boom!

So I have a piece of .htaccess magic on one of the sites that I run.

What this particular set of instructions do is allow me to run a second web server of a different version behind my Apache 1.3 installation, and still have it appear to the end user as if I only run one web server, basically it’s a proxy. I like this, this is good.

The .htaccess rule I setup is for Trac and specifically the tracd daemon, and my rules look like this:
RewriteEngine On
RewriteRule ^trac_common/(.*)$ http://127.0.0.1:8080/trac_common/$1 [P]
RewriteRule ^projects/?(.*)$ http://127.0.0.1:8080/$1 [P]
RewriteRule ^trac(.*)$ http://127.0.0.1:8080/trac$1 [P]

The [P] at the end of those mod_rewrite lines is telling mod_rewrite to use mod_proxy to handle the request and forward the request internally to the web server running on the high port.

Nice and simple, if a request comes in which has the url /projects/ go to the top Trac page.
If a request comes in for the project named trac with the url /trac/ go to that projects’ Trac site.

This works OK, except that the code browser within Trac is accessing the Subversion repository, and within SVN some of the directory paths and files have spaces in them.

What happens is that under the hood a request ends up looking like this:
GET /trac/browser/root/path with spaces in HTTP/1.1

That’s wrong as only two spaces can exist in a GET request, and those spaces delimit the request type, request URI and the protocol.

So somewhere within mod_rewrite and mod_proxy the spaces are not being escaped as they should, because the request should look like this:
GET /trac/browser/root/path%20with%20spaces%20in HTTP/1.1

So, how do you go about replacing spaces using mod_rewrite?

Much googling will tell you that mod_rewrite does not allow you to perform regexp or string replacements.

However, you don’t need to. mod_rewrite already has a RewriteMap feature and we can use that.

If we take our rewrite rules out of the .htaccess file and place them in our httpd.conf file we can use the built-in escape function:
RewriteMap escape int:escape
RewriteEngine On
RewriteRule ^/trac_common/(.*)$ http://127.0.0.1:8080/trac_common/${escape:$1} [P]
RewriteRule ^/projects/?(.*)$ http://127.0.0.1:8080/${escape:$1} [P]
RewriteRule ^/trac(.*)$ http://127.0.0.1:8080/trac${escape:$1} [P]

That now correctly escapes spaces in the matched URL’s and the source browser connected to SVN now works perfectly.

Hope this saves someone else some time.

24
May

On the value of mod_security

Over on plastic bag, Tom has a problem.

The problem in one word is spam.

He actually had two problems (a mass download of his site via a “wget recursively” style script, and the mass spamming of his blog via a “post continuously” script), but both have the same answer: the Apache module named mod_security.

I investigated and installed mod_security on my server in the winter of 2004 when a PHP worm was harvesting forum addresses from Google and then propagating itself via vulnerable GET requests using the PERL module to perform the request.

The essence of mod_security is that it is a software firewall that you can include within the Apache web server, and that it filters traffic before it generates a request within your web application.

This image sums it up pretty nicely:
mod_security illustration

Installation is reasonably easy, so I won’t repeat the documentation that you can find on their site.

The key part is defining the rules, and two rules would’ve saved Tom from his downtime:

The first should block wget and httrack user agents to prevent mass download, and for the hell of it the PERL module that was used in most PERL worms:
SecFilterSelective HTTP_USER_AGENT httrack
SecFilterSelective HTTP_USER_AGENT wget
SecFilterSelective HTTP_USER_AGENT lwp

The second filter should block GET requests on mt-comments.cgi. I’m guessing this one because I don’t use MT, however comments are POST’d to via the form at the bottom, and I think that most spam would simply be using GET… so let’s nuke that… note the chaining together of these so that the condition must match both parts of the rule for the rule to be applied:
SecFilterSelective SCRIPT_FILENAME mt-comments.cgi chain
SecFilterSelective REQUEST_METHOD GET

There may be far more we can do to that… I’m just jotting this down as a quick example of a rule that may do it. I’d want to look at how Movable Type works and test the rules prior to sending them live. That latter one may be far too broad, for example.

But in general, that’s all we need to do… block all mass downloads, and block all GET scripted spam against the comments page of MT.

I’m sure there are many more examples of mod_security helping out, on Bowlie I use it to prevent PHP worms, detect intrusions, and kill spam. If it’s not yet part of your toolkit for administrating an Apache web server, it most definately should be.

And to help you get started, some starter links and example pages:
Mod Security Manual
Security Focus Guide
Mod Security Quick Examples