深夜2時。「本番アカウントで見覚えのないIAMユーザーが作られている」というアラートで叩き起こされたとします。あなたが最初に見るべきは何でしょうか。
答えは1つです。CloudTrail はまだ生きているか。 攻撃者が最初にやることの定番が「証跡を止めて足跡を消す」ことだからです。証跡が止められた後のログには、肝心の侵害行為が映っていません。検知も調査も、まずここから始まります。
私はサーバーレス(Lambda + DynamoDB)の決済プラットフォームの信頼性レイヤーを設計・主導し、本番稼働中の二重課金0件を維持してきました。その規律の核は「正しさを、後からでも否認不能に証明できる状態を、最初から設計しておく」ことです。お金が動くシステムでは、「たぶん大丈夫」は通用しません。誰が・いつ・どの権限で・どこから何をしたかを改ざん不可能な形で残し、いざという時に秒単位で引ける——その土台が CloudTrail を中心としたセキュリティ運用 です。
この記事は、CloudTrail を「監査ログの置き場」で終わらせず、脅威検知・不正検知・インシデント調査(フォレンジック)の実戦プレイブックとして組み上げるためのガイドです。検知の実コード、CISベンチマーク準拠の監視、GuardDuty/Security Hub/Detectiveとの連携、Athena/Lakeの調査クエリ、そして証拠保全までを一気通貫で扱います。
この記事の前提と分担:CloudTrail の基本設定(マルチリージョン証跡・暗号化・整合性検証の有効化・EventBridge/CloudWatch連携の仕組みそのもの)は CloudTrail 完全ガイド(ピラー記事) が担当します。本記事はそこを土台に、セキュリティ運用とフォレンジックの深掘りに集中します。仕様・条件・Finding名はすべて AWS 公式ドキュメント(2026年6月時点)に照合しています。料金・マネージド機能のステータスは改定が速いので、本番投入前に必ず最新の公式を確認してください。アカウントID(
111122223333)・バケット名・リージョンは例示です。
0. メンタルモデル:CloudTrail は「検知」と「調査」の土台、そして「証拠」
セキュリティ運用の文脈で、CloudTrail の役割を3つに分けて固定します。これがこの記事全体の地図です。
検知(Detection)= いま起きていることに気づく。 リアルタイム性が命。EventBridge / CloudWatch メトリクスフィルタ / GuardDuty。
調査(Investigation)= 過去に何が起きたかを横断クエリで再構成する。 網羅性が命。Athena / CloudTrail Lake。
証拠(Evidence)= 「確かにこの認証情報がこのAPIを叩いた」と否認不能に証明する。 完全性が命。ログ整合性検証 / S3 Object Lock。
| 観点 | 何で実現するか | 重視する性質 | 時間軸 |
|---|---|---|---|
| 検知 | EventBridge → Lambda/SNS、CloudWatch メトリクスフィルタ+アラーム、GuardDuty | レイテンシ(秒〜分) | いま |
| 調査 | Athena(S3上のログ)、CloudTrail Lake(Trino SQL) | 網羅性・横断性 | 過去(90日超) |
| 証拠 | ログ整合性検証(SHA-256 / digest チェーン)、S3 Object Lock / MFA Delete | 完全性・否認防止 | 事後 |
CloudTrail のイベントには、検知・調査の両方で繰り返し使う「核となるフィールド」があります。これを身体に入れておくと、後のクエリもフィルタもすべて読み解けます(公式の userIdentity / イベントレコード仕様より)。
| フィールド | 意味 | 検知・調査での使いどころ |
|---|---|---|
userIdentity.type | 呼び出し主体の種別 | Root / IAMUser / AssumedRole / Role / FederatedUser / AWSService / IdentityCenterUser |
userIdentity.arn | 主体のARN | 侵害プリンシパルの特定・全行動の追跡キー |
userIdentity.sessionContext.attributes.mfaAuthenticated | MFA認証されたセッションか | false のサインインを警戒 |
eventName | 呼ばれたAPI | StopLogging、CreateAccessKey など、操作の中身 |
eventSource | サービス | cloudtrail.amazonaws.com、iam.amazonaws.com など |
sourceIPAddress | 呼び出し元IP | 不審なIP・Tor・国外からのアクセス |
errorCode | エラー | AccessDenied / UnauthorizedOperation の急増=偵察の兆候 |
awsRegion | リージョン | 使っていないリージョンでの操作=侵害の兆候 |
readOnly | 読み取り専用か | 書き込み系(破壊的操作)を優先監視 |
注意:
userIdentity.typeの正しい値にIdentityCenterUserはありますが、IAMIdentityCenterという値は存在しません。フィルタやクエリを書くときに混同しないこと。
1. 最優先の検知:攻撃者は最初に「証跡を止め」にくる
冒頭のシナリオに戻ります。インシデント検知で最も価値が高い1本は、地味ですが「CloudTrail 自体への改ざん操作」の即時検知です。なぜなら、ここを止められると以降のすべての検知・調査の前提が崩れるからです。
監視すべき eventSource は cloudtrail.amazonaws.com、eventName は次の4つが中心です。
| eventName | 攻撃者の意図 |
|---|---|
StopLogging | 証跡を止めてログ記録を停止する(足跡消し) |
DeleteTrail | 証跡そのものを削除する |
UpdateTrail | 証跡の設定を改ざん(マルチリージョン解除・ログ先変更など) |
PutEventSelectors | 記録対象イベントを絞り、自分の操作を記録対象外にする |
これは「過去のログを後で見返す」では遅すぎます。ニアリアルタイムで秒単位に検知する必要があるため、CloudWatch メトリクスフィルタ(数分のバッファがある)ではなく、EventBridge → Lambda/SNS が第一選択です。EventBridge は CloudTrail のAPIコールを detail-type: "AWS API Call via CloudTrail" として受け取れます。
EventBridge ルール(Terraform)
# 証跡改ざん操作をニアリアルタイムで捕捉する EventBridge ルール
resource "aws_cloudwatch_event_rule" "cloudtrail_tampering" {
name = "detect-cloudtrail-tampering"
description = "Detect attempts to stop, delete, or weaken CloudTrail logging"
event_pattern = jsonencode({
"detail-type" : ["AWS API Call via CloudTrail"],
"detail" : {
"eventSource" : ["cloudtrail.amazonaws.com"],
"eventName" : ["StopLogging", "DeleteTrail", "UpdateTrail", "PutEventSelectors"]
}
})
}
resource "aws_cloudwatch_event_target" "tampering_to_sns" {
rule = aws_cloudwatch_event_rule.cloudtrail_tampering.name
target_id = "notify-secops"
arn = aws_sns_topic.security_alerts.arn
}
# Lambda でトリアージ情報を整形してから通知したい場合は、こちらをターゲットに
resource "aws_cloudwatch_event_target" "tampering_to_lambda" {
rule = aws_cloudwatch_event_rule.cloudtrail_tampering.name
target_id = "triage-lambda"
arn = aws_lambda_function.tampering_triage.arn
}
トリアージ用 Lambda(TypeScript)
通知をただ飛ばすだけでなく、「誰が・どこから・どの証跡を」止めようとしたかを即座に読める形に整えます。アラートは「読めば判断できる」状態で届けてこそ意味があります。
import type { EventBridgeEvent } from "aws-lambda";
import { SNSClient, PublishCommand } from "@aws-sdk/client-sns";
const sns = new SNSClient({});
const TOPIC_ARN = process.env.SNS_TOPIC_ARN!; // 環境変数のみ。ハードコード禁止
// CloudTrail 経由の API コール詳細(必要フィールドのみ)
interface CloudTrailDetail {
eventName: string;
eventSource: string;
sourceIPAddress?: string;
awsRegion?: string;
userIdentity?: {
type?: string;
arn?: string;
sessionContext?: { attributes?: { mfaAuthenticated?: string } };
};
requestParameters?: Record<string, unknown>;
}
export const handler = async (
event: EventBridgeEvent<"AWS API Call via CloudTrail", CloudTrailDetail>,
): Promise<void> => {
const d = event.detail;
const id = d.userIdentity;
const message = [
"[CRITICAL] CloudTrail tampering detected",
`eventName : ${d.eventName}`,
`principal : ${id?.arn ?? "unknown"} (type=${id?.type ?? "unknown"})`,
`mfa : ${id?.sessionContext?.attributes?.mfaAuthenticated ?? "n/a"}`,
`sourceIP : ${d.sourceIPAddress ?? "unknown"}`,
`region : ${d.awsRegion ?? "unknown"}`,
`time : ${event.time}`,
`params : ${JSON.stringify(d.requestParameters ?? {})}`,
].join("\n");
await sns.send(
new PublishCommand({
TopicArn: TOPIC_ARN,
Subject: `CloudTrail tampering: ${d.eventName}`,
Message: message,
}),
);
};
設計の勘所:「証跡を止められない」ようにする予防もセットで考えます。組織レベルで
cloudtrail:StopLogging/cloudtrail:DeleteTrailを SCP で拒否すれば、メンバーアカウントの侵害プリンシパルでは証跡を止められません。SCP による多層防御とマルチアカウント監査の設計は Organization Trail / マルチアカウント監査ガイド で詳述します(本記事では深追いしません)。検知(この章)と予防(SCP)は両輪です。
2. 攻撃の兆候を検知する:CISベンチマーク準拠アラート集
証跡改ざんの次に張るべき網が、「侵害の典型的な振る舞い」への監視アラートです。ここで最重要の honesty pointを1つ。
よく知られた「root利用」「未認可API」「MFAなしサインイン」などの監視アラートは、CloudTrail のユーザーガイドの『例』ページに載っているものではありません。 CloudTrail 公式が「例」として挙げているメトリクスフィルタは、実はたった3つだけです。
CloudTrail 公式ドキュメントの「CloudWatch アラーム例」ページが提供するのは、次の3例のみです。
| 監視対象 | メトリクスフィルタが拾う eventName | メトリクス名 |
|---|---|---|
| セキュリティグループ変更 | AuthorizeSecurityGroupIngress〜DeleteSecurityGroup のSG操作群 | SecurityGroupEventCount |
| コンソールサインイン失敗 | ConsoleLogin かつ errorMessage = "Failed authentication" | ConsoleSigninFailureCount |
| IAMポリシー変更 | PutUserPolicy〜DetachGroupPolicy のIAMポリシー操作群 | IAMPolicyEventCount |
なお、コンソールサインイン失敗のフィルタパターンは公式通り次の通りです(このまま使えます)。
{ ($.eventName = ConsoleLogin) && ($.errorMessage = "Failed authentication") }
では、世間で「CloudTrail監視のベストプラクティス」として広まっている**root利用・未認可API・MFAなしサインイン・CMK無効化…**といった定番アラート群はどこから来ているのか。出典は CIS AWS Foundations Benchmark(および AWS Security Hub の CIS 標準コントロール)です。正確には、Security Hub の CloudWatch.1 〜 CloudWatch.14 コントロールが、CIS の各推奨(v1.2.0 の 3.x / v1.4.0 の 4.x)に対応しています。
なぜ出典を正しく言えることが重要か。 監査やレビューで「これは何に準拠した監視ですか」と問われたとき、「CloudTrail公式の例です」と答えるのは不正確で、信頼を損ないます。「CIS AWS Foundations Benchmark の §3/§4、Security Hub の CloudWatch コントロールに準拠しています」と言えることが、設計の説明責任そのものです。
CIS準拠の監視アラート一覧(Security Hub CloudWatch コントロール)
公式の Security Hub ユーザーガイドに基づく対応表です。各コントロールは「CloudTrail → CloudWatch Logs にログを流し、メトリクスフィルタ+アラームを置く」という同じ仕組みで実装します。
| Security Hub コントロール | 監視対象 | 対応する CIS |
|---|---|---|
| CloudWatch.1 | root ユーザーの利用 | CIS v1.2.0/3.3, v1.4.0/4.3 |
| CloudWatch.2 | 未認可API呼び出し(AccessDenied/UnauthorizedOperation) | CIS v1.2.0/3.1 |
| CloudWatch.3 | MFAなしのマネジメントコンソールサインイン | CIS v1.2.0/3.2 |
| CloudWatch.4 | IAMポリシー変更 | CIS v1.2.0/3.4, v1.4.0/4.4 |
| CloudWatch.5 | CloudTrail設定変更 | CIS v1.2.0/3.5, v1.4.0/4.5 |
| CloudWatch.6 | コンソール認証失敗 | CIS v1.2.0/3.6, v1.4.0/4.6 |
| CloudWatch.7 | CMK(顧客管理キー)の無効化・スケジュール削除 | CIS v1.2.0/3.7, v1.4.0/4.7 |
| CloudWatch.8 | S3バケットポリシー変更 | CIS v1.2.0/3.8, v1.4.0/4.8 |
| CloudWatch.9 | AWS Config設定変更 | CIS v1.2.0/3.9, v1.4.0/4.9 |
| CloudWatch.10 | セキュリティグループ変更 | CIS v1.2.0/3.10, v1.4.0/4.10 |
| CloudWatch.11 | NACL(ネットワークACL)変更 | CIS v1.2.0/3.11, v1.4.0/4.11 |
| CloudWatch.12 | ネットワークゲートウェイ変更 | CIS v1.2.0/3.12, v1.4.0/4.12 |
| CloudWatch.13 | ルートテーブル変更 | CIS v1.2.0/3.13, v1.4.0/4.13 |
| CloudWatch.14 | VPC変更 | CIS v1.2.0/3.14, v1.4.0/4.14 |
補足(公式の注記より):Security Hub のこれらのコントロールは「CISが規定する正確なメトリクスフィルタ」と完全一致しないと
FAILEDになります。フィールドや語句を独自に足すと不合格です。一方で IAMポリシー変更(CloudWatch.4)・ルートテーブル変更(CloudWatch.13) の修復手順例だけは、AWSが「IAM/EC2のAPIコールのみを対象にする」よう CIS のパターンと意図的に変えた推奨を提示しています。準拠目的なら CIS のパターンを厳密に使い、運用ノイズ削減目的なら AWS の修復例を使う、と使い分けます。
実装例1:未認可API(AccessDenied 急増)の検知 — CIS 3.1 / CloudWatch.2
侵害された認証情報を握った攻撃者は、まず「この認証情報で何ができるか」を探ります。その過程で AccessDenied / UnauthorizedOperation が短時間に急増します。これは偵察の極めて有用なシグナルです。
# CIS AWS Foundations Benchmark 3.1 / Security Hub CloudWatch.2 準拠
# 未認可API呼び出しの検知(CISが規定する正確なパターン)
resource "aws_cloudwatch_log_metric_filter" "unauthorized_api_calls" {
name = "CIS-UnauthorizedAPICalls"
log_group_name = var.cloudtrail_log_group_name # CloudTrailの配信先ロググループ
pattern = "{ ($.errorCode = \"*UnauthorizedOperation\") || ($.errorCode = \"AccessDenied*\") }"
metric_transformation {
name = "UnauthorizedAPICalls"
namespace = "CISBenchmark"
value = "1"
}
}
resource "aws_cloudwatch_metric_alarm" "unauthorized_api_calls" {
alarm_name = "CIS-3.1-UnauthorizedAPICalls"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
metric_name = "UnauthorizedAPICalls"
namespace = "CISBenchmark"
period = 300
statistic = "Sum"
threshold = 1
alarm_description = "CIS 3.1: Unauthorized API calls detected"
alarm_actions = [aws_sns_topic.security_alerts.arn]
treat_missing_data = "notBreaching"
}
実装例2:root ユーザーの利用検知 — CIS 1.7/4.3 / CloudWatch.1
root は全権限を持つため、日常運用での利用は原則ゼロであるべきです。userIdentity.type が Root で、かつ AWS サービス自身による呼び出し(invokedBy)でないものを拾います。
# CIS / Security Hub CloudWatch.1 準拠:root ユーザー利用の検知
resource "aws_cloudwatch_log_metric_filter" "root_usage" {
name = "CIS-RootAccountUsage"
log_group_name = var.cloudtrail_log_group_name
pattern = "{ $.userIdentity.type = \"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\" }"
metric_transformation {
name = "RootAccountUsage"
namespace = "CISBenchmark"
value = "1"
}
}
resource "aws_cloudwatch_metric_alarm" "root_usage" {
alarm_name = "CIS-RootAccountUsage"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
metric_name = "RootAccountUsage"
namespace = "CISBenchmark"
period = 300
statistic = "Sum"
threshold = 1
alarm_description = "CIS: Root account used"
alarm_actions = [aws_sns_topic.security_alerts.arn]
treat_missing_data = "notBreaching"
}
ノイズ対策:これらのアラームには必ず
alarm_actions(SNS等)を設定してください。Security Hub の CloudWatch.15「アラームにアクションを設定すべき」/ CloudWatch.17「アラームアクションは有効化すべき」(こちらは NIST 系コントロール)が、まさに「アラームを作ったのに通知先が無い/無効」という典型的な穴を突きます。検知の最後の1メートル=通知が繋がっていなければ、検知器は存在しないのと同じです。
3. マネージド検知に乗る:GuardDuty / Security Hub / Detective
メトリクスフィルタは「事前に決めたパターン」しか拾えません。未知の・異常な振る舞いを捕まえるには、CloudTrail を入力にした マネージドの検知サービスに乗るのが正攻法です。3つの役割分担を押さえます。
| サービス | 役割 | CloudTrail をどう使うか |
|---|---|---|
| Amazon GuardDuty | 脅威検知(ML/異常検知/脅威インテル) | CloudTrail の管理イベント・S3データイベントを基盤データソースとして、MLで異常APIや既知の悪性パターンを検出 |
| AWS Security Hub | CSPM(態勢管理)/ コンプライアンス | CIS・AWS FSBP 等の標準でアカウントを採点。GuardDuty等のFindingを集約 |
| Amazon Detective | 調査(investigation graph) | CloudTrail等から調査グラフを構築し、Findingの背後関係を可視化 |
GuardDuty:CloudTrail 由来の代表的な Finding(公式の IAM Finding タイプ)
GuardDuty は CloudTrail の管理イベントを主データソースに、IAMエンティティ/アクセスキーに関する Finding を生成します(Resource Type は AccessKey)。公式ドキュメントに記載のある、CloudTrail を入力とする代表的な Finding を分類して挙げます。
ML異常検知系(*:IAMUser/AnomalousBehavior)— データソースは CloudTrail 管理イベント
| Finding タイプ | 意味(攻撃のどの段階か) | 既定の重大度 |
|---|---|---|
CredentialAccess:IAMUser/AnomalousBehavior | 認証情報の収集(GetPasswordData/GetSecretValue 等が異常な形で) | Medium |
DefenseEvasion:IAMUser/AnomalousBehavior | 防御回避(StopLogging/DeleteFlowLogs 等の停止・削除) | Medium |
Discovery:IAMUser/AnomalousBehavior | 偵察(DescribeInstances/ListAccessKeys 等の列挙) | Low |
Exfiltration:IAMUser/AnomalousBehavior | データ持ち出し(CreateSnapshot/PutBucketReplication 等の制御プレーン操作) | High |
Impact:IAMUser/AnomalousBehavior | 破壊・改ざん(DeleteSecurityGroup/PutBucketPolicy 等) | High |
Persistence:IAMUser/AnomalousBehavior | 永続化(CreateAccessKey/ImportKeyPair 等) | Medium |
PrivilegeEscalation:IAMUser/AnomalousBehavior | 権限昇格(AddUserToGroup/PutUserPolicy 等) | Medium |
InitialAccess:IAMUser/AnomalousBehavior | 初期アクセス(GetAuthorizationToken 等) | Medium |
シグネチャ/脅威インテル系
| Finding タイプ | 意味 | 既定の重大度 |
|---|---|---|
Policy:IAMUser/RootCredentialUsage | root サインイン認証情報でAPIが呼ばれた | Low |
Stealth:IAMUser/CloudTrailLoggingDisabled | CloudTrail のロギングが無効化された | Low |
Stealth:IAMUser/PasswordPolicyChange | アカウントのパスワードポリシーが弱体化された | Low〜High |
Recon:IAMUser/MaliciousIPCaller | 既知の悪性IPからリソース列挙系APIが呼ばれた | Medium |
Recon:IAMUser/TorIPCaller | Tor 出口ノードからリソース列挙系APIが呼ばれた | Medium |
UnauthorizedAccess:IAMUser/MaliciousIPCaller | 既知の悪性IPからAPIが呼ばれた | Medium |
UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS | EC2の一時認証情報がAWS外のIPから使われた(認証情報窃取) | High |
UnauthorizedAccess:IAMUser/ConsoleLoginSuccess.B | 同一IAMユーザーで世界各地から短時間に複数回サインイン成功 | Medium |
CredentialAccess:IAMUser/CompromisedCredentials との違い:これは ML 異常検知ではなく Amazon の脅威インテリジェンスで「漏洩済み」と判定されたアクセスキーが使われたことを示す High の Finding です。データソースは「Foundational Data Source Protection に含まれる機能」と公式に記載されており、上記の
AnomalousBehavior系(CloudTrail管理イベントのML)とは生成根拠が異なります。混同しないこと。
GuardDuty の Finding は EventBridge に流れます(detail-type: "GuardDuty Finding")。これを使えば、第1章と同じ要領で「重大度7以上の Finding が出たら即SNS/自動封じ込めLambda」を組めます。GuardDuty 単体の多層・マルチアカウント設計(委任管理者・EventBridge自動対応・Terraform)は GuardDuty 深掘りガイド に分けてあります。
# GuardDuty の重大度の高い Finding を SecOps に即通知する
resource "aws_cloudwatch_event_rule" "guardduty_high_severity" {
name = "guardduty-high-severity-findings"
event_pattern = jsonencode({
"source" : ["aws.guardduty"],
"detail-type" : ["GuardDuty Finding"],
# GuardDuty の severity は数値。7.0 以上 = High 以上を対象にする
"detail" : { "severity" : [{ "numeric" : [">=", 7.0] }] }
})
}
Security Hub:CISスコアで「検知の網の穴」を可視化する
GuardDuty が「動的な検知」なら、Security Hub は「静的な態勢の採点」です。前章で挙げた CloudWatch.1〜17 を含む CIS / AWS FSBP 標準を有効化すると、「root監視アラートが無い」「CloudTrail設定変更の監視が無い」といった検知の穴そのものが FAILED として一覧化されます。検知器を作ったつもりで作れていない、を防ぐ装置です。
4. インシデント調査プレイブック:Athena / Lake でのフォレンジック
検知の次は調査です。検知が「点」なら、調査は「線と面」——侵害プリンシパルの全行動を時系列で再構成し、被害範囲(スコープ)を確定させます。
90日を超える期間、あるいは大量ログの横断クエリには Athena(S3上のCloudTrailログをそのままSQL)が現実的です。スキャン量=課金なので、**パーティション射影(partition projection)**で日付・リージョンを絞り込むのが鉄則です。CloudTrail Lake は Trino SQL で不変のイベントデータストアを直接クエリできますが、2026年5月31日をもって新規顧客の受付を終了しています(既存顧客は継続利用可)。新規構築では Athena + S3 が標準解です。
以下の Athena クエリは、CloudTrail ログ用の外部テーブル(パーティション射影付き)が作成済みである前提です。テーブル定義(
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'とパーティション射影プロパティ)の作り方はピラー記事に譲ります。
IRプレイブック:検知 → トリアージ → スコープ → 封じ込め → 証拠保全
1. 検知 : EventBridge / GuardDuty / CISアラームで気づく
2. トリアージ: 「本物か・誤検知か」「侵害プリンシパルは誰か(ARN)」を確定
3. スコープ : Athena/Lake で侵害ARNの全行動を時系列再構成、被害範囲を確定
4. 封じ込め : 鍵の無効化/失効、ポリシーのデタッチ、セッションの取り消し
5. 証拠保全 : 整合性検証(validate-logs)、ログの隔離コピー、否認不能化(第5章)
ステップ3「スコープ特定」で使う、現場で繰り返し叩くクエリを挙げます。
クエリ1:侵害プリンシパルの「全行動」を時系列で再構成
トリアージで特定した ARN が、いつ・どこから・何をしたか。これが調査のすべての起点です。
-- 侵害が疑われるプリンシパルの全 API コールを時系列で並べる
SELECT
eventtime,
eventsource,
eventname,
sourceipaddress,
awsregion,
errorcode,
readonly
FROM cloudtrail_logs
WHERE useridentity.arn = 'arn:aws:sts::111122223333:assumed-role/AppRole/suspicious-session'
AND timestamp BETWEEN '2026/06/26' AND '2026/06/27' -- パーティション射影で絞る
ORDER BY eventtime ASC;
クエリ2:永続化の兆候 — アクセスキーの新規作成
攻撃者は足場を固めるためにアクセスキーを作ります(GuardDuty の Persistence:IAMUser/AnomalousBehavior と対応)。
-- 調査期間内に作成されたアクセスキー(誰が・誰に対して・どこから)
SELECT
eventtime,
useridentity.arn AS actor,
responseelements, -- 作成されたキーIDやユーザー名が入る
sourceipaddress
FROM cloudtrail_logs
WHERE eventname = 'CreateAccessKey'
AND timestamp BETWEEN '2026/06/20' AND '2026/06/27'
ORDER BY eventtime ASC;
クエリ3:権限昇格の兆候 — IAM の付与系操作
-- 権限昇格に使われがちな IAM 操作を洗い出す
SELECT eventtime, useridentity.arn AS actor, eventname, requestparameters, sourceipaddress
FROM cloudtrail_logs
WHERE eventsource = 'iam.amazonaws.com'
AND eventname IN (
'AttachUserPolicy', 'AttachRolePolicy', 'AttachGroupPolicy',
'PutUserPolicy', 'PutRolePolicy', 'PutGroupPolicy',
'AddUserToGroup', 'CreatePolicyVersion', 'UpdateAssumeRolePolicy'
)
AND timestamp BETWEEN '2026/06/20' AND '2026/06/27'
ORDER BY eventtime ASC;
クエリ4:データ持ち出しの兆候 — スナップショット共有・バケット公開
Exfiltration:IAMUser/AnomalousBehavior が捉える制御プレーン操作を、調査で裏取りします。
-- スナップショットの外部共有・S3公開化など、持ち出しに繋がる制御操作
SELECT eventtime, useridentity.arn AS actor, eventname, requestparameters, sourceipaddress
FROM cloudtrail_logs
WHERE eventname IN (
'ModifySnapshotAttribute', -- スナップショットを他アカウントへ共有
'CreateSnapshot',
'PutBucketPolicy', -- バケットポリシーの書き換え
'PutBucketAcl',
'PutBucketReplication', -- 別バケットへの複製設定
'DeleteBucketPublicAccessBlock'-- パブリックアクセスブロック解除
)
AND timestamp BETWEEN '2026/06/20' AND '2026/06/27'
ORDER BY eventtime ASC;
クエリ5:ソースIP・セッションの追跡 — 横展開の把握
侵害が「1つのARN」に留まっているのか、それとも横展開しているのか。怪しいIPを軸に、そのIPから操作したすべてのプリンシパルを洗い出します。
-- 特定の不審 IP から行動したすべてのプリンシパルと操作
SELECT
useridentity.arn AS actor,
useridentity.type AS actor_type,
eventname,
COUNT(*) AS calls,
MIN(eventtime) AS first_seen,
MAX(eventtime) AS last_seen
FROM cloudtrail_logs
WHERE sourceipaddress = '203.0.113.45'
AND timestamp BETWEEN '2026/06/20' AND '2026/06/27'
GROUP BY useridentity.arn, useridentity.type, eventname
ORDER BY calls DESC;
クエリ6:MFAなしセッションの炙り出し
-- MFA 認証されていないセッションでの書き込み系操作(侵害セッションの疑い)
SELECT eventtime, useridentity.arn AS actor, eventname, sourceipaddress
FROM cloudtrail_logs
WHERE useridentity.sessioncontext.attributes.mfaauthenticated = 'false'
AND readonly = false
AND timestamp BETWEEN '2026/06/26' AND '2026/06/27'
ORDER BY eventtime ASC;
コストの落とし穴:
WHERE timestamp BETWEEN ...のパーティション射影条件を毎回必ず付けること。これを忘れると数年分・全リージョンのログを全スキャンし、課金が跳ねます。Athena はスキャンしたGB数で課金されるため、フォレンジックでも「まず日付で絞る」が癖になるまで徹底します。
5. 証拠保全と否認防止:「確かにこの認証情報がやった」を証明する
調査でスコープが固まったら、最後は証拠保全です。ここを疎かにすると、せっかくの調査結果が「改ざんされていないと証明できない」ために、監査・法的手続き・社内説明で力を失います。
ログ整合性検証:改ざん検出と否認防止
CloudTrail のログファイル整合性検証は、SHA-256 によるハッシュ化と SHA-256 with RSA による電子署名で構築されています。1時間ごとに、その時間に配信されたログファイル群への参照とハッシュを含む digest ファイルが作られ、各 digest は前の digest の署名を含む形で鎖(チェーン)になります。これにより、ログの改ざん・削除・偽造を検出でき、さらに「ある期間にログが1つも配信されていないこと」すら積極的に主張できます。
公式の表現がこの機能の価値を端的に言い表しています。
検証済みのログファイルは、「特定のユーザー認証情報が特定の API アクティビティを実行した」と積極的に主張(assert positively)できる——これが、セキュリティ・フォレンジック調査における否認防止の核心です。
検証は AWS CLI 一発で実行できます。
# S3 上の指定期間のログを digest チェーンに照らして検証する
aws cloudtrail validate-logs \
--trail-arn arn:aws:cloudtrail:ap-northeast-1:111122223333:trail/org-audit-trail \
--start-time 2026-06-26T00:00:00Z \
--end-time 2026-06-27T00:00:00Z
ログを別の場所(隔離用バケットなど)へ移して検証したい場合は、CLI の検証はログが配信された元の場所を前提とするため、カスタム検証を実装します(公式に手順あり)。証拠の隔離コピーを作るなら、この点を設計に織り込んでおきます。
否認不能のためのストレージ設計
検証アルゴリズムが堅牢でも、ログそのものを後から消されたら意味がありません。証拠としての価値を担保するストレージ設計が必要です。
| 対策 | 何を防ぐか | 補足 |
|---|---|---|
| S3 Object Lock(WORM) | ログ・digestの上書き・削除(root権限でも) | コンプライアンスモードなら保持期間中は誰も削除できない |
| S3 MFA Delete | digestファイルの不正削除 | 公式が digest 保護策として明示。削除にMFAを要求 |
| ログアーカイブの隔離アカウント | 侵害アカウントからのログ破壊 | ログ用S3を別アカウント(Log Archive)に置き、本番アカウントから書き込みのみ許可 |
| SSE-KMS + 厳格なキーポリシー | 暗号化と、キー削除によるログ無効化 | CMK無効化はCISのCloudWatch.7で監視する(第2章) |
設計思想:理想は「ログを生成するアカウント」と「ログを保管するアカウント」を分離することです。本番アカウントが完全に侵害されても、Log Archive アカウントの WORM 化されたログは無傷で残り、否認不能の証拠として機能します。決済基盤で「正しさを後から証明できる状態」を最初から作る、とはまさにこの構えのことです。
6. まとめ:検知 → 調査 → 保全のチートシート
CloudTrail を「ログ置き場」から「セキュリティ運用の土台」へ引き上げる要点を、最後に一枚に畳みます。
| フェーズ | やること | 使う道具 | 出典・根拠 |
|---|---|---|---|
| 最優先検知 | 証跡改ざん(StopLogging/DeleteTrail/UpdateTrail/PutEventSelectors)を秒で検知 | EventBridge → Lambda/SNS | CloudTrail EventBridge連携 |
| 兆候検知 | root利用・未認可API・MFAなしサインイン・IAM昇格・CloudTrail設定変更 等 | CloudWatch メトリクスフィルタ+アラーム | CIS AWS Foundations Benchmark / Security Hub CloudWatch.1〜14 |
| マネージド検知 | 未知の異常APIを ML/脅威インテルで | GuardDuty(CloudTrailが基盤データソース) | GuardDuty IAM Finding(公式) |
| 態勢採点 | 検知の穴(監視欠落)の可視化 | Security Hub(CIS/FSBP) | Security Hub 標準 |
| 調査 | 侵害ARNの全行動を時系列再構成・スコープ確定 | Athena(パーティション射影)/ CloudTrail Lake | — |
| 証拠保全 | 改ざん検出・否認防止 | validate-logs、S3 Object Lock/MFA Delete、隔離アカウント | ログ整合性検証(SHA-256 / digest チェーン) |
譲ってはいけない一線はこれです。
検知器は通知が繋がって初めて検知器になる(CloudWatch.15/17)。証拠はログが改ざん・削除不可能になって初めて証拠になる(整合性検証+WORM)。 「アラームはあるが通知先が無い」「ログはあるが消せる」は、無いのと同じ。
そして最も重要な honesty point を繰り返します。root利用や未認可API監視といった定番アラートは、CloudTrail公式の『例』ではなく CIS AWS Foundations Benchmark(Security Hub のコントロール)に由来します。出典を正しく言えることが、監査・レビューでの説明責任そのものです。
セキュリティ運用は「設定して終わり」ではなく、検知 → 調査 → 保全のループを、誰が見ても回せる状態に設計しきれるかで価値が決まります。私は決済という「お金が動く」領域で、二重課金0件を支える信頼性・監査の設計を主導してきました。「正しさを後から否認不能に証明できる状態」を、最初からコードに落とし込む——その経験を、あなたのAWS環境のセキュリティ監視・インシデント対応設計に活かせます。
CloudTrail を軸にした脅威検知・フォレンジック・IR体制の設計でお困りなら、お問い合わせからお気軽にご相談ください。現状の検知の穴の洗い出しから、一緒に詰めます。
関連する深掘り記事:CloudTrailの基本設計はCloudTrail 完全ガイド、GuardDutyの多層検知はGuardDuty 脅威検知ガイド、ネットワーク層の防御はAWS WAF 多層防御ガイド、データストアの権限設計はDynamoDB セキュリティガイドを参照してください。