脆弱なセキュリティポリシーを持つ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
}

重要な修正ポイントと実装手順を説明します:

  1. セキュリティポリシーの設定(最重要):
# 推奨されるセキュリティポリシーを使用(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
      }
      
      

      適用手順:

      1. 変数の設定:
      # 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機能で簡単に検出及び管理する事が可能です。

      運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。

      最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです

      この記事をシェアする

      クラウドセキュリティ対策実践集一覧へ戻る

      貴社の利用状況に合わせた見積もりを作成します。

      料金プランを詳しく見る