🚨 GuardDuty InstanceCredentialExfiltration

EC2認証情報の外部漏洩を検出したときの完全対処マニュアル

.OutsideAWS .InsideAWS
⚠️ 重大度: HIGH(7.0〜8.9)

📌 結論:EC2の「社員証」が盗まれて外部で悪用されている!

EC2インスタンスに付与されたIAMロールの一時的な認証情報(セッショントークン)が、
本来のEC2インスタンス以外の場所からAWSのAPIを呼び出すのに使用されました。
これは認証情報が漏洩し、攻撃者に悪用されている可能性を示す重大なアラートです。

🔴

何が起きた?

EC2の認証情報が
外部から使用された

⚠️

なぜ危険?

攻撃者がAWSリソースに
不正アクセス可能

最優先アクション

IAMロールの
セッション即時無効化

🛡️

再発防止

IMDSv2の強制と
最小権限の原則

📋 2種類のアラートを理解する

.OutsideAWS
🌐 AWS外部からの悪用
EC2の認証情報がAWSネットワーク外部(インターネット上の攻撃者サーバーなど)から使用された場合に発報されます。
重大度 HIGH (8.0)
発信元 外部IPアドレス
典型的な攻撃 SSRF、RCE経由の漏洩
緊急度 🔴 最高
.InsideAWS
☁️ AWS内部からの悪用
EC2の認証情報が別のAWSアカウント別リージョンのAWSリソースから使用された場合に発報されます。
重大度 HIGH (7.5)
発信元 別のAWSアカウント/リージョン
典型的な攻撃 侵害されたEC2経由
緊急度 🟠 高

🏢 高級マンションの「社員証盗難事件」で理解する!

🎭 シナリオ:あなたは高級マンションの管理人

あなたが管理するマンション(AWSアカウント)には、各部屋(EC2インスタンス)があります。
各部屋の住人は専用の社員証(IAMロール認証情報)を持っていて、
この社員証で共用施設(S3、RDS、他のAWSサービス)にアクセスできます。

🎯 攻撃の流れ

1
😈
攻撃者
悪意のあるリクエスト
SSRF攻撃
2
🖥️
EC2 (Webアプリ)
脆弱なアプリケーション
内部アクセス
3
🪪
IMDS
169.254.169.254
認証情報を窃取
4
☁️
AWSサービス
S3, RDS, IAMなど
異常検知!
5
🚨
GuardDuty
アラート発報!

🔓 SSRF攻撃による認証情報の窃取

😈
攻撃者
悪意のあるURLを送信
📝
脆弱なWebアプリ
URLを検証せず取得
🎯
IMDS v1
http://169.254.169.254/
🪪
認証情報取得
AccessKey, Secret, Token

⚠️ IMDSv1では、単純なGETリクエストで認証情報が取得できてしまう!

🏢 マンションのたとえで言うと...

正常な状態:社員証は各部屋の中でしか使えない(認証情報はEC2内でのみ使用)
異常な状態:泥棒が社員証をコピーして、マンション外から共用施設を使っている!

GuardDutyは「この社員証、本来の部屋(EC2)じゃない場所から使われてるぞ!」と警報を鳴らしました。

🔐 IMDSv1 vs IMDSv2 - なぜv2が重要か

IMDSv1
⚠️ 非推奨
単純なGETリクエストで認証情報取得可能
SSRF攻撃に対して脆弱
認証なしでアクセス可能
リクエスト元の検証なし
# IMDSv1での認証情報取得(危険!簡単すぎる) curl http://169.254.169.254/latest/meta-data/iam/security-credentials/MyRole
IMDSv2
✅ 推奨
セッショントークンが必須
PUTリクエストでトークン取得が必要
SSRF攻撃からの保護が大幅に向上
トークンにTTL(有効期限)あり
# IMDSv2での認証情報取得(2段階必要) # Step 1: トークンを取得(PUTリクエスト必須) TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \ -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") # Step 2: トークンを使って認証情報取得 curl -H "X-aws-ec2-metadata-token: $TOKEN" \ http://169.254.169.254/latest/meta-data/iam/security-credentials/MyRole

🛠️ インシデント対応の5ステップ

0-5分

🔴 認証情報の無効化

被害拡大を即座に止める

5-15分

🟠 インスタンス隔離

侵害された環境を隔離

15-60分

🔵 被害範囲の調査

