ELB Insecure SSL Ciphers
Overview
This check verifies that Classic Elastic Load Balancer (ELB) HTTPS listeners use the ELBSecurityPolicy-TLS-1-2-2017-01 security policy, which enforces modern TLS 1.2 protocols and strong cipher suites.
Classic ELBs use predefined security policies that control which SSL/TLS protocols and ciphers are used during HTTPS connections. Older policies allow weak ciphers and deprecated protocols that have known vulnerabilities.
Risk
Using insecure SSL/TLS policies exposes your infrastructure to:
- Man-in-the-middle attacks - Attackers can intercept and decrypt traffic using weak cipher exploits
- Protocol downgrade attacks - Attackers can force connections to use weaker, exploitable protocols
- Data exposure - Credentials, session tokens, and sensitive data can be intercepted
- Compliance violations - PCI-DSS, HIPAA, and other frameworks require modern TLS configurations
Legacy TLS versions (1.0, 1.1) and weak cipher suites have known vulnerabilities. The ELBSecurityPolicy-TLS-1-2-2017-01 policy requires TLS 1.2 and only allows modern AEAD ciphers.
Remediation Steps
Prerequisites
- AWS account access with permission to modify Classic Load Balancers
- Your load balancer name (found in the Prowler findings or EC2 console)
Required IAM permissions
To update Classic ELB listeners, you need:
elasticloadbalancing:DescribeLoadBalancerselasticloadbalancing:DescribeLoadBalancerPolicieselasticloadbalancing:SetLoadBalancerPoliciesOfListener
AWS Console Method
- Open the EC2 console
- In the left navigation, under Load Balancing, click Load Balancers
- Select your Classic Load Balancer
- Click the Listeners tab
- Find the HTTPS listener (typically port 443) and click Edit
- In the Cipher column, click Change
- Select Predefined security policy
- Choose ELBSecurityPolicy-TLS-1-2-2017-01 from the dropdown
- Click Save
Important: Verify your clients support TLS 1.2. Very old browsers or systems may fail to connect after this change.
AWS CLI (optional)
Update the security policy for an HTTPS listener on port 443:
aws elb set-load-balancer-policies-of-listener \
--load-balancer-name <your-load-balancer-name> \
--load-balancer-port 443 \
--policy-names ELBSecurityPolicy-TLS-1-2-2017-01 \
--region us-east-1
Replace <your-load-balancer-name> with your Classic ELB's name.
To check the current policy for your load balancer:
aws elb describe-load-balancers \
--load-balancer-names <your-load-balancer-name> \
--region us-east-1 \
--query 'LoadBalancerDescriptions[0].ListenerDescriptions[?Listener.Protocol==`HTTPS`].PolicyNames' \
--output table
To list all available security policies:
aws elb describe-load-balancer-policies \
--region us-east-1 \
--query 'PolicyDescriptions[?PolicyTypeName==`SSLNegotiationPolicyType`].PolicyName' \
--output table
CloudFormation (optional)
AWSTemplateFormatVersion: '2010-09-09'
Description: Classic ELB with secure TLS 1.2 policy
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
Description: VPC where the load balancer will be created
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Description: Subnets for the load balancer
CertificateArn:
Type: String
Description: ARN of the ACM certificate for HTTPS
Resources:
ClassicLoadBalancer:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
LoadBalancerName: secure-classic-elb
Subnets: !Ref SubnetIds
SecurityGroups:
- !Ref ELBSecurityGroup
Scheme: internet-facing
Listeners:
- LoadBalancerPort: 443
InstancePort: 80
Protocol: HTTPS
InstanceProtocol: HTTP
SSLCertificateId: !Ref CertificateArn
# Key setting: Use TLS 1.2 only policy
PolicyNames:
- ELBSecurityPolicy-TLS-1-2-2017-01
Policies:
# Reference the predefined AWS security policy
- PolicyName: ELBSecurityPolicy-TLS-1-2-2017-01
PolicyType: SSLNegotiationPolicyType
Attributes:
- Name: Reference-Security-Policy
Value: ELBSecurityPolicy-TLS-1-2-2017-01
HealthCheck:
Target: HTTP:80/health
HealthyThreshold: 2
UnhealthyThreshold: 5
Interval: 30
Timeout: 5
ELBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Classic ELB
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Outputs:
LoadBalancerDNS:
Description: DNS name of the load balancer
Value: !GetAtt ClassicLoadBalancer.DNSName
LoadBalancerName:
Description: Name of the load balancer
Value: !Ref ClassicLoadBalancer
Deploy with:
aws cloudformation deploy \
--template-file classic-elb-tls12.yaml \
--stack-name secure-classic-elb \
--parameter-overrides \
VpcId=vpc-12345678 \
SubnetIds=subnet-11111111,subnet-22222222 \
CertificateArn=arn:aws:acm:us-east-1:123456789012:certificate/abc123 \
--region us-east-1
Key configuration:
- The
PolicyNamesin the listener referencesELBSecurityPolicy-TLS-1-2-2017-01 - The
Policiessection defines a reference to AWS's predefined security policy
Terraform (optional)
variable "vpc_id" {
description = "VPC ID where the ELB will be created"
type = string
}
variable "subnet_ids" {
description = "List of subnet IDs for the ELB"
type = list(string)
}
variable "certificate_arn" {
description = "ARN of the ACM certificate for HTTPS"
type = string
}
resource "aws_security_group" "elb" {
name = "secure-classic-elb-sg"
description = "Security group for Classic ELB"
vpc_id = var.vpc_id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "secure-classic-elb-sg"
}
}
resource "aws_elb" "secure" {
name = "secure-classic-elb"
subnets = var.subnet_ids
security_groups = [aws_security_group.elb.id]
listener {
instance_port = 80
instance_protocol = "HTTP"
lb_port = 443
lb_protocol = "HTTPS"
ssl_certificate_id = var.certificate_arn
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 5
timeout = 5
target = "HTTP:80/health"
interval = 30
}
tags = {
Name = "secure-classic-elb"
Security = "TLS12Only"
}
}
# Key resource: Attach the TLS 1.2 security policy to the HTTPS listener
resource "aws_load_balancer_policy" "tls12_policy" {
load_balancer_name = aws_elb.secure.name
policy_name = "ELBSecurityPolicy-TLS-1-2-2017-01"
policy_type_name = "SSLNegotiationPolicyType"
policy_attribute {
name = "Reference-Security-Policy"
value = "ELBSecurityPolicy-TLS-1-2-2017-01"
}
}
resource "aws_load_balancer_listener_policy" "tls12_listener" {
load_balancer_name = aws_elb.secure.name
load_balancer_port = 443
policy_names = [
aws_load_balancer_policy.tls12_policy.policy_name,
]
}
output "elb_dns_name" {
description = "DNS name of the load balancer"
value = aws_elb.secure.dns_name
}
output "elb_name" {
description = "Name of the load balancer"
value = aws_elb.secure.name
}
Deploy with:
terraform init
terraform apply \
-var="vpc_id=vpc-12345678" \
-var='subnet_ids=["subnet-11111111","subnet-22222222"]' \
-var="certificate_arn=arn:aws:acm:us-east-1:123456789012:certificate/abc123"
Key resources:
aws_load_balancer_policycreates a reference to the predefined AWS security policyaws_load_balancer_listener_policyattaches the policy to the HTTPS listener
Verification
After updating your load balancer:
- Go to the EC2 console
- Navigate to Load Balancers under Load Balancing
- Select your Classic Load Balancer
- Click the Listeners tab
- Verify the HTTPS listener shows ELBSecurityPolicy-TLS-1-2-2017-01 in the Cipher column
- Test your application to confirm it still works
CLI verification
Check the current listener policies:
aws elb describe-load-balancers \
--load-balancer-names <your-load-balancer-name> \
--region us-east-1 \
--query 'LoadBalancerDescriptions[0].ListenerDescriptions' \
--output json
Look for PolicyNames containing ELBSecurityPolicy-TLS-1-2-2017-01.
Test the TLS connection externally:
openssl s_client -connect <elb-dns-name>:443 -tls1_2
This should connect successfully. Testing with older protocols should fail:
openssl s_client -connect <elb-dns-name>:443 -tls1_1
# Should fail to connect
Re-run the Prowler check:
prowler aws --checks elb_insecure_ssl_ciphers
Additional Resources
- Predefined SSL Security Policies for Classic Load Balancers
- Update the SSL Negotiation Configuration
- Classic Load Balancer Listeners
- NIST Guidelines on TLS - Recommends TLS 1.2 minimum
Notes
-
Client compatibility: The TLS 1.2 policy requires clients to support TLS 1.2. Most modern browsers and systems support this, but very old clients (Internet Explorer on Windows XP, Android 4.3 and earlier) may fail to connect. Verify your user base can support TLS 1.2 before making this change.
-
Application Load Balancers (ALBs): If you're using an Application Load Balancer instead of a Classic ELB, this check does not apply. ALBs have a different security policy configuration and separate Prowler checks.
-
Network Load Balancers (NLBs): Network Load Balancers operate at layer 4 and do not terminate SSL/TLS, so this check does not apply to them.
-
Custom policies: While you can create custom SSL policies, using the predefined
ELBSecurityPolicy-TLS-1-2-2017-01is recommended as it is maintained by AWS and follows best practices. -
Certificate requirements: Ensure your SSL certificate is compatible with TLS 1.2. Modern ACM certificates work with all supported policies.
-
Migration consideration: AWS recommends migrating from Classic ELBs to Application Load Balancers for new workloads, as ALBs offer more features and better security policy options.