Auto Scaling グループでIMDSv2 のみを有効化するための手順

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。

この記事では、EC2 Auto Scalingグループが IMDSv2 (Instance Metadata Service Version 2) のみを有効にするように設定されていない状態について、リスクと対策を解説します。

リスク

Amazon EC2インスタンスは、インスタンスメタデータサービス (IMDS) を介して、インスタンスのIPアドレス、IAMロールの一時的な認証情報、ユーザーデータなどの情報にアクセスできます。IMDSにはv1とv2の2つのバージョンがあります。EC2 Auto ScalingグループがIMDSv2のみを有効にするように設定されていない場合、以下のようなセキュリティ上の重大なリスクが発生します。

  • 認証情報の不正取得: IMDSv1はセッション指向ではないため、脆弱なWebアプリケーション、特定のプロキシ設定、またはEC2インスタンス上の悪意のあるソフトウェア(SSRF攻撃など)を通じて、攻撃者がIMDSv1にアクセスし、IAMロールの一時的な認証情報を窃取する可能性があります。
  • 権限昇格攻撃: 窃取された認証情報を使用されると、攻撃者はそのIAMロールが持つ権限でAWSリソースを操作できるようになり、権限昇格攻撃やデータ漏洩につながる可能性があります。
  • データ漏洩: インスタンスメタデータには、インスタンスに関する機密情報が含まれる場合があります。IMDSv1の脆弱性を悪用されると、これらの情報が不正に取得され、さらなる攻撃の足がかりとなる恐れがあります。
  • セキュリティコンプライアンス違反: 多くのセキュリティフレームワークやコンプライアンス基準では、AWS環境における認証情報の保護が厳しく求められます。IMDSv1の脆弱性は、これらの要件に抵触する可能性があります。

対策

EC2 Auto ScalingグループでIMDSv2のみを有効にすることは、IAM認証情報の不正取得を防ぎ、セキュリティ体制を大幅に強化するための重要な対策です。

  • IMDSv2の強制: Auto Scalingグループで使用する 起動テンプレート または 起動設定 で、IMDSのバージョンを v2のみ (IMDSv2) に設定します。これにより、EC2インスタンスはIMDSv1からのアクセスを拒否し、認証情報を取得するためのセッションベースの安全なメカニズム(トークン要求)を強制します。
  • アプリケーションの互換性確認: IMDSv2はセッションベースの認証を必要とするため、EC2インスタンス上で動作するアプリケーションやスクリプトがIMDSv2に対応していることを確認します。AWS SDKの最近のバージョンはIMDSv2に自動的に対応していますが、古いSDKやカスタムスクリプトでは更新が必要になる場合があります。
  • 新規Auto Scalingグループでのデフォルト設定: 新しいAuto Scalingグループを作成する際は、必ずIMDSv2のみを有効にするよう設定します。
  • 既存Auto Scalingグループの移行: 既存のAuto ScalingグループがIMDSv1または両方を許可している場合は、新しい起動テンプレート(IMDSv2のみを強制)を作成し、Auto Scalingグループをその新しいテンプレートに更新します。その後、インスタンスのリフレッシュ を実行して、既存のインスタンスを新しい設定のインスタンスに置き換えます。

修復方法

AWSコンソールでの修復手順

AWSコンソールを使用して、EC2 Auto ScalingグループがIMDSv2のみを有効にするように設定します。

1. 起動テンプレートを更新または作成する (推奨):

  • EC2サービスへ移動: AWSコンソールにログインし、EC2サービスを開きます。
  • 起動テンプレートの選択: 左側のナビゲーションペインで「起動テンプレート」を選択します。
  • 新しいバージョンの作成または新規作成:
    • 既存の起動テンプレートを使用している場合は、それを選択し、「アクション」>「テンプレートから新しいバージョンを作成」をクリックします。
    • 新規で作成する場合は、「起動テンプレートを作成」をクリックします。
  • 詳細設定の展開: テンプレート作成/編集画面で、「高度な詳細」セクションまでスクロールして展開します。
  • IMDSv2の設定:
    • メタデータオプション」セクションを見つけます。「メタデータオプションを編集」をクリックします。「インスタンスメタデータサービスバージョン」で「V2 (トークン必須)」を選択します。「HTTP エンドポイント」が「有効」になっていることを確認します。「HTTP トークン応答ホップ制限」はデフォルト値の 1 で問題ありません。「変更を保存」をクリックします。
  • テンプレートの作成/バージョンの発行: テンプレートの残りの設定を確認し、「起動テンプレートを作成」(新規の場合)または「テンプレートバージョンを作成」(新しいバージョンの場合)をクリックします。

2. Auto Scalingグループを更新する:

  • EC2サービスへ移動: EC2サービス画面に戻り、左側のナビゲーションペインで「Auto Scaling グループ」を選択します。
  • Auto Scalingグループの選択: 設定を変更したいAuto Scalingグループを選択します。
  • 編集: Auto Scalingグループの詳細ページで、「編集」をクリックします。
  • 起動テンプレートの更新:
    • 起動テンプレート」セクションで、先ほどIMDSv2を設定した起動テンプレートを選択します。
    • バージョン」ドロップダウンから、IMDSv2が有効になっている最新のテンプレートバージョンを選択します。
  • 更新を適用: 変更を確認し、「更新」をクリックします。
  • インスタンスのリフレッシュ (重要): この変更だけでは、既存のEC2インスタンスにはIMDSv2設定は適用されません。既存のインスタンスにも新しい設定を適用するには、Auto Scalingグループの詳細ページで「インスタンス管理」タブに移動し、「インスタンスのリフレッシュ」を開始します。これにより、グループ内の既存インスタンスが順次終了され、新しい起動テンプレート設定で新しいインスタンスが起動されます。

