-->

Mod rewrite query parameter validation and blockin

2020-02-15 03:03发布

问题:

On my site, only few query query parameters are allowed but, some scanners or hackers trying to access url with unique parameters which my php application doesn't support, I can block them in php application level, by validating $_GET parameters, but my server is getting loaded, so I want to show 403 if parameters are not valid

Query parameters can be in any order

So far what I tried is as follows

# IF there is query string
RewriteCond %{QUERY_STRING} ^.+$

# Then parameters can be only query|debug|lang
# block any extra parameter
RewriteCond %{QUERY_STRING} !(^|$)(query|debug|lang)=[^&]+(&|$) [NC]

RewriteRule ^(.*)$ - [F,L]

But problem here is

http://example.com/search?query=test&debug=on&lang=en&foo=bar

its passing even if hacker pass foo=bar, I want to show 404, strict parameter checking before reaching php application.

Here is : Rewrite Tester

It's not showing 404

Example of Valid url with query parameter

http://example.com/search?query=test&debug=on&lang=en

Example of INVALID url with query parameter

(Check Is there any query parameter other than allowed one ??? )

http://example.com/search?query=test&debug=on&lang=en&foo=bar
http://example.com/search?a=1
http://example.com/search?a=2
http://example.com/search?query=test&a=1

Same I can do in php, But I want to block request before reaching my php application.

$allowed = array('query', 'lang', 'debug');
foreach($_GET as $key => $value)
{
         if(!in_array($key, $allowed))
         {
                  http_response_code(403)  
                  die('Forbidden');
         }
}

Also on my website, request uri allowed chars are [A-Za-z0-9_-]

How can I block if request uri containing anything extra

Also want to know,

  1. is it possible in rewrite to check POST variables too ?
  2. I see many suspicious agents string how can I block them
  3. Also I see in referral url hackers trying to inject xss and sqlinjection string how can I block them.

回答1:

You may replace your existing rule with this rule:

# Then parameters can be only query|debug|lang
# block any extra parameter
RewriteCond %{QUERY_STRING} ^(?!(?:query|debug|lang)=[^&]+(?:&(?:query|debug|lang)=[^&]+)*$). [NC]

RewriteRule ^ - [F]

This rule will return 403 if any query parameter other than query|debug|lang is present in URL.

Here (?!...) is a negative lookahead assertion that will fail if query string has anything except given parameters.


RegEx Details:

  • ^: Start
  • (?!: Start of negative lookahead
    • (?:query|debug|lang)=[^&]+: Match one of the 3 allowed query parameter and it's value
    • (?:: Start non-capture group
      • &: Match a &
      • (?:query|debug|lang)=[^&]+: Match one of the 3 allowed query parameter and it's value
    • )*: End non-capture group. * means 0 or of this group
    • $: End
  • ): End of negative lookahead expression
  • .: Make sure query string is not empty

In simple words negative lookahead asserts failure when query string has any query parameter other than the 3 allowed parameters.



回答2:

You can use the following :

RewriteEngine on

#if there is query string
RewriteCond %{QUERY_STRING} ^.+$
# Then parameters can be only query|debug|lang
# block any extra parameter
RewriteCond %{QUERY_STRING} !^(query|debug|lang)=[^&]+&(query|debug|lang)=[^&]+&(query|debug|lang)=[^&]+$ [NC]
RewriteRule .* - [F,L]

This will return a 403 forbidden error for URLs not matching the RewriteCond regex.