CloudTrailで不正操作を特定

1-24時間

🟢 復旧と再発防止

根本原因の解決と対策実装

1
認証情報の無効化
IAMロールの全セッションを取り消し
⚡ 即時(0-5分)
  • GuardDutyの検出結果から該当のIAMロール名を特定
  • 該当ロールに「過去のセッションを無効化」するインラインポリシーを追加
  • これにより、既存の認証情報は即座に無効化される
# 現在時刻より前に発行されたすべてのセッションを無効化 aws iam put-role-policy \ --role-name CompromisedEC2Role \ --policy-name RevokeOlderSessions \ --policy-document '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Deny", "Action": "*", "Resource": "*", "Condition": { "DateLessThan": { "aws:TokenIssueTime": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'" } } }] }'
2
EC2インスタンスの隔離
ネットワークを遮断し、調査用に保持
⚡ 即時(5-15分)
  • 隔離用セキュリティグループを適用(全通信を拒否)
  • ⚠️ インスタンスは停止・終了しない(フォレンジック調査のため)
  • EBSスナップショットを取得して証拠を保全
# 隔離用セキュリティグループを作成 aws ec2 create-security-group \ --group-name isolation-sg \ --description "Isolation security group - no traffic allowed" # インスタンスに隔離SGを適用(既存SGを全て置換) aws ec2 modify-instance-attribute \ --instance-id i-0123456789abcdef0 \ --groups sg-isolation # EBSスナップショットを取得 aws ec2 create-snapshot \ --volume-id vol-0123456789abcdef0 \ --description "Forensic snapshot - incident investigation"
3
被害範囲の調査
CloudTrailで不正なAPI呼び出しを特定
🔍 15-60分
  • GuardDutyの検出結果から不正なIPアドレスを確認
  • CloudTrailで該当IAMロールのすべてのAPI呼び出しを調査
  • 新規作成されたリソース(IAMユーザー、アクセスキー等)がないか確認
  • S3バケットへのアクセス、データ漏洩の有無を確認
# CloudTrailで該当ロールのAPI呼び出しを調査 aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=Username,AttributeValue=CompromisedEC2Role \ --start-time "2024-01-01T00:00:00Z" \ --end-time "2024-01-02T23:59:59Z" \ --query 'Events[*].{Time:EventTime,Event:EventName,Source:EventSource}' # 特定のIPからのアクセスを調査 aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=ASIAXXXXXXXXXXX
4
侵入経路の特定
どうやって認証情報が漏洩したか調査
📋 1時間以内
  • EC2インスタンスのアプリケーションログを確認
  • SSRF脆弱性(ユーザー入力をURLに使用している箇所)を調査
  • IMDSへのアクセスログ(169.254.169.254)を確認
  • RCE(リモートコード実行)の痕跡がないか確認
5
復旧と再発防止
安全な環境を再構築
📋 調査完了後
  • 新しいEC2インスタンスを作成(侵害されたインスタンスは破棄)
  • IMDSv2を強制適用
  • IAMロールの権限を最小権限に見直し
  • 脆弱性のあったアプリケーションを修正
# 新規EC2インスタンスでIMDSv2を強制 aws ec2 run-instances \ --image-id ami-xxxxxxxxx \ --instance-type t3.medium \ --metadata-options "HttpTokens=required,HttpPutResponseHopLimit=1,HttpEndpoint=enabled" # 既存インスタンスをIMDSv2に変更 aws ec2 modify-instance-metadata-options \ --instance-id i-0123456789abcdef0 \ --http-tokens required \ --http-put-response-hop-limit 1 \ --http-endpoint enabled

🤖 EventBridge + Lambda による自動対応

🚨
GuardDuty
📡
EventBridge
Lambda
🛡️
自動修復

⚡ Lambda関数(Python)- 自動対応

