Skip to main content
emnode / learn
Compliance Medium severity

AWS Security Hub · ELB

ELB.22: Load-balancer-to-target traffic is not encrypted

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub ELB.22 check?

ELB.22 fails when a target group's protocol is HTTP rather than HTTPS — meaning the load balancer forwards traffic to its targets in cleartext, even if the client-facing listener is TLS.

Why does ELB.22 matter?

TLS terminating at the load balancer leaves the LB-to-target hop unencrypted inside the VPC. For regulated workloads that demand end-to-end encryption, or any environment where the VPC network is not treated as trusted, that hop is a gap an attacker with network access can read. Engineers often resist this fearing latency, but the TLS 1.3 handshake adds about 1ms once per connection and keep-alive amortises it to well under 0.1ms per request.

How do I fix ELB.22?

  1. Inventory target group protocols with describe-target-groups and decide where the trust boundary actually requires encryption.
  2. Stand up TLS on the targets (a self-signed cert is sufficient — the LB does not validate the chain).
  3. Cut over at the listener by pointing the rule at a new HTTPS target group rather than re-protocolling the live one in place.
  4. Prevent recurrence with Config plus an IaC default of HTTPS target groups.

Remediation script · bash

# 1. Bulk-enable free SSE-SQS on every unencrypted queue in the region.
for q in $(aws sqs list-queues --query 'QueueUrls[]' --output text); do
  state=$(aws sqs get-queue-attributes --queue-url $q \
    --attribute-names KmsMasterKeyId SqsManagedSseEnabled --query 'Attributes' --output text)
  [ -z "$state" ] && aws sqs set-queue-attributes --queue-url $q \
    --attributes '{"SqsManagedSseEnabled":"true"}' && echo "encrypted $q"
done

# 2. High-throughput stream: SSE-KMS with a 5-minute data-key reuse window to keep KMS cost flat.
aws kinesis start-stream-encryption --stream-name payment-events \
  --encryption-type KMS \
  --key-id arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

# 3. Find unencrypted recovery points (Backup.1 reads IsEncrypted per recovery point, not per vault).
aws backup list-recovery-points-by-backup-vault --backup-vault-name prod-backups \
  --query 'RecoveryPoints[?IsEncrypted==`false`].[RecoveryPointArn,ResourceType]' --output table

# 4. Confirm an at-rest Config rule is evaluating so regressions are caught automatically.
aws configservice describe-compliance-by-config-rule --config-rule-names sqs-queue-encrypted \
  --query 'ComplianceByConfigRules[].Compliance.ComplianceType'

Full walkthrough (console steps, edge cases and verification) in the lesson Encrypt other services at rest (queues, streams, logs, ML).

Is ELB.22 a false positive?

For purely internal, non-regulated traffic inside a trusted VPC, ELB.22 is often noise — assess whether the trust boundary genuinely demands the LB-to-target hop be encrypted before treating it as urgent.

Part of the learning path Encrypt everything
  • 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.4 ALB accepts malformed HTTP headers
  • 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