Defender — Objective 1: Download CloudTrail Logs¶
Setup¶
You are given access to a "Security" account as an IAM user. That account contains a copy of CloudTrail logs from a successful compromise (the attack from the Attacker track), and has the ability to assume a "security" role into the Target account.
Security account credentials (training environment only):
- Account ID: 322079859186
- Username: security
- Access Key: <REDACTED_ACCESS_KEY_ID>
- Secret Key: <REDACTED_SECRET_KEY>
Two accounts involved:
| Account | ID | Purpose |
|---|---|---|
| Security | 322079859186 |
Your analyst account — contains CloudTrail logs, has cross-account access |
| Target | 653711331788 |
The compromised account — contains the vulnerable resources |
This is a realistic setup. Most mature AWS orgs have a dedicated Security or Audit account that's separate from everything else. Logs from all accounts flow into it. Analysts operate from there so compromising the target account doesn't destroy the logs.
What is CloudTrail?¶
CloudTrail is AWS's audit log service. Every AWS API call made in an account — by a human, a script, a Lambda function, an EC2 instance, anything — gets recorded as a JSON event in CloudTrail.
What a CloudTrail event records:
- Who made the call (userIdentity — IAM user, role, service)
- What they called (eventName — ListBuckets, AssumeRole, GetObject, etc.)
- When (eventTime)
- From where (sourceIPAddress)
- With what tool (userAgent — aws-cli, Boto3, Chrome, etc.)
- What they asked for (requestParameters)
- What they got back (responseElements)
- Whether it succeeded or failed (errorCode, errorMessage)
Why it matters for incident response: CloudTrail is the definitive record of what happened. You can reconstruct an entire attack just from the logs — who ran what, when, from which IP, using which credentials.
Log format: Each CloudTrail file is .json.gz — gzipped JSON. Multiple API calls are wrapped in a Records array:
{
"Records": [
{ "eventTime": "...", "eventName": "ListBuckets", ... },
{ "eventTime": "...", "eventName": "AssumeRole", ... }
]
}
Log path pattern:
For this exercise: AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/
Step 1 — Configure the CLI¶
aws configure --profile security
# AccessKeyId: <REDACTED_ACCESS_KEY_ID>
# SecretAccessKey: <REDACTED_SECRET_KEY>
# region: us-east-1
Verify it works:
Expected output:
arn:aws:iam::322079859186:user/security — this is a permanent IAM user (iam:...:user/), not a role. Account ID 322079859186 = Security account. You're in the right place.
Step 2 — List the Buckets¶
Returns: flaws2-logs — the S3 bucket in the Security account that holds the CloudTrail logs.
Step 3 — Download the Logs¶
aws s3 sync — synchronises a source to a destination. Downloads everything from the bucket that doesn't already exist locally.
| Part | What it does |
|---|---|
aws s3 sync |
Sync command — copies new/modified files from source to destination |
s3://flaws2-logs |
Source: the S3 bucket |
. |
Destination: current working directory |
--profile security |
Use the security account credentials |
sync vs cp:
- aws s3 cp — copy a specific file or directory
- aws s3 sync — mirror a whole directory tree, only transferring what's missing or changed
Result: Downloads .json.gz files into ./AWSLogs/653711331788/CloudTrail/us-east-1/2018/11/28/
Why is this bucket public? The challenge is designed so you can reference it from Athena (Objective 6) without needing to copy it into your own account first. In real environments, CloudTrail log buckets are private — accessible only to the Security account.