import boto3 import json from datetime import datetime def lambda_handler(event, context): """ GuardDuty InstanceCredentialExfiltration アラートの自動対応 """ iam = boto3.client('iam') ec2 = boto3.client('ec2') sns = boto3.client('sns') # GuardDutyの検出結果から情報を取得 finding = event['detail'] finding_type = finding['type'] instance_id = finding['resource']['instanceDetails']['instanceId'] role_name = finding['resource']['accessKeyDetails']['userName'] # 対象のアラートタイプか確認 if 'InstanceCredentialExfiltration' not in finding_type: return {'statusCode': 200, 'body': 'Not target finding type'} # 1. IAMロールのセッションを無効化 current_time = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') revoke_policy = { "Version": "2012-10-17", "Statement": [{ "Effect": "Deny", "Action": "*", "Resource": "*", "Condition": { "DateLessThan": {"aws:TokenIssueTime": current_time} } }] } iam.put_role_policy( RoleName=role_name, PolicyName='AutoRevokeOlderSessions', PolicyDocument=json.dumps(revoke_policy) ) # 2. EC2インスタンスを隔離(隔離用SGに変更) # 注: 事前に隔離用SGを作成しておく必要あり ec2.modify_instance_attribute( InstanceId=instance_id, Groups=['sg-isolation-xxxxxxxx'] # 隔離用SG ) # 3. SNSで通知 sns.publish( TopicArn='arn:aws:sns:ap-northeast-1:123456789012:security-alerts', Subject='🚨 [CRITICAL] EC2認証情報漏洩を検出・自動対応実行', Message=f""" GuardDutyが認証情報の外部使用を検出しました。 🔴 検出タイプ: {finding_type} 🖥️ インスタンスID: {instance_id} 🪪 IAMロール: {role_name} ✅ 自動対応を実行しました: 1. IAMロールの既存セッションを無効化 2. EC2インスタンスを隔離用SGに変更 ⚠️ 追加調査が必要です。CloudTrailを確認してください。 """ ) return { 'statusCode': 200, 'body': 'Auto-remediation completed' }

📡 EventBridgeルール

{ "source": ["aws.guardduty"], "detail-type": ["GuardDuty Finding"], "detail": { "type": [ {"prefix": "UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration"} ], "severity": [{"numeric": [">=", 7]}] } }

📦 IMDSv2強制のCloudFormationテンプレート

AWSTemplateFormatVersion: '2010-09-09' Description: 'EC2 Instance with IMDSv2 enforced' Parameters: InstanceType: Type: String Default: t3.medium Resources: # IMDSv2を強制したEC2インスタンス SecureEC2Instance: Type: AWS::EC2::Instance Properties: ImageId: !Ref LatestAmiId InstanceType: !Ref InstanceType IamInstanceProfile: !Ref EC2InstanceProfile MetadataOptions: HttpTokens: required # IMDSv2を強制 HttpPutResponseHopLimit: 1 # コンテナからのアクセスを制限 HttpEndpoint: enabled InstanceMetadataTags: enabled # 最小権限のIAMロール EC2Role: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: ec2.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore # 必要最小限のインラインポリシーのみ追加 # SCP: 組織全体でIMDSv1を禁止 Outputs: SCPExample: Description: 'Example SCP to enforce IMDSv2' Value: | { "Version": "2012-10-17", "Statement": [{ "Sid": "RequireIMDSv2", "Effect": "Deny", "Action": "ec2:RunInstances", "Resource": "arn:aws:ec2:*:*:instance/*", "Condition": { "StringNotEquals": { "ec2:MetadataHttpTokens": "required" } } }] }

✅ インシデント対応チェックリスト

🔴 初動対応(0-15分)

  • GuardDutyの検出結果を確認
  • IAMロール名を特定
  • セッション無効化ポリシーを適用
  • EC2インスタンスを隔離
  • 関係者に通知

🔵 調査(15-60分)

  • CloudTrailでAPI呼び出しを調査
  • 不正なリソース作成がないか確認
  • S3アクセスログを確認
  • 侵入経路を特定
  • EBSスナップショットを取得

🟢 復旧(1-24時間)

  • 新しいEC2インスタンスを作成
  • IMDSv2を強制適用
  • アプリケーションの脆弱性を修正
  • IAMロールの権限を見直し
  • 侵害されたインスタンスを終了

🟣 再発防止(継続)

  • SCPでIMDSv2を組織全体で強制
  • 自動対応Lambdaを設定
  • インシデント報告書を作成
  • チームに教訓を共有
  • 定期的なセキュリティ監査を計画

🛡️ 多層防御による再発防止

🔵 組織レベル: SCP
🟢 アカウントレベル: Config Rules
🟠 インスタンスレベル: IMDSv2
🪪
IAM認証情報
(守られている!)
🔐

