Skip to main content
Back to Articles
SecurityNovember 2, 20258 min read

AWS WAF Configuration for Web Application Security

Deploy and configure AWS WAF with managed rule groups, custom rules, rate limiting, and bot control to protect web applications from common threats.

The Modern Threat Landscape

Web applications face a constant barrage of automated attacks: SQL injection, cross-site scripting, credential stuffing, and application-layer DDoS. AWS WAF provides a managed web application firewall that inspects HTTP requests before they reach your application, blocking malicious traffic at the edge.

This guide covers production-grade WAF configuration patterns that we deploy as part of our security and compliance services.

Architecture Overview

AWS WAF integrates with three AWS services:

  • CloudFront — Global edge protection for static and dynamic content
  • Application Load Balancer — Regional protection for backend services
  • API Gateway — Protection for REST and WebSocket APIs

For maximum coverage, deploy WAF on CloudFront for public-facing traffic and on the ALB for API traffic that bypasses the CDN.

Web ACL Configuration

A Web ACL (Access Control List) contains rules evaluated in priority order. Each rule either allows, blocks, or counts matching requests.

Creating the Web ACL

aws wafv2 create-web-acl \
  --name production-web-acl \
  --scope CLOUDFRONT \
  --region us-east-1 \
  --default-action Allow={} \
  --rules file://waf-rules.json \
  --visibility-config \
    SampledRequestsEnabled=true,\
    CloudWatchMetricsEnabled=true,\
    MetricName=ProductionWebACL

Managed Rule Groups

AWS provides curated rule groups that cover OWASP Top 10 vulnerabilities. Start with these four:

Core Rule Set

{
  "Name": "AWS-AWSManagedRulesCommonRuleSet",
  "Priority": 1,
  "Statement": {
    "ManagedRuleGroupStatement": {
      "VendorName": "AWS",
      "Name": "AWSManagedRulesCommonRuleSet",
      "ExcludedRules": [
        { "Name": "SizeRestrictions_BODY" }
      ]
    }
  },
  "OverrideAction": { "None": {} },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "CommonRuleSet"
  }
}

Exclude SizeRestrictions_BODY if your application accepts file uploads or large JSON payloads. Add it back with a custom size limit rule.

SQL Injection Protection

{
  "Name": "AWS-AWSManagedRulesSQLiRuleSet",
  "Priority": 2,
  "Statement": {
    "ManagedRuleGroupStatement": {
      "VendorName": "AWS",
      "Name": "AWSManagedRulesSQLiRuleSet"
    }
  },
  "OverrideAction": { "None": {} },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "SQLiRuleSet"
  }
}

Known Bad Inputs and Bot Control

Add AWSManagedRulesKnownBadInputsRuleSet (priority 3) for Log4j, SSRF, and other known exploits. Add AWSManagedRulesBotControlRuleSet (priority 4) to identify and manage bot traffic.

Custom Rate Limiting Rules

Managed rules catch known attack patterns, but you also need rate limiting for brute force and DDoS protection:

{
  "Name": "RateLimitPerIP",
  "Priority": 0,
  "Statement": {
    "RateBasedStatement": {
      "Limit": 2000,
      "AggregateKeyType": "IP",
      "ScopeDownStatement": {
        "NotStatement": {
          "Statement": {
            "IPSetReferenceStatement": {
              "ARN": "arn:aws:wafv2:us-east-1:123456789:global/ipset/trusted-ips/abc123"
            }
          }
        }
      }
    }
  },
  "Action": { "Block": {} },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "RateLimitPerIP"
  }
}

This blocks any IP that makes more than 2,000 requests in a 5-minute window, excluding trusted IPs (monitoring services, internal systems).

Login Endpoint Protection

Apply stricter rate limits to authentication endpoints:

{
  "Name": "LoginRateLimit",
  "Priority": 5,
  "Statement": {
    "RateBasedStatement": {
      "Limit": 100,
      "AggregateKeyType": "IP",
      "ScopeDownStatement": {
        "ByteMatchStatement": {
          "SearchString": "/api/auth/login",
          "FieldToMatch": { "UriPath": {} },
          "TextTransformations": [
            { "Priority": 0, "Type": "LOWERCASE" }
          ],
          "PositionalConstraint": "STARTS_WITH"
        }
      }
    }
  },
  "Action": { "Block": {} },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "LoginRateLimit"
  }
}

Geo-Blocking

If your application only serves specific regions, block traffic from countries where you have no customers:

{
  "Name": "GeoBlock",
  "Priority": 6,
  "Statement": {
    "GeoMatchStatement": {
      "CountryCodes": ["CN", "RU", "KP"]
    }
  },
  "Action": { "Block": {} }
}

Use this cautiously — legitimate users behind VPNs may be blocked. Consider counting instead of blocking initially to assess impact.

Logging and Monitoring

Enable WAF logging to S3 for analysis and compliance:

aws wafv2 put-logging-configuration \
  --logging-configuration \
    ResourceArn=arn:aws:wafv2:us-east-1:123456789:global/webacl/production-web-acl/abc123,\
    LogDestinationConfigs=arn:aws:s3:::waf-logs-production

CloudWatch Alarms

Set up alarms for blocked request spikes:

aws cloudwatch put-metric-alarm \
  --alarm-name WAF-BlockedRequests-High \
  --metric-name BlockedRequests \
  --namespace AWS/WAFV2 \
  --statistic Sum \
  --period 300 \
  --threshold 1000 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2 \
  --alarm-actions arn:aws:sns:us-east-1:123456789:security-alerts

Deployment Best Practices

  • Deploy new rules in Count mode first. Analyze sampled requests for false positives over 48-72 hours before switching to Block mode.
  • Maintain a trusted IP set for monitoring services, partner APIs, and internal systems.
  • Review WAF logs weekly and tune rules based on actual traffic patterns.
  • Use AWS Firewall Manager to deploy consistent WAF policies across multiple accounts in an AWS Organization.
  • Integrate WAF metrics into your infrastructure monitoring dashboards for real-time visibility.

Testing Your WAF

Validate rules with controlled tests before relying on them in production:

# Test SQL injection blocking
curl -v "https://example.com/api/search?q=1' OR '1'='1"

# Test rate limiting
for i in $(seq 1 2100); do
  curl -s -o /dev/null -w "%{http_code}\n" https://example.com/api/health
done | sort | uniq -c

A well-configured WAF blocks the vast majority of automated attacks before they reach your application code, significantly reducing your attack surface.

Need help with this?

Our team handles this kind of work daily. Let us take care of your infrastructure.