DFIRタイムラインコマンド¶
aws-ct-timelineコマンド¶
AWS CloudTrailのDFIRタイムラインを、rulesフォルダ内のsigmaルールに基づいて作成します。
コマンド使用例¶
Usage: suzaku aws-ct-timeline [OPTIONS] <--directory <DIR>|--file <FILE>>
General Options:
-r, --rules <DIR/FILE> カスタムルールディレクトリのパス (デフォルト: ./rules)
-h, --help ヘルプメニューを表示する
Input:
-d, --directory <DIR> 複数gz/jsonファイルのディレクトリパス
-f, --file <FILE> gz/jsonファイルのパス
Filtering:
--timeline-start <DATE> 読み込むイベントの開始時刻 (例: "2022-02-22T23:59:59Z)
--timeline-end <DATE> 読み込むイベントの終了時刻 (例: "2020-02-22T00:00:00Z")
--time-offset <OFFSET> オフセットに基づいて直近のイベントをスキャン (例: 1y, 3M, 30d, 24h, 30m)
Output:
-C, --clobber 結果ファイルを上書きする
-G, --GeoIP <MAXMIND-DB-DIR> IPアドレスにGeoIP (ASN、都市、国)情報を追加する
-m, --min-level <LEVEL> 読み込むルールの最小レベル (規定値: informational)
-o, --output <FILE> ファイルに結果を保存
-t, --output-type <OUTPUT_TYPE> ファイルタイプ 1: CSV (デフォルト), 2: JSON, 3: JSONL, 4: CSV & JSON, 5: CSV & JSONL [デフォルト: 1]
-R, --raw-output 元のJSONログを出力する(JSON形式または標準出力のみ利用可能)
--threads <THREAD NUMBER> 使用するスレッド数 (規定値: same as CPU cores)
-s, --sort 出力前に結果をタイムスタンプ順に並べ替える (注意: 全結果をメモリに保持する)
Display Settings:
-K, --no-color カラーで出力しない
-N, --no-summary 結果概要を出力しない
-T, --no-frequency-timeline 結果タイムライン頻度を出力しない (ターミナルがUnicodeをサポートしている必要がある)
-q, --quiet Quietモード: 起動バナーを表示しない
aws-ct-timelineコマンドの例¶
- スクリーンにアラートを出力:
./suzaku aws-ct-timeline -d ../suzaku-sample-data - CSVに保存:
./suzaku aws-ct-timeline -d ../suzaku-sample-data -o sample-timeline.csv - CSVとJSONLに保存:
./suzaku aws-ct-timeline -d ../suzaku-sample-data -o sample-timeline -t 5 - 時刻順に並べ替えてCSVに保存:
./suzaku aws-ct-timeline -d ../suzaku-sample-data -o sample-timeline.csv -s
結果の並べ替え (-s, --sort)¶
デフォルトでは、結果は見つかった順にそのまま出力されます。そのため出力順はログファイルの走査順に従い、走査順はファイルシステムが決めるので実行ごとに変わることがあります。-sを指定すると、画面・CSV・JSON・JSONLの結果を実行の最後まで保持し、時刻順に並べてから出力します。
- イベント時刻を時点(UTCの瞬間)として比較します。
-l, --localtimeを使った場合や、Zと+09:00のオフセットが混在するログでも正しく並びます。 - 時刻がない行や解釈できない行は末尾に置きます。
- 同じ時刻の行は内容で並べます。同じ検出結果集合・出力設定であれば、ファイルの走査順に関係なく検出行が同じ順序になります。端末出力全体やDuckDBファイルのバイト一致は保証しません。
temporal_orderedの相関では、同時刻イベントの入力順が検出成否に影響する場合があり、出力のソートでは解決しません。 - 相関ルールの結果は、構成イベントのうち最も新しい時刻の位置に置きます(下記参照)。
DuckDB出力は常に時刻順にソートされるため、-sの影響を受けません。DuckDBだけを出力する場合、結果の追加コピーは保持しません。
全結果を最後までメモリに保持するため、-sはメモリ使用量が増えます。目安は1結果あたり約1.3KB、--raw-output併用時は約3KBです。flaws.cloudのCloudTrailデータ(190万件の検知)では、-sなしでも使う5.3GBに加えて、ピークメモリが2.4GB(--raw-output併用時は5.5GB)増えました。一方、実行時間の増加は約2〜3%(約70秒の実行で1〜2秒)でした。
相関ルールのタイムスタンプ: 構成イベントのうち最も新しい時刻を代表時刻とします。Timestamp列はUTC、または-l指定時はローカル時刻で表示し、小数秒も保持します。サマリーの日別集計は、-l指定時も常にUTCの日付を使います。これは-sの有無に関係なく、DuckDBの相関行にも適用されます。
aws-ct-timeline出力プロフィール¶
Suzakuはconfig/aws_profile.yamlファイルに基づいて情報を出力します:
Timestamp: '.eventTime'
RuleTitle: 'sigma.title'
Level: 'sigma.level'
EventSource: '.eventSource'
EventName: '.eventName'
ErrorCode: '.errorCode'
UserName: '.userIdentity.userName'
UserType: '.userIdentity.type'
SrcIP: '.sourceIPAddress'
AWS-Region: '.awsRegion'
UserAccountID: '.userIdentity.accountId'
UserARN: '.userIdentity.arn'
UserAccessKeyID: '.userIdentity.accessKeyId'
UserPrincipalID: '.userIdentity.principalId'
UserAgent: '.userAgent'
ErrorMessage: '.errorMessage'
EventID: '.eventID'
RuleAuthor: 'sigma.author'
Tags: 'sigma.tags'
RuleID: 'sigma.id'
.(例:.eventTime)で始まるフィールド値は、CloudTrailログから取得されます。sigma.(例:sigma.title)で始まるフィールド値は、Sigmaルールから取得されます。- 現在は文字列のみをサポートしていますが、将来的には他の型のフィールド値にも対応する予定です。
注意:元のJSONデータを出力し、フィールド情報を失わないようにしたい場合は、
aws-ct-timelineコマンドに-R, --raw-outputオプションを追加してください。
DuckDB出力スキーマ¶
CSVとJSONの出力は上記プロフィールを表示用に整形したものですが、DuckDB出力はデータのインターフェースであるため、型付きで自己記述的な形式になっています。この違いは意図的なもので、aws-ct-timeline、azure-timeline、gws-timeline、aws-ct-searchに共通です:
| CSV / JSON | DuckDB | |
|---|---|---|
| 値がない場合 | - (または空) |
NULL |
Timestamp |
整形済みのテキスト | TIMESTAMP |
Level |
テキスト | suzaku_level (重大度順のENUM) |
AWS-Region |
AWS-Region |
AwsRegion (SQLで引用符が不要) |
Tags |
¦で連結した1つの文字列 |
Tactics, TechniqueIDs, OtherTags (それぞれVARCHAR[]) |
SrcASN / SrcCity / SrcCountry |
-G, --geo-ip指定時のみ追加 |
常に存在(プロフィールにSrcIPがある場合)。-G未指定時はNULL |
| 重複行 | そのまま残る | 完全に一致する重複は削除され、件数はsuzaku_metaに記録される |
どのファイルにも1行のsuzaku_metaテーブルが含まれるため、何がそのファイルを生成したのかを推測せずに確認できます:
| 列 | 意味 |
|---|---|
schema_version |
レイアウトのバージョン。他のテーブルを読む前に確認してください。 |
suzaku_version, command, command_line |
Suzakuのバージョン、サブコマンド、実行したコマンドライン。 |
generated_at |
ファイルを書き出した日時。 |
timestamp_tz |
Timestamp列のタイムゾーン。UTC、または-l, --localtime指定時はローカルのオフセット。 |
rules_version, rules_count |
ルールセットのリビジョン(rulesフォルダがgitのチェックアウトの場合)と読み込んだルール数。 |
geoip_enabled |
-G, --geo-ipが実行されたかどうか。SrcCountryがすべてNULLの場合(付与が無効だった)と、付与済みファイルのNULLセル(その値はIPアドレスではない)を区別できます。 |
scanned_files, scanned_events |
実行時にスキャンした範囲。 |
output_rows, duplicate_rows_removed |
書き出した行数と、書き込み時に削除した完全一致の重複行数。 |
ルールベースのタイムラインコマンドでは、timelineの1行はイベント × ルールのマッチ1件です。複数のルールにマッチしたイベントはマッチごとに1行になるため、EventIDは一意ではありません。aws-ct-searchでは、マッチしたイベントごとに1行が生成されます。
-- Critical and high alerts in a time range, with their ATT&CK techniques.
-- `Level` is an ENUM, so cast the literal to compare by severity rather than alphabetically.
SELECT Timestamp, RuleTitle, EventName, SrcIP, TechniqueIDs
FROM timeline
WHERE Level >= 'high'::suzaku_level
AND Timestamp BETWEEN TIMESTAMP '2024-01-01' AND TIMESTAMP '2024-02-01'
AND ErrorCode IS NULL -- the call succeeded
ORDER BY Timestamp;
-- ATT&CK technique coverage, no string parsing required
SELECT technique, count(*) AS hits
FROM (SELECT unnest(TechniqueIDs) AS technique FROM timeline)
GROUP BY 1 ORDER BY hits DESC;
Suzakuは終了前にデータベースをチェックポイントするため、.duckdbファイルは完全な状態になっており、読み取り専用で開けます(コマンドの実行中ではなく、終了後にコピーしてください)。