脆弱なセキュリティポリシーを持つHTTPS/SSLリスナーを使用するCLB

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。
この記事では、脆弱なセキュリティポリシーを持つHTTPS/SSLリスナーを使用するCLBについて、そのリスクと対策を解説します。

ポリシーの説明
まず、AWS Security Hubによるポリシーの説明は以下の通りです。
[ELB.8] SSL リスナーを使用する Classic Load Balancer は、強力な AWS Config設定を持つ事前定義されたセキュリティポリシーを使用する必要があります
Elastic Load Balancing の Security Hub コントロール – AWS Security Hub
このコントロールは、Classic Load Balancer の HTTPS/SSL リスナーが事前定義されたポリシー
ELBSecurityPolicy-TLS-1-2-2017-01
を使用しているかどうかをチェックします。Classic Load Balancer の HTTPS/SSL リスナーがELBSecurityPolicy-TLS-1-2-2017-01
を使用しない場合、コントロールは失敗します。
リスクとしては、Classic Load Balancer(CLB)のSSLリスナーでAWSが提供する強力なセキュリティポリシーを使用していない場合、弱い暗号スイートや古いTLSプロトコルが有効になってしまう可能性があります。 これにより、攻撃者による盗聴や改ざんのリスクが高まり、さらに業界標準やコンプライアンス要件(PCI DSS、ISO 27001 など)に違反する可能性があります。
そのため、CLBのSSLリスナーにはAWSが提供する強力なセキュリティポリシーを適用し、ポリシーは都度更新されるため、定期的に設定を見直して最新のポリシーへ更新することが望ましいです。
修復方法
AWSコンソールでの修正手順
設定するべき重要なポイントは赤枠で囲ったところになります。 2025/03/15 執筆時点では「ELBSecurityPolicy-TLS13-1-2-2021-06」が推奨されるポリシーとなっています。
① EC2 > ロードバランサーへ移動
② リスナーの設定でSSLを使用した場合は、セキュリティポリシーの設定で以下に変更する

Terraformでの修復手順
ロードバランサーのセキュアな設定のためのTerraformコードを作成します。
# ALB(Application Load Balancer)の設定
resource "aws_lb" "app" {
name = "${var.environment}-${var.app_name}-alb"
internal = var.internal_lb
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = var.subnet_ids
# アクセスログの有効化
access_logs {
bucket = aws_s3_bucket.lb_logs.id
prefix = "alb-logs"
enabled = true
}
tags = {
Environment = var.environment
Name = "${var.environment}-${var.app_name}-alb"
}
}
# ALBリスナー(HTTPS)
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.app.arn
port = "443"
protocol = "HTTPS"
# 推奨されるセキュリティポリシーを使用(2025/03/15時点)
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn = var.certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.app.arn
}
}
# HTTPからHTTPSへのリダイレクト
resource "aws_lb_listener" "http_redirect" {
load_balancer_arn = aws_lb.app.arn
port = "80"
protocol = "HTTP"
default_action {
type = "redirect"
redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
# ALBターゲットグループ
resource "aws_lb_target_group" "app" {
name = "${var.environment}-${var.app_name}-tg"
port = var.app_port
protocol = "HTTP"
vpc_id = var.vpc_id
target_type = "ip"
health_check {
enabled = true
healthy_threshold = 2
interval = 30
timeout = 5
path = var.health_check_path
matcher = "200"
unhealthy_threshold = 2
}
}
# ALBのセキュリティグループ
resource "aws_security_group" "alb" {
name = "${var.environment}-${var.app_name}-alb-sg"
description = "Security group for ALB"
vpc_id = var.vpc_id
# HTTPSインバウンドルール
ingress {
description = "HTTPS from anywhere"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# HTTPインバウンドルール(リダイレクト用)
ingress {
description = "HTTP from anywhere (for redirect)"
from_port = 80
to_port = 80
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 = "${var.environment}-${var.app_name}-alb-sg"
Environment = var.environment
}
}
# ロードバランサーログ用のS3バケット
resource "aws_s3_bucket" "lb_logs" {
bucket = "${var.environment}-${var.app_name}-lb-logs-${data.aws_caller_identity.current.account_id}"
}
# S3バケットのパブリックアクセスをブロック
resource "aws_s3_bucket_public_access_block" "lb_logs" {
bucket = aws_s3_bucket.lb_logs.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# S3バケットの暗号化設定
resource "aws_s3_bucket_server_side_encryption_configuration" "lb_logs" {
bucket = aws_s3_bucket.lb_logs.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
# S3バケットポリシー(ALBログ用)
resource "aws_s3_bucket_policy" "lb_logs" {
bucket = aws_s3_bucket.lb_logs.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${data.aws_elb_service_account.main.id}:root"
}
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.lb_logs.arn}/*"
}
]
})
}
# 必要なデータソース
data "aws_caller_identity" "current" {}
data "aws_elb_service_account" "main" {}
# 変数定義
variable "environment" {
type = string
description = "環境名(production, staging等)"
}
variable "app_name" {
type = string
description = "アプリケーション名"
}
variable "vpc_id" {
type = string
description = "VPC ID"
}
variable "subnet_ids" {
type = list(string)
description = "サブネットIDのリスト"
}
variable "certificate_arn" {
type = string
description = "SSL証明書のARN"
}
variable "internal_lb" {
type = bool
description = "内部ロードバランサーとするかどうか"
default = false
}
variable "app_port" {
type = number
description = "アプリケーションのポート番号"
default = 80
}
variable "health_check_path" {
type = string
description = "ヘルスチェックのパス"
default = "/"
}
# 出力
output "alb_dns_name" {
value = aws_lb.app.dns_name
}
output "alb_zone_id" {
value = aws_lb.app.zone_id
}
重要な修正ポイントと実装手順を説明します:
- セキュリティポリシーの設定(最重要):
# 推奨されるセキュリティポリシーを使用(2025/03/15時点)
resource "aws_lb_listener" "https" {
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06" # 推奨されるセキュリティポリシー
}
2. HTTPSの強制:
resource "aws_lb_listener" "http_redirect" {
default_action {
type = "redirect"
redirect {
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
3. アクセスログの有効化:
access_logs {
bucket = aws_s3_bucket.lb_logs.id
prefix = "alb-logs"
enabled = true
}
適用手順:
- 変数の設定:
# terraform.tfvars
environment = "production"
app_name = "myapp"
certificate_arn = "arn:aws:acm:region:account:certificate/xxx"
vpc_id = "vpc-xxx"
subnet_ids = ["subnet-xxx", "subnet-yyy"]
最後に
今回は、ロードバランサで使用するHTTPS/SSL リスナーについて、脆弱なセキュリティポリシーを持つポリシー設定がされている場合のリスクとその対処方法についてご紹介しました。 古く、脆弱なセキュリティポリシーを持つHTTPS/SSLリスナーを使用することは攻撃者からの盗聴、改ざんされるリスクがあるため、本記事を参考にポリシー設定の見直しを行ってみてください。
この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。
運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。
最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。