AWS WAFWeb Application FirewallDDoSSecurity MonitoringCloudFront

AWS WAF Monitoring: Detecting and Responding to Web Application Attacks

Vigilare Engineering

Platform Team · January 22, 2026 · 10 min read

AWS WAF: More Than Just a Checkbox

Many teams enable AWS WAF because a compliance checklist requires it, then forget about it. They turn on the AWS Managed Rules, set up a CloudWatch dashboard, and move on. This is better than nothing, but it misses most of the value that WAF can provide when you're actually monitoring it.

A properly monitored WAF gives you a real-time view of the attacks hitting your application: what types, from where, and at what volume. That visibility lets you tune your rules, identify targeted attacks before they succeed, and respond to emerging threats faster. This guide covers the monitoring setup that makes WAF actually useful as a security tool.

WAF Architecture: Where It Fits

AWS WAF can be attached to:

  • CloudFront distributions — Global protection, evaluated at edge locations
  • Application Load Balancers — Regional protection for EC2 and container workloads
  • API Gateway stages — REST API protection (see our API Gateway security guide)
  • AppSync GraphQL APIs
  • Cognito User Pools — Protect authentication endpoints
  • App Runner services

For applications that use CloudFront, attach WAF at the CloudFront level for global coverage. For applications that bypass CloudFront, attach WAF at the ALB level. See our CloudFront security guide for the full architecture.

Rule Groups and What They Protect Against

AWS WAF rules are organized into rule groups. The AWS Managed Rule Groups are maintained by Amazon and updated automatically when new attack patterns emerge:

Core Rule Set (CRS)

Protects against the OWASP Top 10: SQL injection, XSS, SSRF, request smuggling, and similar attacks. This should be enabled for every public web application. The rule group blocks obvious attack patterns in headers, query strings, and request bodies.

Known Bad Inputs

Blocks request patterns associated with exploitation of log4j (Log4Shell), Spring Framework vulnerabilities, and other publicly known CVEs. Particularly valuable during the period immediately after a vulnerability disclosure when your application may not yet be patched.

IP Reputation List

Blocks IPs associated with botnets, scanners, and known malicious actors. This is one of the highest-signal rule groups — legitimate traffic rarely comes from these IPs.

Bot Control

Distinguishes between legitimate bots (Googlebot, Bingbot) and malicious scrapers, credential stuffers, and automated vulnerability scanners. Requires additional configuration to allowlist legitimate bots. The managed version handles detection; you configure the response (block, challenge, count).

Anonymous IP List

Blocks requests from TOR exit nodes, anonymizing proxies, and hosting provider IPs. For most consumer-facing applications, blocking TOR reduces fraud with minimal legitimate traffic impact. For some security-conscious audiences (journalists, activists), this may not be appropriate.

Enabling WAF Logging

By default, WAF doesn't log anything — you see only CloudWatch metrics. Logging is essential for understanding what's being blocked, tuning rules, and investigating incidents. Enable WAF logging to Kinesis Firehose, which can deliver logs to S3, OpenSearch, or Splunk:

resource "aws_wafv2_web_acl_logging_configuration" "waf_logging" {
  log_destination_configs = [aws_kinesis_firehose_delivery_stream.waf_logs.arn]
  resource_arn            = aws_wafv2_web_acl.main.arn

  logging_filter {
    default_behavior = "KEEP"
    filter {
      behavior = "DROP"
      condition {
        action_condition {
          action = "ALLOW"
        }
      }
      requirement = "MEETS_ALL"
    }
  }
}

The logging filter above keeps only blocked and counted requests, not allowed traffic. For security monitoring purposes, this is usually sufficient and significantly reduces log volume.

Key Metrics to Monitor

WAF publishes the following CloudWatch metrics:

  • AllowedRequests — Total requests that passed all rules
  • BlockedRequests — Total requests that matched a block rule
  • CountedRequests — Requests matching rules in count mode
  • PassedRequests — Requests that didn't match any rule

Per-rule metrics let you see which rules are firing. Create CloudWatch alarms on:

  • Significant spike in BlockedRequests — active attack
  • BlockedRequests percentage increase — ratio of blocked to allowed traffic rising
  • Specific high-severity rules firing (SQL injection, Log4Shell) — targeted attack

Analyzing WAF Logs with Athena

For detailed analysis of WAF events, Athena is the most flexible tool. Query WAF logs stored in S3 using SQL. Example table definition:

