Waf Charm

Blog

You can now choose new rule action and set regions in the geographic match statement in AWS WAF

Table of Contents

  1. 1. Introduction
  2. 2. Challenge action configuration and behavior
  3. 3. How to set up geographic match rule statement with regions
  4. 4. Usages in WafCharm rule
  5. 5. Conclusion

1. Introduction

We are going to take a look at two updates from AWS WAF.

https://docs.aws.amazon.com/waf/latest/developerguide/waf-captcha-and-challenge.html

The first update is the new action called Challenge, which has been added along with CAPTCHA action.

CAPTCHA action is an action that provides a puzzle to determine if the requester is a human being or not to take measures against bots. Please refer to the blog post below for more information.
The Challenge rule action added in this update is an action that determines if the request is from bots in the background without requiring end users to provide some sort of input.

https://www.wafcharm.com/en/blog/aws-waf-captcha-action-available-en/

https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-geo-match.html

The second update allows rules to include region codes in the geographic match rule statements.
A simple example would be to specify states when adding a statement to match with the US.

2. Challenge action configuration and behavior

You will be able to see the Challenge action on the rule creation page under the Action section.

Token immunity time will be set for the Challenge rule action, and the default is 300 seconds.

You can change the immunity time.

Let's try accessing with curl to check if the Challenge rule action is functioning.

$ curl -v https://XXXXXXXXXXXX.us-east-1.amazonaws.com/test/login
*   Trying 52.72.XXX.XXX...
* TCP_NODELAY set
* Connected to hgk1gtihdb.execute-api.us-east-1.amazonaws.com (52.72.XXX.XXX) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.execute-api.us-east-1.amazonaws.com
*  start date: Jun 22 00:00:00 2022 GMT
*  expire date: Jul 21 23:59:59 2023 GMT
*  subjectAltName: host "XXXXXXXXXXXX.us-east-1.amazonaws.com" matched cert's "*.execute-api.us-east-1.amazonaws.com"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fb37f808200)
> GET /test/login HTTP/2
> Host: XXXXXXXXXXXX.us-east-1.amazonaws.com
> User-Agent: curl/7.64.1
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 202 
< date: Fri, 28 Oct 2022 02:05:45 GMT
< content-type: application/json
< content-length: 0
< x-amzn-requestid: 5c558c9b-0cad-467c-b564-d13a814448ff
< x-amzn-errortype: ForbiddenException
< x-amz-apigw-id: asXXEESboAMFpQg=
< cache-control: no-store, max-age=0
< x-amzn-waf-action: challenge
< 
* Connection #0 to host XXXXXXXXXXXX.us-east-1.amazonaws.com left intact
* Closing connection 0

The Challenge action was taken and HTTP status code 202 is returned.

If the request contains Accept header with value text/html, the Challenge rule action will return a script and evaluates the request.
Therefore, AWS has noted to only use the Challenge action on GET text/html requests.

https://docs.aws.amazon.com/waf/latest/developerguide/waf-captcha-and-challenge-how-it-works.html

https://docs.aws.amazon.com/waf/latest/developerguide/waf-captcha-and-challenge-best-practices.html

3. How to set up geographic match rule statement with regions

ISO 3166-2 is used for the country and region codes.
https://en.wikipedia.org/wiki/ISO_3166-2

For Japan, each prefecture can be set as listed below. For example, Tokyo can be represented by JP-13.
https://en.wikipedia.org/wiki/Prefectures_of_Japan

To use this in a rule, you cannot just specify the conditions to match like specifying a country. You will have to obtain a label from another rule to determine the region.

Example of using a label
https://www.wafcharm.com/blog/aws-waf-label-usage-ja/

For geographic match rule based on country

  • You can set an action for a condition that matches with a specific country (Rule #1)

For geographic match rule based on region code

  • You will need to create a rule that matches a specific country with rule action Count (Rule #1)
  • Using a label from the rule above, create a label match condition and set an action (Rule #2)

Let's compare the JSON formats.

For geographic match rule based on country
Rule #1 (Blocking the US)

{
  "Name": "geo",
  "Priority": 0,
  "Action": {
    "Block": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "geo"
  },
  "Statement": {
    "GeoMatchStatement": {
      "CountryCodes": [
        "US"
      ]
    }
  }
}

For geographic match rule based on region code
Rule #1 (Obtain a label for access from the US. Rule action is Count)

{
  "Name": "geo",
  "Priority": 0,
  "Action": {
    "Count": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "geo"
  },
  "Statement": {
    "GeoMatchStatement": {
      "CountryCodes": [
        "US"
      ]
    }
  }
}

Rule #2 (Using the US rule label, block regions other than Oregon and Washington)

{
   "Name": "blockUSButNotOROrWA",
   "Priority": 11,
   "Statement": {
     "AndStatement": {
       "Statements": [
         {
           "LabelMatchStatement": {
             "Scope": "LABEL",
             "Key": "awswaf:clientip:geo:country:US"
           }
         },
         {
           "NotStatement": {
             "Statement": {
                "OrStatement": {
                  "Statements": [
                    {
                       "LabelMatchStatement": {
                         "Scope": "LABEL",
                         "Key": "awswaf:clientip:geo:region:US-OR"
                       }
                    },
                    {
                       "LabelMatchStatement": {
                         "Scope": "LABEL",
                         "Key": "awswaf:clientip:geo:region:US-WA"
                       }
                    }
                 ]
               }
             }
           }
         }
       ]
     }
   },
   "Action": {
     "Block": {}
   },
   "VisibilityConfig": {
     "SampledRequestsEnabled": true,
     "CloudWatchMetricsEnabled": true,
     "MetricName": "blockUSButNotOROrWA"
   }
}

The mechanism is quite simple if you know that you need a separate rule to obtain a label to use region codes.

4. Usages in WafCharm rule

Currently, we do not plan to add default WafCharm rules using these two features.

5. Conclusion

By applying the Challenge rule action to login pages, you will be able to reduce suspicious access without burdening end users.

We couldn't come up with usages of limiting based on prefectures within Japan, but limiting based on states in the US might come in handy in some cases.