← Back to Tutorials
Tutorial 09 Intermediate

How to Block SQL Injection & Web Attacks with AWS WAF

Web applications are the primary target for cyber attacks. Learn how to protect your applications with AWS WAF's managed rules, rate limiting, and real-time monitoring.

20 min implementation
12 min read
Application Security

Why Web Application Attacks Are Devastating

Web applications are the primary target for the majority of cyber attacks. Unlike infrastructure attacks that may affect systems, web application attacks directly access your most sensitive data—customer records, financial information, and intellectual property. A single SQL injection vulnerability can compromise your entire database.

⚠️
Critical: SQL injection attacks remain one of the most common and dangerous web vulnerabilities. Attackers inject malicious SQL code into web forms, exploiting poor input validation to access databases directly.

The Three Critical Attack Vectors AWS WAF Prevents

1

SQL Injection Attacks

Attackers inject malicious SQL code into web forms, exploiting poor input validation to access databases directly. This method has been used in major breaches to compromise hundreds of organizations and steal sensitive customer data.

Example SQL Injection Payload
' OR '1'='1' UNION SELECT username, password FROM users --
2

Cross-Site Scripting (XSS)

Malicious scripts injected into web pages execute in users' browsers, stealing session cookies, credentials, or performing unauthorized actions. Can lead to account takeovers and data theft.

3

Distributed Denial of Service (DDoS)

Overwhelming your applications with traffic to cause outages. Application-layer DDoS attacks are particularly dangerous because they mimic legitimate user behavior while consuming server resources.

1

Set Up AWS WAF with OWASP Protection

~8 minutes

AWS WAF provides pre-configured protection packs that include OWASP Top 10 protections, designed to block the most common web application attacks.

Prerequisites

  • An existing web application on CloudFront, Application Load Balancer, or API Gateway
  • AWS Console access with appropriate IAM permissions
  • Understanding of your application's normal traffic patterns

Console Steps

1.1 Access AWS WAF Console

  • Navigate to the AWS WAF console
  • Select your region (WAF is global for CloudFront, regional for ALB/API Gateway)
  • Click "Create web ACL"

1.2 Configure Web ACL Settings

  • Name: ProductionWebAppProtection
  • Resource type: Select "Regional resources" for ALB/API Gateway or "CloudFront distributions"
  • Associated AWS resources: Select your ALB, API Gateway, or CloudFront distribution
  • Click "Next"

1.3 Add AWS Managed Rules

  • Click "Add rules" → "Add managed rule groups"
  • Expand "AWS managed rule groups"
  • Enable AWS-AWSManagedRulesCommonRuleSet (Core Rule Set - XSS, path traversal)
  • Enable AWS-AWSManagedRulesSQLiRuleSet (SQL injection protection)
  • Enable AWS-AWSManagedRulesKnownBadInputsRuleSet (Known bad inputs)
  • Click "Add rules"
AWS CLI Alternative
# Create Web ACL with managed rules
aws wafv2 create-web-acl \
    --name "ProductionWebAppProtection" \
    --scope REGIONAL \
    --default-action Allow={} \
    --rules '[
        {
            "Name": "AWS-AWSManagedRulesCommonRuleSet",
            "Priority": 0,
            "Statement": {
                "ManagedRuleGroupStatement": {
                    "VendorName": "AWS",
                    "Name": "AWSManagedRulesCommonRuleSet"
                }
            },
            "OverrideAction": {"None": {}},
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "AWSManagedRulesCommonRuleSet"
            }
        },
        {
            "Name": "AWS-AWSManagedRulesSQLiRuleSet",
            "Priority": 1,
            "Statement": {
                "ManagedRuleGroupStatement": {
                    "VendorName": "AWS",
                    "Name": "AWSManagedRulesSQLiRuleSet"
                }
            },
            "OverrideAction": {"None": {}},
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "AWSManagedRulesSQLiRuleSet"
            }
        },
        {
            "Name": "AWS-AWSManagedRulesKnownBadInputsRuleSet",
            "Priority": 2,
            "Statement": {
                "ManagedRuleGroupStatement": {
                    "VendorName": "AWS",
                    "Name": "AWSManagedRulesKnownBadInputsRuleSet"
                }
            },
            "OverrideAction": {"None": {}},
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "AWSManagedRulesKnownBadInputsRuleSet"
            }
        }
    ]' \
    --visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=ProductionWebAppProtection \
    --region us-east-1
