Skip to main content

Application Load Balancer Has WAF Web ACL Attached

Overview

This check verifies that your Application Load Balancers (ALBs) have an AWS WAF Web ACL attached. AWS WAF (Web Application Firewall) inspects incoming web traffic and blocks malicious requests before they reach your application.

Risk

Without a WAF Web ACL, your ALB accepts all incoming Layer 7 (HTTP/HTTPS) traffic without filtering. This exposes your application to:

  • SQL injection attacks that can steal or corrupt your data
  • Cross-site scripting (XSS) that can compromise user sessions
  • Bot attacks and credential stuffing that attempt to break into accounts
  • Denial of service attacks that can overwhelm your application

Attaching a WAF provides an essential layer of defense at the edge of your network.

Remediation Steps

Prerequisites

  • AWS Console access with permissions to modify WAF and ELBv2 resources
  • An existing WAF Web ACL (or you will create one during this process)
  • The Application Load Balancer you want to protect

AWS Console Method

  1. Open the AWS WAF Console

  2. Make sure you are in the us-east-1 region (or the region where your ALB is located)

  3. If you do not have a Web ACL yet:

    • Click Create web ACL
    • Enter a name (e.g., my-app-web-acl)
    • Select Regional resources as the resource type
    • Click Next and add rules as needed (AWS Managed Rules are a good starting point)
    • Complete the wizard to create the Web ACL
  4. Select your Web ACL from the list

  5. Click the Associated AWS resources tab

  6. Click Add AWS resources

  7. Select Application Load Balancer from the resource type dropdown

  8. Check the box next to the ALB you want to protect

  9. Click Add

Your ALB is now protected by the WAF Web ACL.

AWS CLI (optional)

Associate an existing Web ACL with an ALB

aws wafv2 associate-web-acl \
--web-acl-arn arn:aws:wafv2:us-east-1:123456789012:regional/webacl/my-web-acl/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
--resource-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/50dc6c495c0c9188 \
--region us-east-1

Replace:

  • 123456789012 with your AWS account ID
  • my-web-acl and the ID with your Web ACL name and ID
  • my-alb/50dc6c495c0c9188 with your ALB name and ID

List your Web ACLs to find the ARN

aws wafv2 list-web-acls --scope REGIONAL --region us-east-1

List your ALBs to find the ARN

aws elbv2 describe-load-balancers --region us-east-1 \
--query 'LoadBalancers[?Type==`application`].[LoadBalancerName,LoadBalancerArn]' \
--output table

Verify the association

aws wafv2 get-web-acl-for-resource \
--resource-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/50dc6c495c0c9188 \
--region us-east-1
CloudFormation (optional)

Associate a Web ACL with an ALB

AWSTemplateFormatVersion: '2010-09-09'
Description: Associate WAF Web ACL with Application Load Balancer

Parameters:
WebACLArn:
Type: String
Description: The ARN of the WAFv2 Web ACL to associate
ALBArn:
Type: String
Description: The ARN of the Application Load Balancer to protect

Resources:
WebACLAssociation:
Type: AWS::WAFv2::WebACLAssociation
Properties:
WebACLArn: !Ref WebACLArn
ResourceArn: !Ref ALBArn

Outputs:
AssociatedALB:
Description: ARN of the ALB now protected by WAF
Value: !Ref ALBArn

Deploy the stack

aws cloudformation deploy \
--template-file waf-association.yaml \
--stack-name alb-waf-association \
--parameter-overrides \
WebACLArn=arn:aws:wafv2:us-east-1:123456789012:regional/webacl/my-web-acl/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
ALBArn=arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/50dc6c495c0c9188 \
--region us-east-1

Create a Web ACL with Managed Rules (full example)

AWSTemplateFormatVersion: '2010-09-09'
Description: Create WAF Web ACL with AWS Managed Rules and associate with ALB

Parameters:
ALBArn:
Type: String
Description: The ARN of the Application Load Balancer to protect

Resources:
WebACL:
Type: AWS::WAFv2::WebACL
Properties:
Name: application-web-acl
Scope: REGIONAL
DefaultAction:
Allow: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: ApplicationWebACL
Rules:
- Name: AWSManagedRulesCommonRuleSet
Priority: 1
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: CommonRuleSet
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesCommonRuleSet
- Name: AWSManagedRulesKnownBadInputsRuleSet
Priority: 2
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: KnownBadInputs
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesKnownBadInputsRuleSet
- Name: AWSManagedRulesSQLiRuleSet
Priority: 3
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: SQLiRuleSet
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesSQLiRuleSet

