CloudTrail events to monitor, mapped to MITRE ATT&CK
The CloudTrail events every AWS responder should know, from recon to impact, with the fields that carry the evidence and their MITRE ATT&CK technique ids.
TL;DR. You do not need to know thousands of AWS API names. About fifty event names cover the common attack path on AWS: GetCallerIdentity and List/Describe bursts (recon), CreateUser / CreateAccessKey / CreateLoginProfile (persistence), AttachUserPolicy with AdministratorAccess (privilege escalation), StopLogging / DeleteDetector (defense evasion), GetObject bursts / ModifySnapshotAttribute (exfiltration), GPU RunInstances / ScheduleKeyDeletion (impact). The tables below give the event source, the fields that carry the evidence and the MITRE ATT&CK technique for each.
Every table here matches a rule in the analyzer's open rule set, so what you read is what the tool checks. The tables are organised by tactic, in the order an intrusion usually unfolds.
Fields you read on every event
| Field | What it tells you |
|---|---|
eventTime | UTC time of the request |
eventSource / eventName | Service and API, e.g. iam.amazonaws.com / CreateUser |
userIdentity.type | Root, IAMUser, AssumedRole, FederatedUser, AWSService… |
userIdentity.arn, accessKeyId | Who, and with which credential (AKIA long-term, ASIA temporary) |
sourceIPAddress, userAgent | From where and with what client |
errorCode, errorMessage | Absent when the call succeeded |
requestParameters, responseElements | What was asked and what was created |
awsRegion, recipientAccountId | Where it happened |
AWS documents the full schema in the CloudTrail record contents reference and the userIdentity element.
Initial access and credential abuse
| Event | Evidence to read | ATT&CK |
|---|---|---|
Any call with an AKIA key from a new IP | accessKeyId, sourceIPAddress, userAgent | T1078.004, T1552.001 |
Any call with userIdentity.type = Root | Source IP; root should almost never act | T1078.004 |
ConsoleLogin (signin) | responseElements.ConsoleLogin = Success/Failure, additionalEventData.MFAUsed | T1078.004 |
Repeated ConsoleLogin failures from one IP | Count per IP per 15 min | T1110 |
Discovery
| Event | Evidence to read | ATT&CK |
|---|---|---|
sts:GetCallerIdentity with a long-term key | First call from a new address | T1087.004 |
Many different List* / Describe* / Get* in minutes | Distinct eventName count per key | T1580, T1526 |
iam:GetAccountAuthorizationDetails | Full IAM dump in one call | T1087.004 |
Burst of AccessDenied / UnauthorizedOperation | errorCode per principal | T1069.003 |
GetCallerIdentity needs no permissions and is called by the CLI itself, so on its own it is low severity. It matters as the first event from an unfamiliar address.
Persistence
| Event | Evidence to read | ATT&CK |
|---|---|---|
iam:CreateUser | requestParameters.userName | T1136.003 |
iam:CreateAccessKey for another user | requestParameters.userName ≠ caller; new key in responseElements.accessKey.accessKeyId | T1098.001 |
iam:CreateLoginProfile / UpdateLoginProfile | Console password on a user | T1098 |
iam:UpdateAssumeRolePolicy | New principals trusted by a role | T1098 |
iam:CreateSAMLProvider, CreateOpenIDConnectProvider, UpdateOpenIDConnectProviderThumbprint | New federation trust | T1484.002 |
lambda:AddPermission with principal *, CreateFunctionUrlConfig with authType: NONE | Public backdoor function | T1546, T1648 |
ec2:ModifyInstanceAttribute with userData | Script run at next boot | T1059 |
ec2:CreateKeyPair / ImportKeyPair | SSH access to new instances | T1098.004 |
Privilege escalation
| Event | Evidence to read | ATT&CK |
|---|---|---|
AttachUserPolicy / AttachRolePolicy / AttachGroupPolicy | policyArn ending in AdministratorAccess or IAMFullAccess | T1098.003 |
PutUserPolicy / PutRolePolicy / CreatePolicyVersion | Policy document with "Action": "*" on "Resource": "*" | T1098.003 |
AddUserToGroup | Group name suggesting admin rights | T1098 |
Defense evasion
| Event | Evidence to read | ATT&CK |
|---|---|---|
cloudtrail:StopLogging, DeleteTrail | Trail name, region | T1562.008 |
cloudtrail:UpdateTrail, PutEventSelectors | Destination or selectors changed | T1562.008 |
guardduty:DeleteDetector, UpdateDetector (disabled), CreateIPSet, archive filters | Detector ID, region | T1562.001 |
config:StopConfigurationRecorder, DeleteDeliveryChannel | Region | T1562.001 |
securityhub:DisableSecurityHub, macie2:DisableMacie, inspector2:Disable, detective:DeleteGraph | Service | T1562.001 |
s3:PutBucketLogging without a target | Access logging turned off | T1562.008 |
ec2:DeleteFlowLogs | Network logging removed | T1562.008 |
logs:DeleteLogGroup / DeleteLogStream | Evidence destroyed | T1070 |
ec2:AuthorizeSecurityGroupIngress with 0.0.0.0/0 | Firewall opened | T1562.007 |
| Writes in a region not used before | awsRegion | T1535 |
The defense evasion post explains how to read the gap a StopLogging leaves.
Credential access and exfiltration
| Event | Evidence to read | ATT&CK |
|---|---|---|
secretsmanager:GetSecretValue / BatchGetSecretValue on many secrets | Distinct secretId per principal | T1555.006 |
s3:GetObject bursts (data event) | Count per principal and bucket; additionalEventData.bytesTransferredOut | T1530 |
s3:PutBucketPolicy with Principal: "*", PutBucketAcl with AllUsers | Bucket made public | T1530 |
DeleteBucketPublicAccessBlock / weakened PutPublicAccessBlock | Guard rail removed | T1530 |
ec2:ModifySnapshotAttribute, ModifyImageAttribute, rds:ModifyDBSnapshotAttribute | createVolumePermission / restore shared with a foreign account or all | T1537 |
GetObject is a data event: it is only there if the trail was configured for it. See S3 data exfiltration evidence.
Impact
| Event | Evidence to read | ATT&CK |
|---|---|---|
ec2:RunInstances with p* / g* instance types | instanceType, awsRegion | T1496 |
servicequotas:RequestServiceQuotaIncrease | quotaCode, region | T1496 |
Many Delete* / Terminate* by one principal | Count per 10 min | T1485 |
kms:ScheduleKeyDeletion, DisableKey | Key ID | T1485, T1486 |
Turning the list into alerts
AWS's own guidance is to send the trail to CloudWatch Logs and create metric filters and alarms on events like these (re:Post guide); EventBridge rules work too. For investigation after the fact, filtering the exports is enough — or drop them in the analyzer, which evaluates these rules on every record and links each finding to its ATT&CK techniques. The step-by-step analysis guide shows how to confirm them.