log2timeline/plasoでAWS CloudTrailを扱うまで
はじめに
少し前に以下のブログを見て、plasoがAWS CloudTrailを扱えることを初めて知りました。
plasoはフォレンジック調査に用いるツールでログ等からタイムラインを作成します。
界隈では有名なツールでlog2timeline
やplaso
で検索するといろいろ情報がでてきます。AWSも検索ワードに加わえるとEBSボリュームを対象にした使い方なんかがも見つかります。
今回は、先ほどの記事に倣ってCloudTrailのタイムラインを作成してみます。
タイムラインの作成
Plasoにするためのログ整形
ややこしいでしいですが、CloudTrailのログを使ってタイムラインを作るには、まずCloudTrailのログをPlasoで扱えるフォーマットである必要があります。
前述のブログに記載されている通りですが、S3に保存される形式とplasoが扱える形式には差分があるためです。
前述のブログではS3に保存されたCloudTrailの証跡を利用しています。基本的にはこちらのブログの方法を利用するほうが(後述するdfTimewolf
より)扱いやすい気がします。
もう一つはdfTimewolfを使う方法で、こちらはcloudtrailから直接ログを取得します。
plasoが扱える形式
jsonl形式でイベントが格納されています。この形式がplasoが扱うことができるフォーマットです。
複数イベントを改行されて記載されるjsonl形式になっています。
{"EventId": "11111111-1111-1111-1111-111111111111","EventName": "ListBuckets","ReadOnly": 'true',"AccessKeyId": 'AKIAIOSFODNN7EXAMPLE',"EventTime": "2022-02-08 09:23:37+11:00","EventSource": "s3.amazonaws.com","Username": "myUserName","Resources": [],"CloudTrailEvent": <snip>}
{"EventId": "22222222-2222-2222-2222-222222222222","EventName": "ListBuckets","ReadOnly": 'true',"AccessKeyId": 'AKIAIOSFODNN7EXAMPLE',"EventTime": "2022-02-08 09:23:37+11:00","EventSource": "s3.amazonaws.com","Username": "myUserName2","Resources": [],"CloudTrailEvent": <snip>}
S3の証跡からログ整形
後述するCloudTrailのAPIから取得するより、基本的にはこちらのほうがやりやすいと思います。
証跡としてS3に保存される形式
CloudTrailからS3には以下のサンプルログのように保存されます。
Records
配下にリストで格納されていたり、時間表記が違ったり、いくつか部分的に異なっていることがわかります。
サンプル:証跡としてS3に保存される形式
{
"Records": [
{
"eventVersion": "1.03",
"userIdentity": {
"type": "IAMUser",
"principalId": "111122223333",
"arn": "arn:aws:iam::111122223333:user/myUserName",
"accountId": "111122223333",
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"userName": "myUserName"
},
"eventTime": "2019-02-01T03:18:19Z",
"eventSource": "s3.amazonaws.com",
"eventName": "ListBuckets",
"awsRegion": "us-west-2",
"sourceIPAddress": "127.0.0.1",
"userAgent": "[]",
"requestParameters": {
"host": [
"s3.us-west-2.amazonaws.com"
]
},
"responseElements": null,
"additionalEventData": {
"SignatureVersion": "SigV2",
"AuthenticationMethod": "QueryString",
"aclRequired": "Yes"
},
"requestID": "47B8E8D397DCE7A6",
"eventID": "cdc4b7ed-e171-4cef-975a-ad829d4123e8",
"eventType": "AwsApiCall",
"recipientAccountId": "444455556666",
"tlsDetails": {
"tlsVersion": "TLSv1.2",
"cipherSuite": "ECDHE-RSA-AES128-GCM-SHA256",
"clientProvidedHostHeader": "s3.amazonaws.com"
}
]
}
plasoで扱えるログへの事前変換
S3に保存されたCloudTrailログをブログのPythonスクリプトを使ってplasoで変換できる形式にします。
利用するログはInbvictusが公開しているCloudTrailのデータを使います。これはS3に保存されているフォーマットと同じです。
以下のようなディレクトリで作業します。
|--aws-cloudtrail2plaso.py
|--aws_dataset
| |--CloudTrail
| | |--218007301253_CloudTrail_us-east-1_20230710T1145Z_7xgocspSowgK0Gto.json
| | |--218007301253_CloudTrail_us-east-1_20230710T1145Z_s7dpHbl38neqZbm2.json
| | |--<snip>
input_directory
とoutput_filepath
を指定します。
$ python aws-cloudtrail2plaso.py ./aws_dataset/CloudTrail/ ./out.jsonl
Processed 1 of 55 files: ./aws_dataset/CloudTrail/218007301253_CloudTrail_us-east-1_20230710T1230Z_04rtp9DpvIpSZzMr.json
Processed 2 of 55 files: ./aws_dataset/CloudTrail/218007301253_CloudTrail_us-east-1_20230710T1215Z_nBsuPO1qSTEVerMD.json
...
<snip>
...
Processed 55 of 55 files: ./aws_dataset/CloudTrail/218007301253_CloudTrail_us-east-1_20230710T1220Z_8sBQhbu5YO94UV8p.json
Total records processed: 2900
Unique records found: 2900
Duplicates removed: 0
$ ls
aws-cloudtrail2plaso.py aws_dataset out.jsonl
out.jsonlの一部
$ more out.jsonl
{"EventId": "27c5df2d-9179-4690-bcc4-94bde49772cd", "EventName": "DescribeEventAggregates", "ReadOnly": "true"
, "AccessKeyId": "ASIATFQR7NSCQCITXUXC", "EventTime": "2023-07-10 12:23:30+00:00", "EventSource": "health.amaz
onaws.com", "Username": "bert-jan", "Resources": [], "CloudTrailEvent": "{\"eventVersion\":\"1.08\",\"userIden
tity\":{\"type\":\"IAMUser\",\"principalId\":\"AIDATFQR7NSC5AU2ZV3IE\",\"arn\":\"arn:aws:iam::123837392027:use
r/bert-jan\",\"accountId\":\"123837392027\",\"accessKeyId\":\"ASIATFQR7NSCQCITXUXC\",\"userName\":\"bert-jan\"
,\"sessionContext\":{\"sessionIssuer\":{},\"webIdFederationData\":{},\"attributes\":{\"creationDate\":\"2023-0
7-10T12:13:16Z\",\"mfaAuthenticated\":\"true\"}},\"invokedBy\":\"health.amazonaws.com\"},\"eventTime\":\"2023-
07-10T12:23:30Z\",\"eventSource\":\"health.amazonaws.com\",\"eventName\":\"DescribeEventAggregates\",\"awsRegi
on\":\"us-east-1\",\"sourceIPAddress\":\"health.amazonaws.com\",\"userAgent\":\"AWSInternal\",\"requestParamet
ers\":{\"filter\":{\"startTimes\":[{\"from\":\"Jul3,2023,12:23:30PM\"}],\"eventStatusCodes\":[\"open\",\"upcom
ing\"]},\"aggregateField\":\"eventTypeCategory\"},\"responseElements\":null,\"requestID\":\"7811d310-eb20-4376
-a5af-482fbf452a78\",\"eventID\":\"27c5df2d-9179-4690-bcc4-94bde49772cd\",\"readOnly\":true,\"eventType\":\"Aw
sApiCall\",\"managementEvent\":true,\"recipientAccountId\":\"123837392027\",\"eventCategory\":\"Management\",\
"sessionCredentialFromConsole\":\"true\"}"}
<snip>
dfTimewolfを使ったログ収集
そもそもPlasoはどうやってログを取得するつもりだったんだろう?と思って調べたら見つけました。
Resipesを指定することで、Plasoで処理するためのデータを収集したり、Plasoの処理とTimesketchへのアップデートなどを行うツールです。
導入ちょっと苦戦した
ドキュメントの導入手順はうまくいかなかったので、GitHubレポジトリにあるDockerfileを基にPoetry
を使った。
dftimewolf -h
を実行で利用できるRecipesの一覧を取得
git clone https://github.com/log2timeline/dftimewolf.git && cd dftimewolf
poetry install
poetry run dftimewolf -h
<snip>
Available recipes:
aws_disk_to_gcp Copies EBS volumes from within AWS, and transfers them to GCP.
aws_forensics Copies a volume from an AWS account to an analysis VM.
aws_logging_collect Collects logs from an AWS account and dumps the results to the filesystem.
aws_logging_ts Collects logs from an AWS account, processes the logs with Plaso and uploads the result to Timesketch.
aws_turbinia_ts Copies EBS volumes from within AWS, transfers them to GCP, analyses with Turbinia and exports the results to Timesketch.
azure_forensics Copies a disk from an Azure account to an analysis VM.
<snip>
dftimewolf "recipe name" -h
で各Recipeの使い方を表示
$ poetry run dftimewolf aws_logging_collect -h
[2024-11-13 00:28:14,002] [dftimewolf ] SUCCESS dfTimewolf tool initialized with UUID: 2505e11d-767c-43b8-b475-8cf9f65240fe
usage: dftimewolf aws_logging_collect [-h] [--profile_name PROFILE_NAME] [--query_filter QUERY_FILTER]
[--start_time START_TIME] [--end_time END_TIME]
region
Collects logs from an AWS account using a specified query filter and date ranges, and dumps them on the filesystem. If no args are provided this recipe will collect 90 days of logs for the default AWS profile.
positional arguments:
region AWS Region
options:
-h, --help show this help message and exit
--profile_name PROFILE_NAME
Name of the AWS profile to collect logs from. (default: None)
--query_filter QUERY_FILTER
Filter expression to use to query logs. (default: None)
--start_time START_TIME
Start time for the query. (default: None)
--end_time END_TIME End time for the query. (default: None)
aws_logging_collect
がcloudtrailからログを取得するRecipeになっている。
helpを見ても時間のフォーマットがわからなかったので、GitHubのこのあたりを見てRecipeの内容やオプションの推察をした。
boto3を使っているので、--start_time
などはboto3のドキュメントを見ながら設定する。
AWSの認証情報は通常のboto3と同じで./aws/credentials
などに置くか環境変数に設定すれば実行できる。profileの指定も可能。
poetry run dftimewolf aws_logging_collect --start_time "2024
-11-01 00:00:00" --end_time "2024-11-10 00:00:00" ap-northeast-1
実行ログ
$ poetry run dftimewolf aws_logging_collect --start_time "2024
-11-01 00:00:00" --end_time "2024-11-10 00:00:00" ap-northeast-1
[2024-11-13 00:33:59,453] [dftimewolf ] SUCCESS dfTimewolf tool initialized with UUID: 0c89e862-d840-4793-8de5-14dcf52df632
[2024-11-13 00:33:57,977] [dftimewolf ] INFO Loading recipe aws_logging_collect...
[2024-11-13 00:33:58,390] [dftimewolf ] INFO Loaded recipe aws_logging_collect with 2 modules
[2024-11-13 00:33:58,390] [dftimewolf ] INFO Running preflights...
[2024-11-13 00:33:59,252] [dftimewolf ] INFO Setting up modules...
[2024-11-13 00:33:59,253] [dftimewolf.state ] INFO Setting up module: AWSLogsCollector
[2024-11-13 00:33:59,253] [dftimewolf ] INFO Modules successfully set up!
[2024-11-13 00:33:59,253] [dftimewolf ] INFO Running modules...
[2024-11-13 00:33:59,253] [dftimewolf.state ] INFO Running module: AWSLogsCollector
[2024-11-13 00:33:59,254] [AWSLogsCollector ] SUCCESS Downloading logs to /tmp/tmp0z9lo0oa.jsonl
[2024-11-13 00:36:03,273] [AWSLogsCollector ] SUCCESS Downloaded logs to /tmp/tmp0z9lo0oa.jsonl
[2024-11-13 00:36:03,275] [dftimewolf.state ] INFO Module AWSLogsCollector finished execution
[2024-11-13 00:36:03,276] [dftimewolf ] INFO Modules run successfully!
実行ログから/tmp/tmp0z9lo0oa.jsonl
にダウンロードされていることが確認できる。
中身は対象のAWSアカウントのCloudTrailで、Plasoで扱えるフォーマットに変換されています。
$ ls /tmp/ | grep jsonl
tmp0z9lo0oa.jsonl
$ cat /tmp/tmp0z9lo0oa.jsonl | wc -l
10599
$ more -1 /tmp/tmp0z9lo0oa.jsonl
{"EventId": "33333333-3333-3333-3333-333333333333", "EventName": "AssumeRole", "ReadOnly": "true", "EventTime":
Plasoでのタイムライン作成
先ほどまでの結果を使って、いよいよPlasoでタイムラインを作成します。
今回は公式で公開されているDockerイメージを使います。
以下のようなディレクトリで作業します。
|--data
| |--evidences
| | |--output.jsonl // aws-cloudtrail2plaso.pyで生成したファイル
--help
で使い方が見れます。実際には時間指定などを入れてタイムライン作成することになると思います。
docker run --rm -v ./data/:/data log2timeline/plaso log2timeline --storage-file /data/evidences.plaso /data/evidences
実行すると./data/evidences.plaso
が作成されます。この程度のログ量ではあれば時間はかからないはずです。
Plaso実行ログ
plaso - log2timeline version 20240826
Source path : /data/evidences
Source type : directory
Processing time : 00:00:10
Tasks: Queued Processing Merging Abandoned Total
0 0 0 0 2
Identifier PID Status Memory Sources Event Data File
Main 7 completed 158.6 MiB 2 (0) 2900 (0)
Worker_00 11 idle 104.9 MiB 1 (0) 0 (0) OS:/data/evidences
Worker_01 15 idle 124.4 MiB 0 (0) 2900 (0) OS:/data/evidences/output.jsonl
Worker_02 19 idle 103.8 MiB 0 (0) 0 (0)
Worker_03 23 idle 103.9 MiB 0 (0) 0 (0)
Worker_04 27 idle 104.0 MiB 0 (0) 0 (0)
Worker_05 31 idle 104.0 MiB 0 (0) 0 (0)
Worker_06 35 idle 104.1 MiB 0 (0) 0 (0)
Worker_07 39 idle 104.2 MiB 0 (0) 0 (0)
Worker_08 43 idle 104.1 MiB 0 (0) 0 (0)
Worker_09 47 idle 104.3 MiB 0 (0) 0 (0)
Worker_10 51 idle 104.4 MiB 0 (0) 0 (0)
Worker_11 55 idle 104.3 MiB 0 (0) 0 (0)
Worker_12 59 idle 104.3 MiB 0 (0) 0 (0)
Worker_13 63 idle 104.5 MiB 0 (0) 0 (0)
Worker_14 67 idle 104.6 MiB 0 (0) 0 (0)
Processing completed.
おまけのPsort
Plasoと同じDockerイメージを使います。
以下のようなディレクトリで作業します。
|--data
| |--evidences
| | |--evidences.plaso // Plasoで生成したファイル
フィルターなどのオプションは以下から
docker run -v ./data/:/data log2timeline/plaso psort -w /data/timeline.log /data/evidences.plaso
実行ログ
plaso - psort version 20240826
Storage file : /data/evidences.plaso
Processing time : 00:00:03
Events: Filtered In time slice Duplicates MACB grouped Total
0 0 17410 182 20492
Identifier PID Status Memory Events Tags Reports
Main 8 completed 135.1 MiB 20492 (0) 0 (0) 0 (0)
Processing completed.
data/timeline.log
にはevidences.plaso
から抽出されたログが出力される。(特にフィルターをかけていないのでそのまま出力)
$ more -2 data/timeline.log
datetime,timestamp_desc,source,source_long,message,parser,display_name,tag
2023-07-10T11:42:18.000000+00:00,Recorded Time,LOG,AWS CloudTrail Log,User benjamin performed GetRegionOptStatus using access key AKIATF
おわりに
CloudTrailのログにlog2timelineを使いました。
Discussion