WebACLAssociation:
Type: AWS::WAFv2::WebACLAssociation
Properties:
WebACLArn: !GetAtt WebACL.Arn
ResourceArn: !Ref ALBArn

Outputs:
WebACLArn:
Description: ARN of the created Web ACL
Value: !GetAtt WebACL.Arn
Terraform (optional)

Associate an existing Web ACL with an ALB

resource "aws_wafv2_web_acl_association" "alb_waf" {
resource_arn = "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/50dc6c495c0c9188"
web_acl_arn = "arn:aws:wafv2:us-east-1:123456789012:regional/webacl/my-web-acl/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
}
variable "alb_arn" {
description = "ARN of the Application Load Balancer to protect"
type = string
}

variable "web_acl_arn" {
description = "ARN of the WAFv2 Web ACL"
type = string
}

resource "aws_wafv2_web_acl_association" "alb_waf" {
resource_arn = var.alb_arn
web_acl_arn = var.web_acl_arn
}

Create a Web ACL with Managed Rules and associate (full example)

resource "aws_wafv2_web_acl" "application" {
name = "application-web-acl"
description = "Web ACL for Application Load Balancer protection"
scope = "REGIONAL"

default_action {
allow {}
}

# AWS Managed Common Rule Set
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 1

override_action {
none {}
}

statement {
managed_rule_group_statement {
vendor_name = "AWS"
name = "AWSManagedRulesCommonRuleSet"
}
}

visibility_config {
sampled_requests_enabled = true
cloudwatch_metrics_enabled = true
metric_name = "CommonRuleSet"
}
}

# AWS Managed Known Bad Inputs Rule Set
rule {
name = "AWSManagedRulesKnownBadInputsRuleSet"
priority = 2

override_action {
none {}
}

statement {
managed_rule_group_statement {
vendor_name = "AWS"
name = "AWSManagedRulesKnownBadInputsRuleSet"
}
}

visibility_config {
sampled_requests_enabled = true
cloudwatch_metrics_enabled = true
metric_name = "KnownBadInputs"
}
}

# AWS Managed SQL Injection Rule Set
rule {
name = "AWSManagedRulesSQLiRuleSet"
priority = 3

override_action {
none {}
}

statement {
managed_rule_group_statement {
vendor_name = "AWS"
name = "AWSManagedRulesSQLiRuleSet"
}
}

visibility_config {
sampled_requests_enabled = true
cloudwatch_metrics_enabled = true
metric_name = "SQLiRuleSet"
}
}

visibility_config {
sampled_requests_enabled = true
cloudwatch_metrics_enabled = true
metric_name = "ApplicationWebACL"
}

tags = {
Environment = "production"
}
}

resource "aws_wafv2_web_acl_association" "alb" {
resource_arn = aws_lb.application.arn
web_acl_arn = aws_wafv2_web_acl.application.arn
}

Verification

After associating the Web ACL:

  1. Go to the EC2 Load Balancers Console
  2. Select your Application Load Balancer
  3. Click the Integrations tab
  4. Under AWS WAF, confirm your Web ACL is listed

Alternatively, check in the WAF Console:

  1. Go to AWS WAF Console
  2. Select your Web ACL
  3. Click the Associated AWS resources tab
  4. Confirm your ALB appears in the list
CLI Verification
aws wafv2 get-web-acl-for-resource \
--resource-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/50dc6c495c0c9188 \
--region us-east-1

A successful response returns the Web ACL details. If no Web ACL is associated, you will receive an empty response.

Additional Resources

Notes

  • Propagation time: Changes may take a few seconds to several minutes to propagate across all AWS edge locations.
  • Regional scope: For ALBs, use REGIONAL scoped Web ACLs. CloudFront distributions require CLOUDFRONT scoped Web ACLs.
  • One Web ACL per resource: Each ALB can only be associated with one Web ACL at a time. Associating a new one automatically removes the previous association.
  • Cost considerations: AWS WAF charges based on the number of Web ACLs, rules, and requests processed. Review pricing before implementation.
  • Start in Count mode: When first deploying WAF rules, consider setting them to "Count" mode to monitor traffic without blocking, then switch to "Block" after validating the rules work correctly.