AWS WAF Classic Regional Rule Has at Least One Condition
Overview
This check verifies that your AWS WAF Classic Regional rules have at least one condition (also called a "predicate") attached. Conditions define what traffic the rule evaluates -- without them, a rule cannot match any requests and provides no protection.
Note: This check applies to AWS WAF Classic (Regional). AWS recommends migrating to AWS WAF v2, which offers a unified API for both regional and global resources.
Risk
Rules without conditions create security gaps because they cannot match traffic effectively. This can lead to:
- Data exposure: Without proper filtering, malicious requests may reach your application
- Injection attacks: Missing SQL injection or XSS detection conditions leave your application vulnerable
- Denial of service: Without rate limiting or size restrictions, your application may be overwhelmed
Empty rules are often placeholder configurations that were never completed, leaving your web applications unprotected.
Remediation Steps
Prerequisites
You need:
- AWS Console access with permissions to modify WAF Classic resources
- Knowledge of which traffic patterns you want to filter (IP addresses, request patterns, geographic regions, etc.)
AWS Console Method
- Open the AWS WAF Console
- In the navigation pane, choose Rules under "AWS WAF Classic"
- Select the rule that has no conditions
- Click Edit rule
- Under Add conditions, select the type of condition to add:
- IP match - Block or allow specific IP addresses
- String match - Match patterns in request headers, body, or URI
- Regex match - Use regular expressions for pattern matching
- Geographic match - Filter by country of origin
- Size constraint - Limit request size
- SQL injection match - Detect SQL injection attempts
- XSS match - Detect cross-site scripting attempts
- Select an existing condition or create a new one
- Click Add condition
- Click Update to save the rule
AWS CLI (optional)
First, list your WAF Regional rules to find the rule ID:
aws waf-regional list-rules --region us-east-1
Get details about a specific rule to see its current conditions:
aws waf-regional get-rule \
--rule-id <your-rule-id> \
--region us-east-1
To add a condition, you first need to create the condition resource (like an IP set), then add it to the rule. Here is an example adding an IP match condition:
Step 1: Create an IP Set (if you do not have one)
# Get a change token
CHANGE_TOKEN=$(aws waf-regional get-change-token \
--region us-east-1 \
--query ChangeToken --output text)
# Create the IP set
aws waf-regional create-ip-set \
--name "BlockedIPs" \
--change-token "$CHANGE_TOKEN" \
--region us-east-1
Step 2: Add IP addresses to the IP Set
CHANGE_TOKEN=$(aws waf-regional get-change-token \
--region us-east-1 \
--query ChangeToken --output text)
aws waf-regional update-ip-set \
--ip-set-id <your-ipset-id> \
--change-token "$CHANGE_TOKEN" \
--updates '[{"Action":"INSERT","IPSetDescriptor":{"Type":"IPV4","Value":"192.0.2.0/24"}}]' \
--region us-east-1
Step 3: Add the IP Set as a condition to your rule
CHANGE_TOKEN=$(aws waf-regional get-change-token \
--region us-east-1 \
--query ChangeToken --output text)
aws waf-regional update-rule \
--rule-id <your-rule-id> \
--change-token "$CHANGE_TOKEN" \
--updates '[{"Action":"INSERT","Predicate":{"Negated":false,"Type":"IPMatch","DataId":"<your-ipset-id>"}}]' \
--region us-east-1
Replace:
<your-rule-id>with your WAF rule ID<your-ipset-id>with the IP set ID from step 1
CloudFormation (optional)
This template creates a WAF Regional rule with an IP match condition:
AWSTemplateFormatVersion: '2010-09-09'
Description: WAF Regional Rule with IP Match Condition
Parameters:
RuleName:
Type: String
Default: MyWAFRule
Description: Name for the WAF rule
Resources:
# IP Set to use as a condition
ExampleIPSet:
Type: AWS::WAFRegional::IPSet
Properties:
Name: example-ipset
IPSetDescriptors:
- Type: IPV4
Value: 192.0.2.0/24
# WAF Regional Rule with the IP Match condition
ExampleWAFRule:
Type: AWS::WAFRegional::Rule
Properties:
Name: !Ref RuleName
MetricName: ExampleWAFRuleMetric
Predicates:
- DataId: !Ref ExampleIPSet
Negated: false
Type: IPMatch
Outputs:
RuleId:
Description: The ID of the WAF Regional Rule
Value: !Ref ExampleWAFRule
IPSetId:
Description: The ID of the IP Set
Value: !Ref ExampleIPSet
Deploy with:
aws cloudformation deploy \
--template-file template.yaml \
--stack-name waf-rule-with-conditions \
--region us-east-1
Terraform (optional)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
# Example IP Set for the rule condition
resource "aws_wafregional_ipset" "example" {
name = "example-ipset"
ip_set_descriptor {
type = "IPV4"
value = "192.0.2.0/24"
}
}
# WAF Regional Rule with a condition (predicate)
resource "aws_wafregional_rule" "example" {
name = "example-rule"
metric_name = "exampleRule"
predicate {
data_id = aws_wafregional_ipset.example.id
negated = false
type = "IPMatch"
}
}
Apply with:
terraform init
terraform apply
Verification
After adding conditions to your rule:
- Return to the WAF Classic Console > Rules
- Select your rule and confirm it shows one or more conditions listed
- Re-run the Prowler check to confirm it passes:
prowler aws --check waf_regional_rule_with_conditions
Additional Resources
- AWS WAF Classic Developer Guide
- Working with Rules in AWS WAF Classic
- Migrating from AWS WAF Classic to AWS WAF v2
- AWS WAF Pricing
Notes
- Migration recommended: AWS WAF Classic is a legacy service. Consider migrating to AWS WAF v2, which provides a unified API, better rule management, and new features like managed rule groups.
- Multiple conditions: If a rule has multiple conditions, a request must match ALL conditions to trigger the rule action. Design your rules accordingly.
- Condition types: Choose the right condition type for your use case -- IP match for blocking known bad actors, SQL injection match for database protection, XSS match for script injection protection.
- Testing: Before deploying rules to production, test them in "Count" mode first to see what traffic would be affected without actually blocking requests.