CREATE EXTERNAL TABLE waf_logs (
  timestamp bigint,
  formatversion int,
  webaclid string,
  terminatingruleid string,
  terminatingruletype string,
  action string,
  httprequest struct<
    clientip:string,
    country:string,
    headers:array<struct<name:string,value:string>>,
    uri:string,
    args:string,
    httpmethod:string
  >
)
PARTITIONED BY (year string, month string, day string)
STORED AS PARQUET
LOCATION 's3://your-bucket/waf-logs/';

Useful WAF Log Queries

Top blocked IPs:

SELECT httprequest.clientip, COUNT(*) as blocks
FROM waf_logs
WHERE action = 'BLOCK'
  AND year = '2026' AND month = '08'
GROUP BY httprequest.clientip
ORDER BY blocks DESC
LIMIT 20;

SQL injection attempts by country:

SELECT httprequest.country, COUNT(*) as attempts
FROM waf_logs
WHERE terminatingruleid LIKE '%SQLi%'
GROUP BY httprequest.country
ORDER BY attempts DESC;

Blocked requests over time:

SELECT date_trunc('hour', from_unixtime(timestamp/1000)) as hour,
       terminatingruleid,
       COUNT(*) as count
FROM waf_logs
WHERE action = 'BLOCK'
GROUP BY 1, 2
ORDER BY 1 DESC;

Custom WAF Rules for Application-Specific Protection

Managed rules cover common patterns, but your application has unique characteristics that warrant custom rules. Examples:

Rate Limiting by IP

resource "aws_wafv2_rule_group" "rate_limit" {
  rule {
    name     = "RateLimitByIP"
    priority = 1
    action {
      block {}
    }
    statement {
      rate_based_statement {
        limit              = 2000
        aggregate_key_type = "IP"
      }
    }
  }
}

Geographic Restrictions

If your application serves only specific regions, blocking all other countries dramatically reduces attack surface. A startup serving only US customers can block traffic from high-abuse-rate countries with minimal legitimate traffic impact.

Header Validation

If your application requires a specific header (a custom API version header, a partner identifier), block requests that don't include it. This raises the cost of automated attacks that don't know your application's protocol.

WAF and GuardDuty Integration

GuardDuty and WAF see different threat signals — WAF sees HTTP-level attacks, GuardDuty sees network and API-level patterns. They complement each other. A common pattern: when GuardDuty detects a malicious IP making API calls, automatically add that IP to a WAF IP block list:

  • GuardDuty finding triggers EventBridge rule
  • EventBridge invokes Lambda with the malicious IP
  • Lambda adds the IP to a WAF IP set used in a block rule

This automated feedback loop can block attackers at the WAF layer before they escalate from reconnaissance to exploitation. See our GuardDuty findings guide for the threat detection context.

False Positives: The WAF Tuning Challenge

WAF managed rules can block legitimate traffic — a customer submitting code in a form triggering the SQL injection rule, for example. Managing false positives is an ongoing process:

  1. Start rules in count mode, not block mode, for 1-2 weeks
  2. Analyze counted requests in WAF logs to identify false positives
  3. Add exception rules for legitimate patterns before switching to block mode
  4. Monitor blocked request rates after enabling block mode for unexpected spikes

Never just switch all rules to block mode immediately — you risk breaking legitimate workflows and causing user support escalations.

WAF Scope-Down Statements

For performance-sensitive applications, WAF's inspection of every request can add latency. Scope-down statements restrict when a rule applies, reducing unnecessary inspection:

# Only inspect requests to the API, not static assets
statement {
  and_statement {
    statement {
      sqli_match_statement { ... }
    }
    statement {
      byte_match_statement {
        field_to_match { uri_path {} }
        positional_constraint = "STARTS_WITH"
        search_string         = "/api/"
      }
    }
  }
}

FAQ

How much does WAF cost?

WAF pricing is $5/month per Web ACL, $1/month per rule, and $0.60 per million requests inspected. Managed rule groups add $1-10/month each. For a typical small application with 10M requests/month and 5 rule groups, expect $20-50/month. Bot Control and Fraud Control are significantly more expensive.

Does WAF protect against DDoS?

WAF provides application-layer (L7) rate limiting, which mitigates some DDoS patterns. For volumetric DDoS protection, you need AWS Shield Standard (free, always on) or Shield Advanced ($3,000/month). CloudFront also absorbs significant DDoS volume at the edge before it reaches your origin.

Should I use WAF on every application?

For any application with user input accessible over the internet, yes. The cost is low relative to the protection provided. Internal applications behind IAM or VPN don't typically need WAF.

Protect your AWS accounts before it's too late

Vigilare monitors your AWS accounts for suspension risks — billing anomalies, IAM issues, GuardDuty findings, and more — and alerts you before AWS takes action.

Written by Vigilare Engineering

Platform Team