Compare request to referring URL; deny if same.

Giganews Newsgroups
Subject: Compare request to referring URL; deny if same.
Posted by:  D. Stussy (spam+newsgroups@bde-arc.ampr.org)
Date: Mon, 26 Jul 2010

Goal:  Compare the current request to the referring URL - and deny if
identical.

Given:  Assume port 80 only, no SSL, and no self-referring resources.

RewriteCond    %{HTTP_HOST}/%{HTTP_REFERER}        ([^/]+)/http://\1/
[NC]
RewriteCond    %{REQUEST_URI}?%{HTTP_REFERER}
([^?]+)\?http://([^/])\1($|\?|#)
RewriteRule      ^/    -    [F,NS]

Explanation:  Use trick in PCRE where "\1" is a previously-matched ()
expression.  Match that against the first substituted variable (host or
URI).

The first conditional checks ONLY for the hostname (which is case
insensitive per DNS rules).  The hostname is terminated by a trailing
slash, which never occurs in a valid hostname, whether a domain name or an
IP address literal.  The regex is open-ended at the tail because this line
does not check the URI itself.

The second conditional checks ONLY the requested URI against the referrer's
URI portion.  Since a question mark terminates a URI by separating the
"filename" part from a query string, it never appears within a URI and
therefore makes a suitable terminator.  Again, we use the "\1" trick to
compare the trailing part, which this time must terminate.

The match on the rewrite rule makes certain we're only matching local
requests (proxied requests would start with a scheme).  I mark it as "no
subrequests" because I want to deny original requests from outside the
server only.

I am aware that this "simplied version" does not compare the query string
nor anchor parts of the referring URL to that of the request.  I want
confirmation that this works for URLs that lack those features (i.e. no
query string and no anchor) before adding checks for those (in a similar
manner).  [I don't think an anchor is ever passed to a server as part of a
request, and if so, then we need no additional check for such.  However,
that's not true of a query string.]

Will this work as expected?

Replies