2

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.
user3637224
  • 585
  • 1
  • 3
  • 22

2 Answers2

1

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.

Amit Verma
  • 40,709
  • 21
  • 93
  • 115
  • `query=.+&debug=.+&lang` order is not fixed, it can be anywhere, example `http://example.com/search?debug=on&query=test&lang=en` – user3637224 May 08 '19 at 10:37
  • @user3637224 I have updated the pattern . Does it work now? – Amit Verma May 08 '19 at 10:56
  • @user3637224 Thats what you mentioned in your Post. You said that the valid url is `http://example.com/search?query=test&debug=on&lang=en` . The rule should work fine for that URL. What do you mean by `/search?debug=on` ? Is this also the part of your valid urls? – Amit Verma May 08 '19 at 12:32
  • Actually parameters can be in any order, and allowed are 3 parameters, which can be either `query` or `lang` or `debug` or all three – user3637224 May 08 '19 at 12:49
  • @user3637224 ok , in that case you can use a rewriteCond to check querystring with a single key value pair. Add the following condition right above the rule or below the second RewriteCond `RewriteCond %{QUERY_STRING} !^(query|debug|lang)=[^&]+$ [NC]` . – Amit Verma May 08 '19 at 13:35
  • 1
    @user3637224 You must not replace, but *add* the `RewriteCond` to the existing `RewriteRule`. – Olaf Dietsche May 15 '19 at 12:47
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.

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    Oh, You saved me, Will you please explain This regex `^(?!(?:query|debug|lang)=[^&]+(?:&(?:query|debug|lang)=[^&]+)*$).`, Looks like now I can block some scanners hitting, Also I want to enable only request uri can have only `[A-Za-z0-9_-/]` but its blocking some encoded chars, I am not sure, how to filter out only safe chars in request uri – user3637224 May 16 '19 at 06:28
  • thank you so much, if you have time please guide me towards web safe chars for request uri, currently all my urls using only `[A-Za-z0-9_-/]+` chars but to how to deal with encoded chars with `%` ? – user3637224 May 16 '19 at 07:01
  • 1
    Keep hyphen at last char in character class to make it `[\w/-]+`. Other than these characters all other special characters need not be there – anubhava May 16 '19 at 07:06
  • sir can you please guide me on this [post](https://stackoverflow.com/questions/56679932/apache-proxy-rewrite-setup-for-specific-file-types-inside-sub-directory) – user3637224 Jun 20 '19 at 06:09