Htacess Helicon APE false positive 403 Fail

Solution 1:

I've expressed my concern in comments that there must be "something else" going on, but anyway...

It's difficult to write an exception for a rule that shouldn't (read: "can't") be triggered in the first place - it's complete guess work. After all, why would the exception be honoured?

That rule should already avoid the given request for a couple of "big" reasons:

  1. The request does not include a query string.
  2. The regex in the condition (CondPattern) does not match any part of URL (even if it was in the query string).

Considering #2 above, the regex already contains a sufficient exception not to match the given request, so how can we implement "another" exception?

You could modify the CondPattern to avoid instances when a hyphen (-) follows the word "union", using a negative lookahead. For example:

(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union(?!-)|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode)

So, the above matches Xunion, but not Xunion-, where X is one of the character sequences from the first alternation group (ie. (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00)).

Or, when a hyphen follows any of these keywords:

(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode)(?!-)


(UPDATE: The following two suggestions probably won't work, since it seems that the directives are only processed after IIS has already rewritten the URL. At which point the URL-path is simply /index.php, not /union-contracts.)

Or, modify the RewriteRule so that it does not match when the URL-path starts with /union- (although this potentially provides a backdoor for the XSS attempt the rule is trying to block). For example:

RewriteRule !^/?union- - [F]

(On Apache at least, the L flag is not required when the F flag is used - it is implied.)

Alternatively, you create another rule at the top, before your existing rules, that creates an exception for when requesting a URL that starts /union- and does not have a query string (although that would seem to be a contradiction, if the other rule is to be believed). For example:

RewriteCond %{QUERY_STRING} ^$
RewriteRule ^/?union- - [L]

However, this will potentially "break" the request if you have other rules later in the file that need to rewrite the URL in some way - since these will not occur.

I'm assuming Helicon-APE/mod_rewrite works in a directory-like context (eg. .htaccess style syntax as opposed to server or virtualhost context)? Although that should not affect the directives above, as it happens.


UPDATE: When IIS generates a 404 error the URL becomes:

index.php?404;http://example.com:80/union-contracts

Ah, yes! That URL will get caught by the original condition. So, it seems the mod_rewrite directives are processed after the IIS "rewrite" in web.config! This does make these "security" directives somewhat superfluous or even incorrect, since they are supposed to be run on the initial request from the client. And....

I filter out the URL to just the last part and I check the database against that string to see if it matches a saved URL

Since you are actively parsing the URL and filtering out just the part you require then these "security" checks would seem to be redundant anyway for these "404" requests at least. (In fact, depending on the real files (ie. non-404 requests) that could potentially be requested directly, could a malicious query string of this nature realistically pose a security threat for any URL?)

The two suggestions above to modify the regex in the condition to exclude instances when a hyphen follows the "union" keyword, or any keyword, would still apply here and would seem to solve the immediate problem.

You could also abort all checks when a URL of the form index.php?404; is encountered (ie. after it has been rewritten by IIS). (I'm assuming all your mod_rewrite directives are similar "security" checks?)

For example, add the following to the top of the .htaccess script, before the existing directives:

RewriteCond %{QUERY_STRING} ^404;
RewriteRule ^/?index\.php - [L]

This should prevent any further processing when a URL of the form /index.php?404;...... is encountered. (Since you are parsing the URL anyway in your script.)