RSS LJ

February 16, 2011

Any mod_rewrite gurus out there? (, , )

by fluffy at 10:50 PM

As an attempt at getting rid of some stupid spammers who are also trying to exploit nonexistent scripts on my site, I'm trying to redirect all requests that contain /../ in the original request URI (which are basically guaranteed to be an exploit attempt) elsewhere. However, it looks like mod_rewrite is only performing the substitution rule on the resolved path (i.e. it's treating /foo/../bar/ as /bar/) despite the fact that the REQUEST_URI environment variable still has the original /../-containing expression in it. I know my regexp is written correctly because the rule is working on other things (such as QUERY_STRING and HTTP_REFERER).

So, does anyone know if there's any configurations to mod_rewrite which might fix this behavior?

It's not a big deal but I've noticed a high correlation between the spammers who get through and the folks who are trying to find stupid CGI exploits and I figure anything that trips them up can only help.

Comments

#13786 02/17/2011 12:25 am
If the REQUEST_URI contains the crazy path in it, why not just write a RewriteCond that tests that? e.g,

RewriteCond %{REQUEST_URI} /\.\./
RewriteRule . - [F]


Or something of the sort.
#13787 02/17/2011 12:26 am
Er, that's what wasn't working. I should be more clear - the running script sees the original REQUEST_URI but mod_rewrite doesn't (as far as I can tell).
#13788 02/17/2011 12:32 am
Here's the clauses in my .htaccess:

# if there's a /../ in the URI or referrer, it's probably a spammer or exploit
RewriteCond %{HTTP_REFERER} /\.\./ [OR]
RewriteCond %{REQUEST_URI} /\.\./ [OR]
RewriteCond %{QUERY_STRING} /\.\./
RewriteRule . http://google.com/ [R,L]


And here's what happens if I manually send a request to /blog/../env.cgi via telnet to port 80:

gloss:~ fluffy$ telnet beesbuzz.biz 80
Trying 69.163.217.46...
Connected to beesbuzz.biz.
Escape character is '^]'.
GET /blog/../env.cgi HTTP/1.0
Host: beesbuzz.biz

HTTP/1.1 200 OK
Date: Thu, 17 Feb 2011 08:29:19 GMT
Server: Apache
MS-Author-Via: DAV
Vary: Accept-Encoding
Content-Length: 626
Connection: close
Content-Type: text/plain

SERVER_SIGNATURE=
UNIQUE_ID=TVzcX0WjzVcAAC9NGwAAAAAP
SERVER_PORT=80
HTTP_HOST=beesbuzz.biz
DOCUMENT_ROOT=/home/plaidfluff/beesbuzz.biz
SCRIPT_FILENAME=/home/plaidfluff/beesbuzz.biz/env.cgi
REQUEST_URI=/blog/../env.cgi
SCRIPT_NAME=/env.cgi
SCRIPT_URI=http://beesbuzz.biz/env.cgi
REMOTE_PORT=39394
[remainder omitted for brevity]


Note that the rewrite rule wasn't triggered, and env.cgi still shows a REQUEST_URI which should match it.

But if I falsify a referrer with the match string in it, it works:

gloss:~ fluffy$ telnet beesbuzz.biz 80
Trying 69.163.217.46...
Connected to beesbuzz.biz.
Escape character is '^]'.
GET /blog/../env.cgi HTTP/1.0
Host: beesbuzz.biz
Referer: foo/../bar

HTTP/1.1 302 Found
Date: Thu, 17 Feb 2011 08:31:20 GMT
Server: Apache
Location: http://google.com/
Vary: Accept-Encoding
Content-Length: 202
Connection: close
Content-Type: text/html; charset=iso-8859-1

<DOCTYPE>
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="http://google.com/">here</a>.</p>
</body></html>


And of course the QUERY_STRING one works fine too (although for whatever reason it's preserving the QUERY_STRING in the forwarded URL, which is a bit odd).