Classic Load Balancer Should Be Configured with Defensive or Strictest Desync Mitigation Mode
Overview
This check verifies that your Classic Load Balancer has desync mitigation mode set to either "defensive" or "strictest." Desync mitigation protects your applications from HTTP Desync attacks, which exploit inconsistencies in how servers parse HTTP requests.
Risk
Without proper desync mitigation, your Classic Load Balancer may be vulnerable to HTTP request smuggling attacks. These attacks can lead to:
- Request queue or cache poisoning - Attackers inject malicious requests that get processed by your backend
- Session hijacking - Unauthorized access to other users' sessions
- Credential theft - Sensitive authentication data could be exposed
- Unauthorized command execution - Attackers may trigger unintended actions on your backend
Remediation Steps
Prerequisites
You need:
- Access to the AWS Console with permissions to modify load balancers, OR
- AWS CLI configured with appropriate credentials
AWS Console Method
- Open the EC2 Console
- In the left navigation, click Load Balancers (under "Load Balancing")
- Select your Classic Load Balancer from the list
- Click the Attributes tab
- Click Edit
- Under Traffic configuration, find Desync mitigation mode
- Select either:
- Defensive (recommended) - Balances security with application availability
- Strictest - Only allows RFC 7230-compliant requests
- Click Save changes
AWS CLI (optional)
Check Current Setting
First, verify the current desync mitigation mode:
aws elb describe-load-balancer-attributes \
--load-balancer-name <your-load-balancer-name> \
--region us-east-1 \
--query 'LoadBalancerAttributes.AdditionalAttributes'
Set to Defensive Mode
Create a JSON file named attributes.json:
{
"AdditionalAttributes": [
{
"Key": "elb.http.desyncmitigationmode",
"Value": "defensive"
}
]
}
Then apply the change:
aws elb modify-load-balancer-attributes \
--load-balancer-name <your-load-balancer-name> \
--load-balancer-attributes file://attributes.json \
--region us-east-1
Set to Strictest Mode
If you need maximum protection, use strictest instead:
{
"AdditionalAttributes": [
{
"Key": "elb.http.desyncmitigationmode",
"Value": "strictest"
}
]
}
CloudFormation (optional)
CloudFormation's AWS::ElasticLoadBalancing::LoadBalancer resource does not natively support the AdditionalAttributes property for desync mitigation mode at creation time.
Recommended Approach: Post-Creation Configuration
After deploying your Classic Load Balancer via CloudFormation, use a Custom Resource with AWS Lambda to set the desync mitigation mode, or configure it manually using the AWS CLI.
Example: Custom Resource Lambda
Add this to your CloudFormation template:
AWSTemplateFormatVersion: '2010-09-09'
Description: Classic Load Balancer with Desync Mitigation Mode via Custom Resource
Parameters:
Subnets:
Type: List<AWS::EC2::Subnet::Id>
Description: Subnets for the load balancer
Resources:
ClassicLoadBalancer:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
LoadBalancerName: my-classic-elb
Subnets: !Ref Subnets
Listeners:
- LoadBalancerPort: 80
InstancePort: 80
Protocol: HTTP
DesyncMitigationLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: ELBModifyAttributes
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- elasticloadbalancing:ModifyLoadBalancerAttributes
Resource: '*'
DesyncMitigationLambda:
Type: AWS::Lambda::Function
Properties:
Runtime: python3.11
Handler: index.handler
Role: !GetAtt DesyncMitigationLambdaRole.Arn
Timeout: 60
Code:
ZipFile: |
import boto3
import cfnresponse
def handler(event, context):
if event['RequestType'] == 'Delete':
cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
return
try:
elb = boto3.client('elb')
elb.modify_load_balancer_attributes(
LoadBalancerName=event['ResourceProperties']['LoadBalancerName'],
LoadBalancerAttributes={
'AdditionalAttributes': [
{
'Key': 'elb.http.desyncmitigationmode',
'Value': event['ResourceProperties']['DesyncMode']
}
]
}
)
cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
except Exception as e:
cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': str(e)})
SetDesyncMitigation:
Type: Custom::DesyncMitigation
DependsOn: ClassicLoadBalancer
Properties:
ServiceToken: !GetAtt DesyncMitigationLambda.Arn
LoadBalancerName: !Ref ClassicLoadBalancer
DesyncMode: defensive
Outputs:
LoadBalancerDNS:
Description: DNS name of the load balancer
Value: !GetAtt ClassicLoadBalancer.DNSName
Terraform (optional)
Terraform's aws_elb resource supports desync mitigation mode directly via the desync_mitigation_mode attribute.
resource "aws_elb" "example" {
name = "my-classic-elb"
availability_zones = ["us-east-1a", "us-east-1b"]
listener {
instance_port = 80
instance_protocol = "HTTP"
lb_port = 80
lb_protocol = "HTTP"
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "HTTP:80/"
interval = 30
}
# Set desync mitigation mode to defensive (recommended)
desync_mitigation_mode = "defensive"
tags = {
Name = "my-classic-elb"
}
}
For Strictest Mode
Change the attribute value:
desync_mitigation_mode = "strictest"
Valid Values
monitor- Allows all requests but logs non-compliant ones (NOT compliant with this check)defensive- Recommended balance of security and availability (COMPLIANT)strictest- Maximum security, only RFC 7230-compliant requests allowed (COMPLIANT)
Verification
After making changes, confirm the setting is correct:
- In the AWS Console, go to EC2 > Load Balancers
- Select your Classic Load Balancer
- Click the Attributes tab
- Verify that Desync mitigation mode shows "Defensive" or "Strictest"
CLI Verification
aws elb describe-load-balancer-attributes \
--load-balancer-name <your-load-balancer-name> \
--region us-east-1 \
--query 'LoadBalancerAttributes.AdditionalAttributes[?Key==`elb.http.desyncmitigationmode`].Value' \
--output text
Expected output: defensive or strictest
Additional Resources
- AWS Documentation: Desync Mitigation Mode for Classic Load Balancers
- AWS Security Blog: HTTP Desync Attacks
- Prowler Check Documentation
Notes
Understanding Desync Mitigation Modes
| Mode | Behavior | Use Case |
|---|---|---|
| Monitor | Allows all requests, only logs issues | Testing/debugging only - NOT COMPLIANT |
| Defensive | Blocks severe threats, handles ambiguous requests safely | Most production environments |
| Strictest | Only allows fully RFC-compliant requests | High-security environments |
Request Classifications
The load balancer classifies incoming HTTP requests as:
- Compliant - Fully RFC 7230 compliant, allowed in all modes
- Acceptable - Minor deviations with no known risk, blocked only in strictest mode
- Ambiguous - Potential security risk (e.g., multiple Content-Length headers)
- Severe - High security risk, blocked in all modes except monitor
Monitoring Non-Compliant Requests
After enabling defensive or strictest mode, monitor the DesyncMitigationMode_NonCompliant_Request_Count CloudWatch metric to track how many requests are being classified as non-compliant.
Potential Impact
- Defensive mode: Minimal impact on legitimate traffic; closes connections for ambiguous requests
- Strictest mode: May block some legitimate but non-compliant HTTP clients; test thoroughly in staging before production deployment