Terraformでの修復手順

TerraformでEC2 Auto ScalingグループにIMDSv2のみを強制するには、aws_launch_template リソースの metadata_options ブロックを設定し、それを aws_autoscaling_group で参照します。

注: 起動設定 (aws_launch_configuration) ではなく、起動テンプレート (aws_launch_template) を使用することが推奨されます。起動設定ではIMDSv2のみを強制するオプションが直接サポートされていないため、起動テンプレートへの移行が必要です。

# EC2 Auto Scalingグループで使用する起動テンプレートを定義
resource "aws_launch_template" "my_app_launch_template" {
  name_prefix   = "my-app-lt-"
  image_id      = "ami-0abcdef1234567890" # 使用するAMI IDに置き換えてください (例: 最新のAmazon Linux 2 AMIなど)
  instance_type = "t3.medium"            # インスタンスタイプを適切に選択

  key_name      = "my-ec2-keypair"      # 使用するキーペア名に置き換えてください (オプション)

  # セキュリティグループの指定 (適切なセキュリティグループIDに置き換え)
  vpc_security_group_ids = [aws_security_group.app_instance_sg.id]

  # IMDSv2のみを強制する設定
  metadata_options {
    http_endpoint               = "enabled"  # HTTPエンドポイントを有効に
    http_tokens                 = "required" # トークンを必須に (IMDSv2のみ)
    http_put_response_hop_limit = 1          # ホップ制限を1に (デフォルト)
  }

  # (オプション) 詳細なモニタリングを有効にする
  monitoring {
    enabled = true
  }

  # (オプション) EBSボリュームの設定
  block_device_mappings {
    device_name = "/dev/xvda"
    ebs {
      volume_size = 30
      volume_type = "gp3"
      encrypted   = true
      delete_on_termination = true
    }
  }

  # (オプション) インスタンスにアタッチするIAMロール
  iam_instance_profile {
    name = aws_iam_instance_profile.app_instance_profile.name
  }

  # (オプション) ユーザーデータ
  user_data = base64encode(<<EOF
#!/bin/bash
echo "Hello from user data!" > /tmp/user-data.log
EOF
)

  tags = {
    Name = "MyAppLaunchTemplateWithIMDSv2"
  }
}

# Auto Scalingグループの定義
resource "aws_autoscaling_group" "my_app_asg" {
  name = "my-application-asg"

  # 起動テンプレートを参照
  launch_template {
    id      = aws_launch_template.my_app_launch_template.id
    version = "$Latest" # 常に最新バージョンを使用
  }

  min_size             = 1
  max_size             = 3
  desired_capacity     = 1
  vpc_zone_identifier  = [aws_subnet.public_a.id, aws_subnet.public_c.id] # あなたのサブネットIDに置き換え

  health_check_type          = "EC2"
  health_check_grace_period  = 300 # 秒

  tag {
    key                 = "Name"
    value               = "MyAppInstance"
    propagate_at_launch = true
  }
  tag {
    key                 = "Environment"
    value               = "Development"
    propagate_at_launch = true
  }
}

# 関連リソースの定義例 (Security Group, IAM Role, Subnet など)
# これらはあなたの環境に合わせて定義または参照してください。

resource "aws_security_group" "app_instance_sg" {
  name        = "app-instance-security-group"
  description = "Security group for app instances"
  vpc_id      = aws_vpc.main.id # あなたのVPC IDに置き換え

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # 適切なIP範囲に制限してください
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_iam_role" "ecs_instance_role" {
  name = "my-app-instance-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ec2.amazonaws.com"
        }
      },
    ]
  })
}

resource "aws_iam_instance_profile" "app_instance_profile" {
  name = "my-app-instance-profile"
  role = aws_iam_role.ecs_instance_role.name
}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "main-vpc"
  }
}

resource "aws_subnet" "public_a" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "ap-northeast-1a" # あなたのリージョンに合わせて変更
  tags = {
    Name = "public-subnet-a"
  }
}

resource "aws_subnet" "public_c" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "ap-northeast-1c" # あなたのリージョンに合わせて変更
  tags = {
    Name = "public-subnet-c"
  }
}

上記のTerraformコードでは、aws_launch_template リソース内の metadata_options ブロックで http_tokens = "required" を設定することで、IMDSv2のみを強制しています。そして、この起動テンプレートを aws_autoscaling_group で参照しています。

ami-0abcdef1234567890my-ec2-keypair、サブネットIDなどのプレースホルダーは、実際の環境に合わせて修正してください。

最後に

この記事では、EC2 Auto ScalingグループがIMDSv2のみを有効にするように設定されていない状態について、リスクと対策を解説しました。IMDSv2の強制は、EC2インスタンスのセキュリティを向上させるための基本的なベストプラクティスです。特に、WebアプリケーションにおけるSSRF攻撃などによる認証情報漏洩のリスクを大幅に軽減できます。

貴社のAuto Scalingグループでは、IMDSv2が適切に設定されていますか?この機会にぜひご確認ください。

この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。

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

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

この記事をシェアする

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

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

料金プランを詳しく見る