How to use a custom block action for AWS managed rules in WAFv2

0

Hi, I created a WAF WebACL with two rules.

The first rule named ${AWS::StackName}-WebACL-Rule1 blocks requests with User-Agent header set to BotAgent and returns the custom JSON response named Forbidden with 403 HTTP status and response body { "message": "403 Forbidden" }.

The second rule named ${AWS::StackName}-WebACL-Rule2 blocks requests that match AWSManagedRulesAnonymousIpList and is supposed to return the same 403 response as the first one.

Here's my WebACL configuration written in CloudFormation template:

Resources:
  WebACL:
    Type: AWS::WAFv2::WebACL
    Properties:
      Name:
        Fn::Sub: ${AWS::StackName}-WebACL
      Description: My CloudFront Web ACL
      DefaultAction:
        Allow: {}
      VisibilityConfig:
        SampledRequestsEnabled: true
        CloudWatchMetricsEnabled: true
        MetricName:
          Fn::Sub: ${AWS::StackName}-WebACL
      Scope: CLOUDFRONT
      CustomResponseBodies:
        Forbidden:
          ContentType: APPLICATION_JSON
          Content: '{ "message": "403 Forbidden" }'
      Rules:
        - Name:
            Fn::Sub: ${AWS::StackName}-WebACL-Rule1
          Priority: 0
          Action:
            Block:
              CustomResponse:
                ResponseCode: 403
                CustomResponseBodyKey: Forbidden
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName:
              Fn::Sub: ${AWS::StackName}-WebACL-Rule1
          Statement:
            ByteMatchStatement:
              FieldToMatch:
                SingleHeader:
                  Name: User-Agent
              PositionalConstraint: EXACTLY
              SearchString: BotAgent
              TextTransformations:
                - Priority: 0
                  Type: NONE
        - Name:
            Fn::Sub: ${AWS::StackName}-WebACL-Rule2
          Priority: 1
          OverrideAction:
            None: {}
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName:
              Fn::Sub: ${AWS::StackName}-WebACL-Rule2
          Statement:
            ManagedRuleGroupStatement:
              Name: AWSManagedRulesAnonymousIpList
              VendorName: AWS
              RuleActionOverrides:
                - Name: AnonymousIPList
                  ActionToUse:
                    Block:
                      CustomResponse:
                        ResponseCode: 403
                        CustomResponseBodyKey: Forbidden
                - Name: HostingProviderIPList
                  ActionToUse:
                    Block:
                      CustomResponse:
                        ResponseCode: 403
                        CustomResponseBodyKey: Forbidden

I attached this WebACL to my CloudFront distribution and tested this WebACL with curl command with NordVPN connection turned on.

$ curl -H "User-Agent: BotAgent" -isSL http://d32jyfppz17k8f.cloudfront.net/index.html
HTTP/1.1 403 Forbidden
Server: CloudFront
Date: Sat, 30 Sep 2023 07:22:34 GMT
Content-Length: 30
Connection: keep-alive
Content-Type: application/json
X-Cache: Error from cloudfront
Via: 1.1 7813c3b749fe8e3a44c4359da4183e70.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: NRT57-P4
X-Amz-Cf-Id: 8u1RX4Fo2touzwz8Pw6kfq5YKA1y98EnFXcLcUh2Wadfq54xPqeGmA==

{ "message": "403 Forbidden" }
$ curl -isSL http://d32jyfppz17k8f.cloudfront.net/index.html
HTTP/1.1 403 Forbidden
Server: CloudFront
Date: Sat, 30 Sep 2023 07:22:59 GMT
Content-Type: text/html
Content-Length: 919
Connection: keep-alive
X-Cache: Error from cloudfront
Via: 1.1 12632bbc89afe55228d7f1ab9e5993a6.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: NRT57-C3
X-Amz-Cf-Id: MbOyYmJpH8B601nrPeVY1eriKbaTxFC8d-6h5B-ZNH4vCHXORiLORg==

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>403 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Request blocked.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: MbOyYmJpH8B601nrPeVY1eriKbaTxFC8d-6h5B-ZNH4vCHXORiLORg==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>

The first curl command returns the custom 403 response as expected since it matches the first WebACL rule. The second curl command matches the second WebACL rule (since NordVPN is activated), but it doesn't return the custom response which I configured.

It is possible to override the AWS managed rule to Count action if I changed the configuration as follows so that the requests from NordVPN connected environment will never be blocked.

                         CustomResponseBodyKey: Forbidden
                 - Name: HostingProviderIPList
                   ActionToUse:
-                    Block:
-                      CustomResponse:
-                        ResponseCode: 403
-                        CustomResponseBodyKey: Forbidden
+                    Count: {}

How can I override an action from AWS managed rules to a Block action with a custom response?

profile picture
HS
asked 9 months ago548 views
1 Answer
1
Accepted Answer

Hello.

I think this blog will be helpful.
https://dev.classmethod.jp/articles/tsnote-waf-managedrule-customresponse/

The managed rule section should be set to count and another rule added to return a custom response.

profile picture
EXPERT
answered 9 months ago
profile picture
EXPERT
reviewed a month ago
  • Thanks you for the very helpful post! I've successfully customized the block action with the following configurations.

    Resources:
      WebACL:
        Type: AWS::WAFv2::WebACL
        Properties:
          # ...
          Rules:
            # ...
            - Name:
                Fn::Sub: ${AWS::StackName}-WebACL-Rule2
              Priority: 2
              OverrideAction:
                Count: {}
              VisibilityConfig:
                SampledRequestsEnabled: true
                CloudWatchMetricsEnabled: true
                MetricName:
                  Fn::Sub: ${AWS::StackName}-WebACL-Rule2
              Statement:
                ManagedRuleGroupStatement:
                  Name: AWSManagedRulesAnonymousIpList
                  VendorName: AWS
            - Name:
                Fn::Sub: ${AWS::StackName}-WebACL-Rule3
              Priority: 3
              Action:
                Block:
                  CustomResponse:
                    ResponseCode: 403
                    CustomResponseBodyKey: Forbidden
              VisibilityConfig:
                SampledRequestsEnabled: true
                CloudWatchMetricsEnabled: true
                MetricName:
                  Fn::Sub: ${AWS::StackName}-WebACL-Rule3
              Statement:
                LabelMatchStatement:
                  Scope: NAMESPACE
                  Key: "awswaf:managed:aws:anonymous-ip-list:"

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions