Skip to main content
SecurityNovember 2, 20258 min read

AWS WAF Configuration for Web Application Security

Get technical support

Which of these can actually be exploited?

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.

Or read how we handle it in Security & Compliance.

Related Articles

Security

How to Give Applications AWS Credentials Without Storing Any

Every long-lived access key in your account is a copy waiting to leak, and no amount of rotation discipline fixes that. The alternative is to have no key at all, because each place an application normally needs credentials already has a mechanism that hands it fresh ones on demand. This walks through instance profiles on EC2, task roles on ECS, EKS Pod Identity and IRSA on Kubernetes, and OIDC federation for a CI pipeline, with the trust policy shape for each. It also covers the one condition in the CI trust policy that decides whether the whole thing is secure or theatre.

Security

A cPanel Account With Email Access Can Reach Root, and Every Supported Version Is Affected

CVE-2026-67401 lets an authenticated cPanel account holder with mail privileges create arbitrary files and run code as root. cPanel lists all supported versions as affected and has shipped patched builds. The precondition is an ordinary customer account, which on a hosting platform anyone can buy.

Security

How to Kill Password SSH Across a Fleet, Once

Password authentication on SSH is the single setting that turns a leaked or guessed credential into a shell. Turning it off is five lines of config; doing it across a fleet without locking yourself out is the part that needs an order. This is that order, including the check that proves keys work before you disable the fallback, why AuthenticationMethods beats PasswordAuthentication alone, and how to leave one deliberate way back in.