How to completely exclude sub-rule from managed rule in AWS WAF v2?

Viewed 18

I trying to implement WAF protection at AWS and using WAS WAF v2.

What I need:

  1. Add custom responses when request is blocked
  2. Exclude payload body size check (SizeRestrictions_BODY) from AWS-AWSManagedRulesCommonRuleSet rule
  3. Block request if any other check is positive

What I tried:

Here is JSON of my example WEB ACL:

{
  "Name": "example",
  "Id": "uuiduuid-uuid-uuid-uuiduuid",
  "ARN": "arn:aws:wafv2:ap-northeast-1:0123456789:regional/webacl/example/uuiduuid-uuid-uuid-uuiduuid",
  "DefaultAction": {
    "Allow": {}
  },
  "Description": "WAF example",
  "Rules": [
    {
      "Name": "AWS-AWSManagedRulesAmazonIpReputationList",
      "Priority": 0,
      "Statement": {
        "ManagedRuleGroupStatement": {
          "VendorName": "AWS",
          "Name": "AWSManagedRulesAmazonIpReputationList"
        }
      },
      "OverrideAction": {
        "Count": {}
      },
      "VisibilityConfig": {
        "SampledRequestsEnabled": false,
        "CloudWatchMetricsEnabled": false,
        "MetricName": "AWS-AWSManagedRulesAmazonIpReputationList"
      }
    },
    {
      "Name": "AWS-AWSManagedRulesCommonRuleSet",
      "Priority": 1,
      "Statement": {
        "ManagedRuleGroupStatement": {
          "VendorName": "AWS",
          "Name": "AWSManagedRulesCommonRuleSet",
          "ExcludedRules": [
            {
              "Name": "SizeRestrictions_BODY"
            }
          ]
        }
      },
      "OverrideAction": {
        "Count": {}
      },
      "VisibilityConfig": {
        "SampledRequestsEnabled": false,
        "CloudWatchMetricsEnabled": false,
        "MetricName": "AWS-AWSManagedRulesCommonRuleSet"
      }
    },
    {
      "Name": "BlockLabeledRequests",
      "Priority": 2,
      "Statement": {
        "OrStatement": {
          "Statements": [
            {
              "LabelMatchStatement": {
                "Scope": "NAMESPACE",
                "Key": "awswaf:managed:aws:"
              }
            },
            {
              "NotStatement": {
                "Statement": {
                  "LabelMatchStatement": {
                    "Scope": "LABEL",
                    "Key": "awswaf:managed:aws:core-rule-set:SizeRestrictions_Body"
                  }
                }
              }
            }
          ]
        }
      },
      "Action": {
        "Block": {
          "CustomResponse": {
            "ResponseCode": 499,
            "CustomResponseBodyKey": "custom-response-body",
            "ResponseHeaders": [
              {
                "Name": "x-custom-header",
                "Value": "hello-world"
              }
            ]
          }
        }
      },
      "VisibilityConfig": {
        "SampledRequestsEnabled": false,
        "CloudWatchMetricsEnabled": false,
        "MetricName": "BlockLabeledRequests"
      }
    }
  ],
  "VisibilityConfig": {
    "SampledRequestsEnabled": false,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "waf-example"
  },
  "Capacity": 727,
  "ManagedByFirewallManager": false,
  "LabelNamespace": "awswaf:0123456789:webacl:example:",
  "CustomResponseBodies": {
    "custom-response-body": {
      "ContentType": "APPLICATION_JSON",
      "Content": "{\n  \"error\": \"oops, something wrong\"\n}"
    }
  }
}

What is happening here:

  1. Request go through AWSManagedRulesAmazonIpReputationList rule. If this check is not passed (positive) awswaf:managed:aws:rule-set-name:rule-name label will be added.
  2. Because of default action overridden to Count request go to next rule in any way. (Why I can't block bad request immediately? Because default block action of the rule returning standard response, but I have to customize it. And that is not possible to override Block response. Only Count may be overridden. And that is stupid limitation N1.)
  3. Request go through AWS-AWSManagedRulesCommonRuleSet rule and even if SizeRestrictions_BODY's action overridden to Count, the rule still adding own label awswaf:managed:aws:core-rule-set:SizeRestrictions_Body to request but not blocks it (It is not possible to disable rule at all, at least Count should be triggered. Stupid limitation N2.)
  4. Rule set action overridden to Count, so request goes to final rule
  5. Final rule BlockLabeledRequests checks if any label starting from awswaf:managed:aws: exists in request and blocks it if YES. But SizeRestrictions_Body adding own label starting from awswaf:managed:aws: and that makes impossible to use awswaf:managed:aws: existence check. Because of it I set two conditions: Request will be blocked if has label starting from awswaf:managed:aws: or doesn't have label awswaf:managed:aws:core-rule-set:SizeRestrictions_Body. In most cases it working correct, but if we add to request big sized payload SizeRestrictions_Body will be triggered and request will be passed even if we have another rules triggered, and that is a security hole. WAF if statements logic is pretty dumb and only one possible way to exclude SizeRestrictions_Body is to check all awswaf:managed:aws:rule-set-name:rule-name one by one with if and statement and exclude SizeRestrictions_Body from it. But it is inconvenient because number of rules is pretty big. (stupid limitation N3.)

QUESTION: So is here any way to set thing What I need by any another logic? Or just exclude only awswaf:managed:aws:core-rule-set:SizeRestrictions_Body label check but use wildcard label check awswaf:managed:aws: at same time? Or may be here is some way to force remove awswaf:managed:aws:core-rule-set:SizeRestrictions_Body label from request before label checking?

AWS WAF limitations making it pretty useless

0 Answers
Related