Logging and Monitoring
Every API call in the account is recorded. The question is whether anyone reads it.
What you will learn
- -Know which log records the control-plane actions that reveal an attacker
- -Read a CloudTrail event and spot the signals of compromise
- -Understand why attackers try to kill logging first, and how to stop them
Every action in an AWS account, every key created, every bucket changed, every login, generates a record. AWS captures it whether you asked or not. The gap between a breach that gets caught in an hour and one that runs for months is almost never whether the evidence existed. It is whether anyone was looking at it.
CloudTrail is the log that matters
CloudTrail records the : the calls that manage the account. Who called CreateUser, from what IP, at what time, and did it succeed. This is where an intruder shows up, because to do anything useful in a cloud account they have to make API calls, and CloudTrail sees them all.
Do not confuse it with its neighbors. CloudWatch is metrics and application , useful for "is the CPU pegged," not "who assumed this role." Flow Logs record connections, from A to B, but not the API actions behind them. GuardDuty sits on top of CloudTrail, , and flow logs and raises . Azure's version of CloudTrail is Activity Log; GCP's is Cloud Logs. Same idea, same primacy.
A CloudTrail event is . The fields you read first every time:
{
"eventName": "CreateAccessKey",
"eventTime": "2026-07-15T03:14:22Z",
"sourceIPAddress": "203.0.113.44",
"userIdentity": { "type": "IAMUser", "userName": "svc-deploy" },
"errorCode": null
}
eventName is the action. sourceIPAddress is where it came from. userIdentity is who did it. errorCode tells you if it was denied, and a burst of AccessDenied from one is often someone probing the edges of what a stolen can do.
What compromise looks like in the log
You learn to read these by knowing the shapes attackers make. A that always calls from an AWS internal IP suddenly calling from a residential ISP in another country. CreateUser or CreateAccessKey outside a deploy window. AttachUserPolicy granting AdministratorAccess. GetCallerIdentity right after a credential shows up, because that is the first thing both attackers and their tools run to see whose keys they hold.
$aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=CreateAccessKey --max-results 10The single strongest signal is a change to logging itself. StopLogging, DeleteTrail, or PutEventSelectors narrowing what gets recorded. A legitimate admin rarely turns off the audit trail. An attacker does it early, because the log is the thing that will them caught.
One of the first moves after gaining access is to blind the defender. If you see StopLogging or DeleteTrail in CloudTrail, treat it as an active , not a config change. Enable log file validation and, better, ship CloudTrail to a separate account or an with -delete and object lock so the attacker who owns the compromised account still cannot erase the record.
Make the log actually get read
A log nobody reads is theater. Turn it into detection. Turn on GuardDuty first, because it costs little and flags the obvious patterns, including access from Tor and known-bad , out of the box. Route CloudTrail into CloudWatch Logs with metric filters and alarms on the events that should never happen quietly: account usage, changes, security-group edits, and any logging change.
Reading CloudTrail requires legitimate access to the account it belongs to. In a real engagement you review these logs under , the same as any other . On the offensive side, know that everything you do is being recorded here; a good pentest report includes what you did and when, so the can match it against exactly these events.
The logs are already running. The work is wiring them to something that pages a human when the shape is wrong, and protecting them so the record survives the attacker who wants it gone.
While reviewing CloudTrail, you see a StopLogging event from an IAM user that normally only deploys code. What is the most likely explanation?