Home > Blockchain >  mod_rewrite match encoded URL
mod_rewrite match encoded URL

Time:10-03

In my Apache config I'd like to return 403 when a query string parameter contains a specific value. Everything works fine except when the client query string is encoded in hex. How do I get it to match without having to type out the literal hex string?

RewriteEngine On
RewriteCond %{QUERY_STRING} mykey=myval [NC]
RewriteRule .* - [F,L]

Then test it:

# Works fine, returns 403
curl -I 'http://localhost/?mykey=myval'

# Does not work, returns 200:
curl -I 'http://localhost/?mykey=myval'
curl -I 'http://localhost/?mykey=myval'

thx

CodePudding user response:

The QUERY_STRING server variable remains %-encoded (as it is in the request), unlike the URL-path matched by the RewriteRule pattern, which is %-decoded.

However, on Apache 2.4 you can use an Apache expression with the RewriteCond directive to URL decode the QUERY_STRING before making the comparison. For example:

RewriteCond expr "unescape(%{QUERY_STRING}) =~ /mykey=myval/"
RewriteRule ^ - [F]

This will now successfully match requests of the form ?mykey=myval, ?mykey=myval and ?mykey=myval.

You don't need the L flag when using F, since it is implied. The regex ^ is marginally more efficient than .* if you simply need to be successful for any URL-path (without actually matching anything).

Note that the regex mykey=myval matches that string anywhere in the query string, so it would successfully match anymykey=myval and mykey=myvalany, which may or may not be a problem. To remove that ambiguity and only match the "key=value" pair in the query string then you would need to use a regex like (?:^|&)mykey=myval(?:&|$) instead.

  • Related