investigating-aws-incidents について
AWS の侵害を調査するインシデント対応担当者向けのスキルです。CloudTrail や VPC Flow Logs などを相関し、主体を特定して活動の時系列を再構成し、封じ込め前の証拠保全を重視します。
主な機能
- 01主体と認証情報の特定
- 02CloudTrail イベントの相関
- 03IAM 永続化の確認
- 04GuardDuty 検出結果の調査
- 05S3 とスナップショット流出の確認
活用シーン
- 01漏えいした AWS アクセスキーの調査
- 02異常な API 呼び出しや GuardDuty 警告の追跡
- 03IAM 永続化の疑いの確認
- 04S3 またはスナップショットからの窃取評価
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trilwu/ secskills --skill investigating-aws-incidentsインストール後、Claude Code で/investigating-aws-incidentsを入力して読み込まれたか確認します。
詳細
AWS インシデントの調査
AWS のインシデントは、通常、攻撃者が削除できなかったログ(CloudTrail、VPC Flow Logs、コントロールプレーンが記録したすべての API 呼び出しの記録)から再構成できます。そのため、調査では侵害されたプリンシパルを軸にログを相関させます。具体的には、アクセスキーまたは引き受けたロールと、それが実行した一連の API 呼び出しを追跡します。プリンシパルを特定し、それが生成したすべてのイベントを取得すれば、侵入の全容がタイムラインから明らかになります。
使用する場合
- AWS アクセスキーが露出または漏えいした場合(リポジトリへのコミット、pastebin への投稿、または AWS Abuse によるフラグ付け)
- CloudTrail に異常なアクティビティがある場合(見慣れないリージョン、IP、またはユーザーエージェントからの API 呼び出し)
- GuardDuty の検出結果がある場合(認証情報の窃取、Tor トラフィック、暗号通貨マイニング、または異常な IAM の動作)
- 予期しない IAM の変更がある場合(許可なく作成されたユーザー、キー、ロール、ログインプロファイル、またはポリシーのアタッチ)
- EC2 で暗号通貨マイニングが発生している場合(オンデマンドインスタンスや GPU ファミリーの急増、または予期しない請求アラート)
- S3 データの持ち出しがある場合(GetObject の急増、公開されたバケット、または共有されたスナップショット)
使用しない場合
- インシデントが AWS ではなく Microsoft 365 / Entra ID で発生している場合 —
investigating-m365-entraを使用してください - インシデントが Azure のリソース/サブスクリプションで発生している場合 —
investigating-azure-incidentsを使用してください - インシデントが Google Cloud で発生している場合 —
investigating-gcp-incidentsを使用してください - 一般的な IR プロセスやホストレベルの対応の場合 —
responding-to-incidentsを使用してください - 対応者ではなく攻撃者の場合 —
exploiting-cloud-platformsを使用してください - 調査対象が EKS 上の Kubernetes に限定されている場合 —
attacking-eks-gke-aksを使用してください - インシデントが確認されていない状態で、予防的な脅威ハンティングを行う場合 —
hunting-threatsを使用してください
最初の1時間のトリアージ
次の3つのアクションを順番に行います。プリンシパルを特定し、その最近のアクティビティを取得し、封じ込める前に証拠を保全します。
侵害されたプリンシパルの範囲を特定します。 漏えいしたキー、GuardDuty の検出結果、請求額の急増のいずれであっても、1つのプリンシパル ARN(IAM ユーザー、ロール、またはルートアカウント)に特定します。この ARN が以降の調査すべての基点になります。
# What is this key/session, and does it still work?
aws sts get-caller-identity # if you hold the suspect creds
# Resolve an access key ID to its owner
aws iam get-access-key-last-used --access-key-id AKIA...
# Enumerate the principal's current footprint
aws iam list-access-keys --user-name <user>
aws iam list-attached-user-policies --user-name <user>
aws iam list-user-policies --user-name <user>
プリンシパルの最近のアクティビティを取得します。 イベント履歴(以下を参照)は最も手早く初動の確認ができる手段です。S3 のログバケットが信頼できる情報源です。
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=Username,AttributeValue=<user> \
--start-time 2026-07-01T00:00:00Z --max-results 200
# By access key -- catches role sessions that lookup-by-username misses
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIA...
気付かれずに隔離します — スナップショットを取得してから封じ込めます。 攻撃者が操作の途中でキーを無効化されたことに気付くと、まだ発見できていない永続化の手段を使ってくるおそれがあります。進行中の被害がある場合を除き、まず証拠を保全し(ボリュームのスナップショットを取得し、ログをエクスポートします)、永続化の手段を特定してから、すべてをまとめて封じ込めます。実被害が進行中(マイニングやデータ持ち出しが継続中)の場合は、被害を止めることを優先し、その代償を受け入れます。
CloudTrail の詳細解説
イベント履歴と S3 ログバケットの違い。 コンソールのイベント履歴は検索可能ですが、管理イベントは 90 日分に限られ、データイベントは記録されません。CloudTrail の S3 ログバケット(または CloudTrail Lake)が正式な記録であり、S3/Lambda のデータイベントが記録される唯一の場所です。最初に確認する段階を過ぎたら、コンソールではなくここをクエリしてください。実際に記録されている内容を確認します。
aws cloudtrail describe-trails
aws cloudtrail get-trail-status --name <trail> # IsLogging: true?
aws cloudtrail get-event-selectors --trail-name <trail> # data events on?
userIdentity の種類から、何を確認しているのかが分かります。
type | 意味 | 調査上の注意点 |
|---|---|---|
IAMUser | 長期間有効なユーザー認証情報 | accessKeyId を手掛かりにします。人間のユーザーか、サービスアカウントかを確認してください。 |
AssumedRole | 一時的な STS 認証情報 | sessionContext.sessionIssuer を確認し、元のロールを特定します。 |
AWSService | AWS サービスによる操作 | 通常は問題ありませんが、偽装のように見えるサービス呼び出しがないか確認してください。 |
Root | ルートアカウント | API 呼び出しで正当なケースはほとんどありません。重大な事象として扱ってください。 |
FederatedUser / WebIdentityUser | GetFederationToken ブローカー/OIDC ウェブアイデンティティ | ブローカーの IAM ユーザー、または IdP のセッションまで追跡してください。 |
AssumedRole の場合、sessionContext.sessionIssuer.arn にロール名が記載され、sessionContext.attributes.mfaAuthenticated から MFA が使用されたかどうかが分かります。
grep する異常フィールド:
sourceIPAddress-- VPC 内でのみ使用されるはずのロール認証情報が、外部 IP から使われていないか確認します(後述の IMDS からの窃取を示す兆候です)。VPC Flow Logs と照合してください。userAgent-- 通常はコンソールまたは Lambda からの SDK エージェントが表示されるプリンシパルで、aws-cli/2.x、Boto3、python-requests、またはkaliを含むユーザーエージェントがないか確認します。awsRegion-- 運用していないリージョンでの呼び出しを確認します(攻撃者は注意をそらすため、ap-*/sa-*でマイニングを開始することがあります)。列挙では、短時間に多数のリージョンが対象になります。errorCode--AccessDenied/UnauthorizedOperationが大量に発生している場合は列挙を示しています。攻撃者が、窃取したプリンシパルで何ができるかを調べています。
-- Athena over the CloudTrail S3 bucket: AccessDenied enumeration storm
SELECT eventname, count(*) AS n
FROM cloudtrail_logs
WHERE useridentity.accesskeyid = 'AKIA...'
AND errorcode = 'AccessDenied'
AND eventtime > '2026-07-01T00:00:00Z'
GROUP BY eventname ORDER BY n DESC;
攻撃者の典型的な API パターン
タイムラインで次の一連の操作を grep してください。窃取されたキーによる侵入のほとんどは、このパターンを示します。
GetCallerIdentity-- 最初の呼び出しであることがよくあります。攻撃者はキーが何で、アカウントの所有者が誰なのかを確認しています。- 列挙 -- IAM、S3、EC2、RDS、Secrets Manager 全体での
List*/Get*/Describe*。AccessDeniedが大量に発生することもよくあります。 - 権限昇格 --
CreateUser、CreateAccessKey、AttachUserPolicy(AdministratorAccessに注意)、PutUserPolicy(アタッチ済みポリシーの一覧に表示されないインラインポリシー)、CreateLoginProfile(API 専用アカウントにコンソールパスワードを設定)、UpdateLoginProfile。 iam:PassRoleの悪用 -- 高い権限を持つロールを新しい EC2 インスタンス、Lambda、または Glue ジョブに渡し、その権限を引き継がせます。PassRoleとRunInstances/CreateFunctionの組み合わせを探してください。- 信頼ポリシーの改ざん --
UpdateAssumeRolePolicy、または外部アカウントを信頼ポリシーに指定したCreateRole(クロスアカウントのバックドア)。 - STS の連鎖 --
AssumeRoleでより高い権限を持つロールに移行し、さらに別のロールへ移行します。元の窃取キーをたどれないようにする連鎖を構築します。
# Pull the IAM mutating calls for the window
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=CreateAccessKey
# Repeat for: CreateUser, AttachUserPolicy, PutUserPolicy, CreateLoginProfile,
# UpdateAssumeRolePolicy, CreateRole, AssumeRole
# (iam:PassRole is a permission, not an event -- find it in requestParameters of
# RunInstances / CreateFunction, not via lookup-by-EventName)
永続化の調査
封じ込め時には、各メカニズムを明示的にすべて調査してください。漏洩したキーを 1 つローテーションしても、攻撃者が作成した 2 つ目のキーには対処できません。
- インシデント期間中に作成された新しい IAM ユーザー/キー/ロール。
- 既存ユーザーに追加された 2 つ目のアクセスキー -- 被害者または別のアカウントでの
CreateAccessKey。ユーザーごとに最大 2 つのキーを持てます。 - サービスアカウントのコンソールログインプロファイル -- コンソールを使ったことのないプリンシパルに対する
CreateLoginProfileは、強い兆候です。 - 変更されたロールの信頼ポリシー -- 外部プリンシパル、または別のアカウントからの
sts:AssumeRoleを追加するUpdateAssumeRolePolicy。 - Lambda のバックドア -- 認証情報を生成する、またはユーザーを再作成する新規または更新済みの関数。多くの場合、EventBridge のスケジュールで実行されます。
- 攻撃者の Lambda を cron で呼び出す EventBridge / CloudWatch Events のルール。
iam:CreateServiceLinkedRoleおよび、その他の目立たない高権限ロール。
# Users and keys created recently
aws iam list-users --query 'Users[?CreateDate>=`2026-07-01`].[UserName,CreateDate]'
for u in $(aws iam list-users --query 'Users[].UserName' --output text); do
aws iam list-access-keys --user-name "$u" \
--query 'AccessKeyMetadata[].[UserName,AccessKeyId,CreateDate]' --output text
done
# Roles whose trust policy names an external account
aws iam list-roles --query 'Roles[].[RoleName,AssumeRolePolicyDocument]'
# Recently modified Lambda and the EventBridge rules that fire them
aws lambda list-functions --query 'Functions[].[FunctionName,LastModified]'
aws events list-rules --query 'Rules[].[Name,ScheduleExpression,State]'
IMDS / SSRF 認証情報窃取のシグネチャ
典型的な AWS 権限昇格です。EC2 インスタンス上で SSRF や足がかりを得た攻撃者が、Instance Metadata Service(http://169.254.169.254/latest/meta-data/iam/...)を読み取り、インスタンスロールの一時認証情報を盗み出して別の場所で使用します。
CloudTrail のシグネチャは明白です。インスタンスロールのセッション認証情報が、そのインスタンスではない sourceIPAddress から使用されています。 ロールはそのインスタンス用に発行されるため、外部または無関係な IP からの呼び出しがあれば、認証情報がインスタンスの外に持ち出されたことを意味します。
-- Role session creds used from outside the VPC
SELECT eventtime, eventname, sourceipaddress, useragent
FROM cloudtrail_logs
WHERE useridentity.arn LIKE '%assumed-role/<instance-role>%'
AND sourceipaddress NOT LIKE '10.%'
AND sourceipaddress NOT LIKE '172.%'
ORDER BY eventtime;
IMDSv1(セッショントークン不要の単純な GET)では窃取が容易であり、それ自体が検出事項です。aws ec2 describe-instances を使い、インスタンスで IMDSv2(HttpTokens: required)が必須になっているか確認してください。窃取が発生した時間帯を、アウトバウンドの SSRF と認証情報の再利用元に関する VPC Flow Logs と照合します。
GuardDuty の検出結果のトリアージ
GuardDuty は調査の開始を告げる合図であり、調査そのものではありません。各検出タイプから仮説を立て、CloudTrail で確認します。
| 検出タイプ | 意味 |
|---|---|
UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.* | インスタンスロールの認証情報がインスタンス外で使用されています。上記の IMDS 窃取です。 |
UnauthorizedAccess:IAMUser/MaliciousIPCaller | 既知の不正 IP からプリンシパルが呼び出しを行いました。 |
UnauthorizedAccess:IAMUser/TorIPCaller | Tor 経由の API 呼び出しです。正当な管理者によるものとはほとんど考えられません。 |
CryptoCurrency:EC2/BitcoinTool.B!DNS | インスタンスがマイニングプールと通信しています。暗号資産のマイニングが確認されています。 |
Recon:IAMUser/* | 列挙です。AccessDenied が大量に発生しています。 |
Persistence:IAMUser/*、PrivilegeEscalation:IAMUser/* | 上記の権限昇格パターンに一致する IAM の変更です。 |
Policy:S3/BucketAnonymousAccessGranted | バケットが公開されました。持ち出し用の中継地点にされた可能性があります。 |
aws guardduty list-findings --detector-id <id> \
--finding-criteria '{"Criterion":{"severity":{"Gte":4}}}'
aws guardduty get-findings --detector-id <id> --finding-ids <id>
CloudTrail の保持期間を過ぎた検出結果にも、プリンシパルと IP が記録されています。Event history の生イベントが期限切れになっていても、それらを手がかりに調査してください。
データ窃取の検出
- S3 GetObject の急増 — 機密バケットで
GetObjectの回数やバイト数が急増しています。S3 データイベントが記録されている場合にのみ確認できます。プリンシパル別にリクエスト数を確認してください。 - バケットの公開 —
PutBucketPolicy/PutBucketAclでAllUsersまたはAuthenticatedUsersに権限を付与する操作、あるいはブロックを無効にするPutPublicAccessBlock。 - スナップショットの共有 —
ModifySnapshotAttributeまたはModifyImageAttributeで外部アカウントまたはallをボリューム/AMI に追加します(スナップショットを外部共有してデータを盗み出します)。 - RDS からの持ち出し — DB スナップショットを共有する
ModifyDBSnapshotAttribute、または攻撃者が管理する S3 バケットにスナップショットを出力するStartExportTask。
SELECT eventname, useridentity.arn, sourceipaddress,
json_extract_scalar(requestparameters, '$.attributeType') AS attr
FROM cloudtrail_logs
WHERE eventname IN ('ModifySnapshotAttribute','ModifyImageAttribute',
'ModifyDBSnapshotAttribute','PutBucketPolicy','PutBucketAcl')
AND eventtime > '2026-07-01T00:00:00Z';
攻撃者が試みるアンチフォレンジック
能力のある攻撃者は、調査を妨げようとします。次の操作に注意し、特に、それらを回避する手段も講じてください。
StopLogging/DeleteTrail— CloudTrail を停止します。PutEventSelectors— トレイルを削除せずに、記録対象を絞り込みます(データイベントやリージョン全体を除外します)。DeleteFlowLogs— ネットワーク側の痕跡を隠すため、VPC Flow Logs を削除します。DeleteDetector/UpdateDetector(無効化)/停止 — GuardDuty を停止します。
これらすべてへの対策は、メンバーアカウントに依存しない Organizations レベルのトレイルを使用して、侵害されたプリンシパルがアクセスできない、中央のロックされた S3 バケットにログを記録することです(MFA 削除、Object Lock、ログアーカイブ専用の別アカウント)。StopLogging 自体も、効果が発生する前にそのバケットへ記録されます。組織トレイルがあれば、攻撃者による証拠隠滅の操作は欠落ではなく証拠になります。組織トレイルがない場合は、可視性のない期間を調査範囲の制限事項として記録してください。
# Was logging tampered with? These calls are the finding.
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=StopLogging
# Repeat: DeleteTrail, PutEventSelectors, DeleteFlowLogs, DeleteDetector
証拠の保全
-
すべての対象インスタンスのボリュームの EBS スナップショットを、インスタンスに触れる前に取得します。ケース ID をタグ付けし、リソースポリシー/法的保全措置を適用して削除できないようにします。
aws ec2 create-snapshot --volume-id vol-xxx \ --description "IR-2026-042 preserve" \ --tag-specifications 'ResourceType=snapshot,Tags=[{Key=case,Value=IR-2026-042},{Key=legal-hold,Value=true}]' -
稼働中インスタンスのメモリを取得してから終了します。常駐型インプラントやメモリ内の認証情報を調べる場合、これが唯一の情報源です。取得後、
analyzing-memory-imagesに従って分析します。 -
該当する期間の CloudTrail をエクスポートして保全された場所に保存し、保持期間が切れる前に VPC Flow Logs と GuardDuty の検出結果をコピーします。
-
すべての証拠資料にタグを付け、法的保全措置を適用します。インシデントが規制対応や訴訟につながる可能性がある場合は、収集前に法務部門を関与させます。
封じ込めと根絶
スコープを特定してから、すべてを一度に実施します。部分的な封じ込めは攻撃者に警告してしまいます。
-
キーは削除せず、無効化します。削除すると証拠が失われますが、無効化したキーはタイムラインに残ります。
aws iam update-access-key --user-name <user> \ --access-key-id AKIA... --status Inactive -
有効なセッションを取り消します。キーを無効化しても、そのキーから発行された進行中の一時セッションは終了しません。インラインの拒否ポリシーを適用し、現在より前に発行されたすべてのセッション/トークンを無効化します(
AWSRevokeOlderSessionsパターン)。aws iam put-user-policy --user-name <user> \ --policy-name AWSRevokeOlderSessions \ --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Deny", "Action":"*","Resource":"*","Condition":{"DateLessThan": {"aws:TokenIssueTime":"2026-07-20T00:00:00Z"}}}]}'ロールの場合は、ロールのインラインポリシーまたは境界に同等の拒否を設定します。
-
プリンシパルがアクセスできたすべての認証情報をローテーションします。他のキー、プリンシパルが読み取った Secrets Manager/SSM 内のシークレット、侵害されたインスタンス上にハードコードされた認証情報が対象です。
-
セキュリティグループで隔離します。マイニングやデータ流出に使われたインスタンスは終了せず、送信通信を許可しないセキュリティグループに移動し、分析に必要なメモリとディスクを保持します。
-
攻撃者による永続化を除去します。作成されたユーザー/キー/ロールの削除、改ざんされた信頼ポリシーの復元、バックドアとなる Lambda や EventBridge ルールの削除は、記録を残した後にのみ行います。
退けるべき合理化
- 「GuardDuty がアラートを出していないので、何も起きていません。」 GuardDuty がカバーするのは一部の動作に限られ、適切なリージョンで有効になっていることが前提です。検出結果がないことは、事象がなかった証拠にはなりません。CloudTrail のタイムラインが信頼できる情報源です。
- 「漏えいしたキーをローテーションしたので、対応は完了です。」 漏えいしたキーは最初の一歩にすぎません。2 つ目のキー、新しいユーザー、変更された信頼ポリシー、バックドアとなる Lambda はローテーション後も残ります。対応を終了する前に、すべての永続化メカニズムを洗い出してください。
- 「アクティビティの発信元は AWS の IP 範囲なので、正規のものです。」 攻撃者も EC2 上でツールを実行できます。IP の所有者だけでなく、プリンシパル、ユーザーエージェント、動作を相関分析してください。
- 「CloudTrail に CreateUser がないので、永続化はありません。」 インラインポリシー(
PutUserPolicy)、既存ユーザーへの 2 つ目のアクセスキー、変更されたロール信頼ポリシーは、ユーザーを作成せずに永続化を実現できます。 - 「暗号資産のマイニングにすぎないので、優先度は低いです。」 マイニングが行われたということは、
RunInstancesを実行できるプリンシパルが侵害されたということです。同じアクセス権でデータを流出させたり、権限を昇格したりすることも可能です。マイニングは目に見える症状であり、侵害範囲そのものではありません。 - 「インスタンスロールの権限は低いので、SSRF は問題になりません。」 必ず確認してください。
iam:PassRoleとAssumeRoleの連鎖によって、権限が控えめなインスタンスロールからアカウント全体にアクセスできるようになることは珍しくありません。推測に頼らず、ロールがアクセスできる範囲を追跡してください。 - 「ログは 90 日分しかないので、侵害は 90 日以内に始まったはずです。」 それは可視性の限界であり、攻撃者の活動期間ではありません。スコープ特定上の不足として記録し、保持期間がより長い組織のトレイル/Lake を確認してください。
参考資料
investigating-m365-entra-- M365/Entra ID インシデント向けの関連クラウド IR スキルresponding-to-incidents-- 一般的な IR プロセス、証拠の取り扱い、ホストレベルの対応exploiting-cloud-platforms-- 攻撃側の視点。これらの AWS TTP がどのように実行されるかattacking-eks-gke-aks-- ピボット先が EKS 上の Kubernetes の場合analyzing-memory-images-- Volatility を使用したインスタンスのメモリキャプチャの分析hunting-threats-- インシデントが確認されていない場合のプロアクティブなハンティングreporting-security-findings-- インシデントの経緯と成果物の構成- AWS CLI、Athena、CloudTrail Lake -- 信頼できるログのクエリ
cloudtrail-partitioner-- CloudTrail S3 バケットをパーティション化して、Athena クエリを高速化- Prowler -- アカウントの事後的なセキュリティ態勢および設定ミスの評価
stratus-red-team-- AWS 攻撃 TTP をエミュレートし、それぞれが CloudTrail に何を残すかを把握- AWS セキュリティインシデント対応ガイド、GuardDuty の検出結果タイプのリファレンス