Protection Active: Your web application now has comprehensive OWASP protection including SQL injection, XSS, and other common attack vectors.
⚠️
Important: Test WAF rules in "Count" mode first in non-production environments to avoid blocking legitimate traffic. Monitor for 24-48 hours before switching to "Block" mode.
2

Configure Rate Limiting Rules

~4 minutes

Rate limiting prevents automated attacks and ensures application availability during traffic spikes. Configure limits based on your application's normal usage patterns.

Console Steps

2.1 Create General Rate-Based Rule

  • In your Web ACL, click "Add rules" → "Add my own rules and rule groups"
  • Select "Rate-based rule"
  • Name: GeneralRateLimit
  • Rate limit: 2000 requests
  • Evaluation window: 5 minutes (300 seconds)
  • Request aggregation: Source IP address
  • Action: Block
  • Click "Add rule"

2.2 Create Login Protection Rule

  • Add another rate-based rule
  • Name: LoginProtection
  • Rate limit: 50 requests
  • Evaluation window: 5 minutes (300 seconds)
  • Scope of inspection: "Only consider requests that match the criteria in a rule statement"
  • Statement: URI path contains /login
  • Action: Block
Rate Limiting Rule Configuration (JSON)
{
    "Name": "LoginProtection",
    "Priority": 5,
    "Statement": {
        "RateBasedStatement": {
            "Limit": 50,
            "EvaluationWindowSec": 300,
            "AggregateKeyType": "IP",
            "ScopeDownStatement": {
                "ByteMatchStatement": {
                    "SearchString": "/login",
                    "FieldToMatch": {"UriPath": {}},
                    "TextTransformations": [
                        {"Priority": 0, "Type": "LOWERCASE"}
                    ],
                    "PositionalConstraint": "CONTAINS"
                }
            }
        }
    },
    "Action": {"Block": {}},
    "VisibilityConfig": {
        "SampledRequestsEnabled": true,
        "CloudWatchMetricsEnabled": true,
        "MetricName": "LoginProtection"
    }
}
💡
Pro Tip: AWS WAF now supports rate limits as low as 10 requests per evaluation window. For sensitive endpoints like login pages, consider lower thresholds to protect against credential stuffing attacks.
DDoS Protection: Your application is now protected against both volumetric and application-layer DDoS attacks with intelligent rate limiting.
3

Implement Geographic Blocking

~3 minutes

Geographic blocking helps reduce attack surface by restricting access from high-risk regions where your business doesn't operate.

Console Steps

3.1 Create Geographic Rule

  • In your Web ACL, click "Add rules" → "Add my own rules and rule groups"
  • Select "Rule builder"
  • Name: GeoBlocking
  • Type: "Regular rule"
  • Statement: "Originates from a country in"
  • Select countries to block based on your threat intelligence
  • Action: Block

3.2 Create Allow List for Trusted IPs

  • Go to "IP sets" in the WAF console
  • Create a new IP set: TrustedIPAddresses
  • Add your office IPs, VPN endpoints, and trusted partners
  • Create a rule to allow these IPs with higher priority than the geo-blocking rule
Geographic Blocking Rule (AWS CLI)
# Add geographic blocking rule to existing Web ACL
# Note: Replace YOUR_WEB_ACL_ID and YOUR_LOCK_TOKEN with actual values

aws wafv2 update-web-acl \
    --name "ProductionWebAppProtection" \
    --scope REGIONAL \
    --id YOUR_WEB_ACL_ID \
    --lock-token YOUR_LOCK_TOKEN \
    --default-action Allow={} \
    --rules '[
        {
            "Name": "GeoBlocking",
            "Priority": 10,
            "Statement": {
                "GeoMatchStatement": {
                    "CountryCodes": ["CN", "RU", "KP", "IR"]
                }
            },
            "Action": {"Block": {}},
            "VisibilityConfig": {
                "SampledRequestsEnabled": true,
                "CloudWatchMetricsEnabled": true,
                "MetricName": "GeoBlocking"
            }
        }
    ]' \
    --visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=ProductionWebAppProtection \
    --region us-east-1
⚠️
Business Consideration: Ensure geographic blocking doesn't conflict with legitimate business operations. Consider customer locations, partner access, and remote workers before implementing broad geographic restrictions.
4

Set Up Real-Time Monitoring

~5 minutes

Real-time monitoring enables immediate response to attacks and helps optimize WAF rules based on actual traffic patterns.

Console Steps

4.1 Enable WAF Logging

  • In the WAF console, select your Web ACL
  • Go to the "Logging and metrics" tab
  • Click "Enable logging"
  • Choose destination: CloudWatch Logs
  • Create log group: aws-waf-logs-production
  • Set retention period: 90 days (recommended for security compliance)

