Skip to main content
emnode / learn
Compliance Medium severity

AWS Security Hub · ELB

ELB.4: ALB accepts malformed HTTP headers

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub ELB.4 check?

ELB.4 fails when an Application Load Balancer has the drop_invalid_header_fields attribute set to false. With the attribute off, the ALB forwards requests whose headers contain characters that are not valid per the HTTP spec.

Why does ELB.4 matter?

When a front-end load balancer and a back-end target disagree on where one request ends and the next begins, an attacker can smuggle a hidden request inside a malformed Content-Length or Transfer-Encoding header — HTTP desync. That can poison caches, bypass auth on the front end, or hijack another user's session. Dropping invalid headers removes the ambiguity the attack depends on.

How do I fix ELB.4?

  1. Audit each ALB with describe-load-balancer-attributes and check routing.http.drop_invalid_header_fields.enabled.
  2. Set it to true with modify-load-balancer-attributes; the change is non-disruptive to well-formed traffic.
  3. Pair this with ELB.5 (access logs) and ELB.12 (defensive desync mode) for a hardened perimeter.
  4. Default the attribute on in your IaC so new ALBs are compliant from creation.

Remediation script · bash

# Harden every Application Load Balancer in the region: reject invalid headers and
# require defensive (or strictest) desync mode. Both are instant, non-disruptive flips.
for arn in $(aws elbv2 describe-load-balancers \
    --query 'LoadBalancers[?Type==`application`].LoadBalancerArn' --output text); do
  aws elbv2 modify-load-balancer-attributes --load-balancer-arn "$arn" \
    --attributes \
      Key=routing.http.drop_invalid_header_fields.enabled,Value=true \
      Key=routing.http.desync_mitigation_mode,Value=defensive
  echo "$arn: hardened"
done

# Switch load-balanced Auto Scaling groups to ELB health checks with a safe grace period
# (confirm the target-group probe reflects real app health first).
for g in $(aws autoscaling describe-auto-scaling-groups \
    --query 'AutoScalingGroups[?(LoadBalancerNames!=`[]` || TargetGroupARNs!=`[]`) && HealthCheckType==`EC2`].AutoScalingGroupName' \
    --output text); do
  aws autoscaling update-auto-scaling-group --auto-scaling-group-name "$g" \
    --health-check-type ELB --health-check-grace-period 300
  echo "$g: now using ELB health checks"
done

Full walkthrough (console steps, edge cases and verification) in the lesson Harden load balancers (ALB/NLB/CLB).

Part of the learning path Build in resilience
  • ELB.1 ALB serves HTTP without redirecting to HTTPS
  • ELB.2 CLB SSL/HTTPS listeners should use ACM certs
  • ELB.3 CLB listeners should use HTTPS/TLS termination
  • ELB.5 Load balancers are not writing access logs
  • ELB.6 Load balancers can be deleted by accident
  • ELB.7 CLBs should have connection draining
  • ELB.8 CLB SSL listeners should use strong policy
  • ELB.9 CLBs should have cross-zone balancing
  • ELB.10 CLBs should span multiple AZs
  • ELB.12 ALB desync mitigation mode
  • ELB.13 A single-AZ load balancer is a data-plane single point of failure
  • ELB.14 CLB desync mitigation mode