IMDSv2の強制

  • HttpTokens=requiredを設定
  • HttpPutResponseHopLimit=1でコンテナ保護
  • 既存インスタンスも順次移行
  • 起動テンプレートでデフォルト化
📏

最小権限の原則

  • IAMロールに必要最小限の権限のみ
  • ワイルドカード(*)の使用を避ける
  • リソースレベルの制限を設定
  • 定期的な権限の棚卸し
🏛️

SCPによる組織統制

  • IMDSv1でのインスタンス起動を禁止
  • 全アカウントに一括適用
  • 例外管理のプロセスを整備
  • コンプライアンスの自動化
📊

継続的な監視

  • GuardDutyアラートの自動通知
  • Config Rulesでコンプライアンス監視
  • Security Hubで一元管理
  • 定期的なセキュリティ監査

❓ よくある質問

🤔 誤検知の可能性はある?どう判断する?
はい、以下の場合は誤検知(正当な使用)の可能性があります:

VPN/Direct Connect経由:オンプレミスから正規にアクセスしている場合
NAT Gateway経由:別のVPCのEC2からNAT経由でアクセスしている場合
プロキシサーバー経由:正規のプロキシを使用している場合
AWS Lambda:EC2の認証情報を正規に使用するLambda

判断のポイント:
1. 発信元IPアドレスは既知のものか?
2. 実行されたAPIは正常な業務に関連するか?
3. 時間帯は通常の業務時間内か?

⚠️ ただし、誤検知の判断は慎重に行い、まずは対応を優先してください。
🤔 EC2を停止すれば認証情報は無効になる?
❌ いいえ!EC2を停止・終了しても認証情報は有効なままです。

EC2のIAMロールが発行する一時的な認証情報(STSトークン)は、最大12時間有効です。
EC2インスタンスの状態に関係なく、有効期限が切れるまで使用可能です。

正しい対処:
1. IAMロールに「セッション無効化ポリシー」を追加
2. これにより、ポリシー追加前に発行された全セッションが無効化される
3. その上でEC2を隔離・調査
🤔 .OutsideAWSと.InsideAWS、どちらが危険?
どちらも危険ですが、.OutsideAWSの方がより深刻です。

🔴 .OutsideAWS(重大度: 8.0)
認証情報がAWS外部(インターネット上の攻撃者サーバー等)から使用されています。
これは明らかな攻撃であり、認証情報が完全に漏洩していることを意味します。

🟠 .InsideAWS(重大度: 7.5)
認証情報が別のAWSアカウントやリージョンから使用されています。
攻撃者が別のAWSアカウントを持っている場合や、侵害された別のEC2を踏み台にしている可能性があります。

いずれにせよ、即座に対応が必要です。
🤔 IMDSv2に移行すると既存アプリが動かなくなる?
AWS SDKやCLIの最新バージョンを使用していれば、ほとんどの場合問題ありません。

確認が必要なケース:
• 古いAWS SDK(2019年以前のバージョン)を使用している場合
• IMDSに直接curlでアクセスしているスクリプトがある場合
• コンテナ環境でホップ数制限の影響を受ける場合

移行手順:
1. まず「optional」モードでIMDSv2を有効化
2. CloudWatchでIMDSv1アクセスを監視(MetadataNoToken メトリクス)
3. IMDSv1へのアクセスがなくなったら「required」に変更

AWS SDKは自動的にIMDSv2を使用するため、通常は問題が発生しません。

🎓 まとめ

🚨

アラートの意味

EC2の認証情報が
外部から悪用されている

最優先対応

IAMロールの
セッション即時無効化

🔍

調査のポイント

CloudTrailで
不正API呼び出しを確認

🔐

根本対策

IMDSv2の強制で
SSRF攻撃を防止

🏛️

組織統制

SCPで組織全体に
IMDSv2を強制

🏢 マンションの社員証が盗まれたら?

1️⃣ 社員証を即座に無効化(IAMロールのセッション取り消し)
2️⃣ 泥棒がいた部屋を隔離(EC2インスタンスの隔離)
3️⃣ どこに侵入されたか調査(CloudTrailでAPI呼び出し確認)
4️⃣ セキュリティを強化した新しい部屋を用意(IMDSv2強制の新EC2)
5️⃣ マンション全体のセキュリティを見直し(SCPで組織全体に適用)

🚨 このアラートは「今すぐ対応が必要」な緊急事態です!

Created by SSuzuki1063

AWS SAP Learning Resources