4.2 Create SNS Topic for Alerts

  • Navigate to Amazon SNS console
  • Create topic: WAF-Security-Alerts
  • Add subscriptions for your security team email addresses

4.3 Set Up CloudWatch Alarm

  • Navigate to CloudWatch console
  • Create alarm for blocked requests
  • Metric: BlockedRequests
  • Namespace: AWS/WAFV2
  • Threshold: Greater than 100 in 5 minutes
  • Action: Send notification to WAF-Security-Alerts topic
CloudWatch Alarm (AWS CLI)
# Create SNS topic for alerts
aws sns create-topic --name WAF-Security-Alerts

# Subscribe email to topic (replace with your email)
aws sns subscribe \
    --topic-arn arn:aws:sns:us-east-1:ACCOUNT_ID:WAF-Security-Alerts \
    --protocol email \
    --notification-endpoint security-team@yourcompany.com

# Create CloudWatch alarm
aws cloudwatch put-metric-alarm \
    --alarm-name "WAF-HighBlockedRequests" \
    --alarm-description "High number of blocked requests detected" \
    --metric-name BlockedRequests \
    --namespace AWS/WAFV2 \
    --statistic Sum \
    --period 300 \
    --threshold 100 \
    --comparison-operator GreaterThanThreshold \
    --dimensions Name=WebACL,Value=ProductionWebAppProtection Name=Region,Value=us-east-1 \
    --evaluation-periods 1 \
    --alarm-actions arn:aws:sns:us-east-1:ACCOUNT_ID:WAF-Security-Alerts
Complete Protection: Your web application now has enterprise-grade protection with real-time monitoring, automated alerting, and comprehensive logging for compliance and forensics.

Validate Your Configuration

Complete these checks to ensure your AWS WAF configuration is properly protecting your application:

Security Validation Script

Run this script to validate your WAF protection (only run against test environments):

Bash Script
#!/bin/bash
# AWS WAF Protection Validation Script
# WARNING: Only run against test environments!

APP_URL="https://your-test-app.example.com"

echo "Testing AWS WAF protection for $APP_URL"
echo "========================================="

# Test 1: SQL Injection Protection
echo ""
echo "Test 1: SQL injection protection..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$APP_URL/search?q=' OR '1'='1'--")
if [ "$RESPONSE" = "403" ]; then
    echo "✓ SQL injection blocked (HTTP 403)"
else
    echo "✗ SQL injection not blocked (HTTP $RESPONSE)"
fi

# Test 2: Path Traversal Protection
echo ""
echo "Test 2: Path traversal protection..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$APP_URL/../../../etc/passwd")
if [ "$RESPONSE" = "403" ]; then
    echo "✓ Path traversal blocked (HTTP 403)"
else
    echo "✗ Path traversal not blocked (HTTP $RESPONSE)"
fi

# Test 3: Check CloudWatch Metrics
echo ""
echo "Test 3: Checking CloudWatch metrics..."
METRICS=$(aws cloudwatch get-metric-statistics \
    --namespace AWS/WAFV2 \
    --metric-name BlockedRequests \
    --dimensions Name=WebACL,Value=ProductionWebAppProtection \
    --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
    --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
    --period 300 \
    --statistics Sum \
    --query 'Datapoints[0].Sum' \
    --output text 2>/dev/null)

if [ -n "$METRICS" ] && [ "$METRICS" != "None" ]; then
    echo "✓ CloudWatch metrics available (Blocked: $METRICS)"
else
    echo "! CloudWatch metrics not yet available"
fi

echo ""
echo "Validation complete! Check CloudWatch Logs for detailed results."

Common Mistakes to Avoid

Deploying to production without testing in Count mode first. Always test in non-production environments to identify false positives.

Setting rate limits too low, blocking legitimate users during peak traffic. Monitor baseline traffic patterns before setting thresholds.

Not excluding legitimate automated traffic (APIs, monitoring tools, health checks) from rate limiting rules.

Forgetting to enable logging, making incident investigation and optimization impossible.

Not regularly updating managed rule groups, missing protection against new attack vectors.

Overly broad geographic blocking that impacts traveling customers or VPN users. Consider customer locations before implementing restrictions.

Stop Managing WAF Rules Manually

Manually monitoring and tuning WAF rules is time-consuming and requires constant attention. AWSight automatically monitors your AWS environment against 500+ security best practices daily—including WAF configuration and effectiveness.

References