AWS #

Log sources - what each one actually covers

AWS timestamps 101: every CloudTrail record carries eventTime in ISO-8601 UTC with Z suffix (second resolution; some data events have fractional), set by the CloudTrail service at the moment the API call is processed, not when the client initiated it (clock skew between caller and service is possible). CloudTrail delivers to S3 within an average of about 5 minutes of the API call, and AWS does not guarantee it - allow for longer. VPC Flow Logs are aggregated into a maximum interval of 10 minutes (default) or 1 minute (there is no 10-second option; Nitro-based ENIs are always 1 minute or less) - start/end are the first and last packet times seen in the window, so you cannot sequence activity below roughly a minute from flow logs alone. GuardDuty findings have createdAt, updatedAt, service.eventFirstSeen, service.eventLastSeen - a finding's updatedAt can be hours after the underlying event because GuardDuty keeps updating one finding as new occurrences arrive.

SourceCoversGotchasParsers / tools
CloudTrail - management eventsControl-plane API calls (IAM, EC2, S3 bucket config, Lambda create, etc.)Default retention in Event history = 90 days UI only. Durable logging requires a trail → S3. Multi-region, org-trail required for full coverage. ts: eventTime ISO-8601 UTC (second); S3 object key uses UTC date partition. Delivery to S3 averages ~5 min (not guaranteed) after the API call. requestID + eventID are stable keys to join across delayed deliveries.Athena (w/ partition projection), CloudTrail Lake, aws cloudtrail lookup-events, CloudTrail-Partitioner (Duo), Panther, Splunk
CloudTrail - data eventsS3 object-level, Lambda invoke, DynamoDB item ops, moreOff by default and billed separately. Many investigations fail because data events weren't on. ts: same eventTime format but higher-frequency events can batch - multiple records for the same object within a second may share an eventTime but have unique eventIDs. S3 object-level reads also stamp the S3 server-access log (different ts, different delivery lag - up to several hours).Athena, CloudTrail Lake, Mitiga IR, Cado Response
CloudTrail InsightsAnomaly detection on API call rate / error rateNot forensic-grade; triage aid.Console, aws cloudtrail get-insight-selectors
CloudTrail LakeManaged data lake with SQLClosed to new customers since 31 May 2026 (existing users only; critical fixes only). AWS points new users to CloudWatch. If already in use, retention can be up to 10 years (one-year extendable pricing) or a fixed 7 years (seven-year pricing); otherwise query the trail with Athena.aws cloudtrail start-query, Lake console, CloudWatch Logs Insights
VPC Flow Logs5-tuple + bytes/packets + action (ACCEPT/REJECT)No payload. Granularity: subnet, ENI, or VPC. Build a custom format with the fields you need - tcp-flags is a v3 field, flow-direction / traffic-path are v5. Transit Gateway has its own flow logs. ts: start and end are Unix epoch seconds (UTC) bounding the aggregation window, max 600 s (default) or 60 s, Nitro always ≤60 s; each can be off from the real packet time by up to a minute. Delivery lags the window end by ~5 min to CloudWatch, ~10 min to S3.Athena, CloudWatch Logs Insights, Flowlogs-reader (obsrvbl)
Route 53 Resolver query logsDNS from VPCDifferent from Route 53 public DNS logs; both exist. ts: query_timestamp ISO-8601 UTC - per AWS, the time the query was submitted.Athena, CloudWatch, Chronicle/Google SecOps ingest
GuardDutyManaged detections. Foundational sources (always on with GuardDuty): CloudTrail management events, VPC Flow Logs, DNS logs. Protection plans (opt-in): S3, EKS Audit, EKS/EC2 Runtime Monitoring (eBPF agent), Malware Protection, RDS login, Lambda. ts: each finding has createdAt (first opened) and updatedAt (last correlated occurrence); service.eventFirstSeen/eventLastSeen bound the activity. New findings export in ~5 min; updates to an existing finding export every 6 h by default (set to 15 min / 1 h), so updatedAt can lag the activity.GuardDuty console, aws guardduty get-findings, Security Hub, SIEM
Security HubAggregator for GuardDuty, Macie, Inspector, Config, 3PSecurity Hub CSPM (formerly Security Hub; ASFF, best-practice controls) and the new Security Hub (OCSF, correlation/risk analytics, GA Dec 2025) - a client may have either or both. Dedupe matters.aws securityhub get-findings, console, SIEM
DetectiveGraph of entity behavior over ~1yrGreat pivoting UI; expensive at scale.Detective console (no CLI equiv for the graph)
ConfigResource configuration timelineLets you reconstruct "when did this SG become 0.0.0.0/0?"aws configservice get-resource-config-history, Config advanced queries (SQL), Athena
S3 server access logs / S3 access analyzerBucket-level accessAccess analyzer finds public/externally shared resources.Athena on S3 access logs, IAM Access Analyzer
AthenaSQL over CloudTrail / Flow / etc in S3Expect to write ad hoc queries under time pressure.Console, aws athena start-query-execution, pyathena
AWS IR frameworks & posture tools: Prowler (CSPM + IR checks), ScoutSuite (NCC), Cloudsplaining (Salesforce, IAM over-perm finder), PMapper (NCC, IAM graph), Cloudtracker (Duo, unused perms), Trailblazer (Will Bengtson, maps actions to CloudTrail events), Stratus Red Team (Datadog, attack emulation; useful ref for defenders), Pacu (Rhino, offensive, ref), SkyArk (CyberArk, privilege escalation finder), enumerate-iam (Andres Riancho), Steampipe/CloudQuery (SQL over cloud APIs), Cado (now Darktrace), Mitiga, Grimoire (Datadog, generates CloudTrail datasets by running Stratus attacks), Falcon Cloud Security.

IAM & identity attack surface

  • Long-lived access keys (AKIA…) - leaked keys are the #1 initial access vector. Rotate via aws iam list-access-keys, UpdateAccessKey.
  • STS short-lived creds (ASIA… tokens from sts:AssumeRole, GetFederationToken, GetSessionToken). Appear as separate userIdentity.sessionContext.
  • AssumeRoleWithWebIdentity - OIDC federation. GitHub Actions commonly uses this; misconfigured trust policy (sub: *, missing audience) → cross-tenant takeover.
  • Role chaining - AssumeRole from one session into another, limited to 1-hour max session unless using original creds; attackers chain to launder lineage.
  • Session tags / SourceIdentity - enterprises require sts:SourceIdentity to trace end-user identity through role assumption.
  • IMDS - v1 unauthenticated; v2 requires token (PUT /latest/api/token). A PUT-response hop limit of 1 stops containers on the instance from getting a token; AMIs flagged imds-support v2.0 (e.g. Amazon Linux 2023) default to 2, which lets containers reach IMDS - check the instance's metadata options. Account-level defaults and IMDSv2 enforcement can also be set per Region. SSRF to v2 still possible if app proxies PUT. Capital One (2019) = IMDSv1 SSRF; today container metadata (169.254.170.2) for ECS task roles is the modern analogue.
  • Service control policies (SCPs) at org - denies ride higher than permissions boundaries. But SCPs never restrict the management account or service-linked roles, so they can't contain an attacker operating in the management account. An attacker with org admin can also detach them.

Common adversary API calls - "the greatest hits"

Real CloudTrail eventNames, grouped by what the attacker is doing. Names here are CloudTrail event names, which can differ from the IAM permission (for example the IAM action s3:ListAllMyBuckets appears in CloudTrail as ListBuckets). Most recon is read-only management events, on by default; the big blind spots are flagged inline (S3 object reads need data events). Pivot on userIdentity.arn / sessionContext, sourceIPAddress, userAgent and errorCode.

CloudTrail event (service)What it does / why it matters
Initial access / sign-in
ConsoleLoginConsole sign-in. additionalEventData.MFAUsed=No matters for IAM users / root only - federated and SSO sign-ins always record No (MFA happened at the IdP), so check IdP logs for those. errorMessage "Failed authentication" = password spray.
GetFederationToken, GetSessionToken (sts)Mint short-lived creds that are harder to tie back to the source identity.
AssumeRoleWithWebIdentity, AssumeRoleWithSAML (sts)Federated entry (GitHub Actions OIDC, SAML SSO). A loose trust policy (sub:*, missing audience) is cross-tenant takeover.
Reconnaissance & enumeration (mostly read-only management events - on by default, low-noise to the attacker)
GetCallerIdentity (sts)"Who am I?" - the first call from stolen creds.
GetAccountAuthorizationDetails (iam)Dumps every user, group, role and attached/inline policy in one call, the IAM map. Pull it yourself for a point-in-time snapshot too.
ListUsers, ListRoles, ListGroups, ListPolicies, ListAccessKeys, ListMFADevices, GetLoginProfile, ListAttachedUserPolicies, GetPolicyVersion (iam)Enumerate identities, their keys, whether MFA/console login is set, and exactly what each can do.
SimulatePrincipalPolicy, SimulateCustomPolicy (iam)Ask AWS directly "what can this principal do?" without triggering denies, quiet privesc path-finding.
ListBuckets (s3; IAM action s3:ListAllMyBuckets)List every bucket in the account. Then GetBucketPolicy, GetBucketAcl, GetBucketPublicAccessBlock, GetBucketPolicyStatus, ListObjects/ListObjectsV2 to find readable and public data.
DescribeInstances, DescribeSecurityGroups, DescribeVpcs, DescribeSubnets, DescribeSnapshots, DescribeImages, DescribeVolumes, DescribeKeyPairs, DescribeInstanceAttribute (ec2)Map compute, networking and where disks/AMIs live (snapshot/AMI exfil targets).
ListSecrets (secretsmanager), DescribeParameters (ssm), ListFunctions (lambda), DescribeDBInstances/DescribeDBClusters (rds), ListTables (dynamodb)Find where secrets, code and data live before touching them.
DescribeOrganization, ListAccounts (organizations)Map the org - other accounts to pivot into, and whether this is the management account.
Tooling: enumerate-iam (Andres Riancho), Pacu recon modules, ScoutSuite, ProwlerFire hundreds of List/Describe/Get calls fast - a burst of read-only calls from one new principal is itself a signal.
Privilege escalation (Rhino Security catalogued ~21 IAM privesc paths - these are the common CloudTrail events)
CreatePolicyVersion + --set-as-default, or SetDefaultPolicyVersion (iam)Rewrite a policy the attacker can edit to grant *, or roll the default to an old permissive version.
AttachUserPolicy, AttachGroupPolicy, AttachRolePolicy (e.g. AdministratorAccess)Attach a managed admin policy to a controlled principal.
PutUserPolicy, PutGroupPolicy, PutRolePolicy (iam)Add an inline *:* policy, easy to miss because it's not a named managed policy.
AddUserToGroup (iam)Join a privileged group.
UpdateAssumeRolePolicy (iam)Rewrite a role's trust policy so the attacker principal can assume it, then AssumeRole.
iam:PassRole + RunInstances / CreateFunction / CreateInstanceProfile + AddRoleToInstanceProfile + AssociateIamInstanceProfilePass a more-privileged role to a resource you can run code on, then use its credentials. In CloudTrail you see the consuming call carrying the role ARN.
UpdateFunctionCode / UpdateFunctionConfiguration (lambda)Overwrite the code of a function that already has a privileged execution role.
CreateLoginProfile / UpdateLoginProfile on another user (iam)Set a console password on a privileged user that only had API keys.
Persistence
CreateUser + CreateAccessKey + AttachUserPolicy AdministratorAccessClassic backdoor admin user. Detect via Config / GuardDuty / the event sequence.
CreateAccessKey on an existing user (iam)A second access key on a real user - survives the owner's password reset; watch for a user with two active keys.
CreateLoginProfile (iam)Add console access to a service-only user.
CreateRole / UpdateAssumeRolePolicy with trust to an external account or Principal:*Durable cross-account backdoor the attacker can assume from their own account.
CreateSAMLProvider / UpdateSAMLProvider, CreateOpenIDConnectProvider (iam)Add a federation identity provider the attacker controls, a quiet, long-lived way back in.
CreateFunction + AddPermission + EventBridge rule (PutRule/PutTargets)Lambda backdoor triggered on a schedule or event, running with an attached role.
ImportKeyPair / CreateKeyPair (ec2)Add an SSH key for later access to instances.
Credential access
GetSecretValue (secretsmanager)Read stored secrets - DB passwords, API keys. Logged as a management event; rotate anything the principal could read.
GetParameter / GetParameters WithDecryption=true (ssm)Read SecureString parameters (often credentials).
Decrypt, GenerateDataKey (kms)Decrypt attacker-reachable ciphertext; spikes can indicate bulk decryption.
GetPasswordData (ec2)Retrieve the encrypted Windows administrator password for an instance.
GetAuthorizationToken (ecr)Get a registry token to pull private container images (may contain secrets).
Lateral movement
AssumeRole (sts)Move between roles and accounts; role chaining launders lineage. Follow sessionContext and SourceIdentity.
SendCommand, StartSession (ssm)Run commands / get an interactive shell on a private EC2 instance with no SSH or inbound port, a top real-world lateral path.
SendSSHPublicKey (ec2-instance-connect)Push a one-time SSH key to an instance, then connect.
ModifyInstanceAttribute (userData) then stop/start (ec2)Rewrite boot-time user-data to run attacker code as root on restart.
CreateDBSnapshot + RestoreDBInstanceFromDBSnapshot (rds)Clone a database into an instance the attacker controls to read it.
Defense evasion & anti-forensics
StopLogging, DeleteTrail, UpdateTrail, PutEventSelectors (narrowing scope) (cloudtrail)Stop or blind the audit trail. StopLogging itself is logged, a high-signal event.
DeleteFlowLogs (ec2), DeleteResolverQueryLogConfig (route53resolver)Remove network and DNS visibility.
UpdateDetector (Enable=false), DeleteDetector, CreateFilter (AUTO_ARCHIVE), CreateIPSet/UpdateIPSet (trusted-IP allowlist), publishing-destination changes, member disassociation (guardduty)Kill or blind GuardDuty. (DisableGuardDutyDetector is not a real API - don't search for it.)
StopConfigurationRecorder, DeleteConfigRule (config); DeleteLogGroup, DeleteLogStream (logs); DeleteAlarms (cloudwatch)Remove config history, logs and alerting.
DisableSecurityHub, DeleteMembers (securityhub)Turn off the findings aggregator.
DeactivateMFADevice, DeleteVirtualMFADevice (iam)Weaken a target account's MFA.
PutBucketLogging (off) (s3)Stop S3 access logging before reading objects.
Exfiltration
GetObject (s3) - data event, off by defaultBulk object download. Without data events on, you only see it indirectly (S3 server access logs, bytes in Flow Logs). The most common reason an S3 exfil can't be proven.
ModifySnapshotAttribute (ec2), ModifyDBSnapshotAttribute (rds), ModifyImageAttribute (ec2)Share an EBS/RDS snapshot or AMI to an attacker account, then they copy it out. Emulated by Stratus aws.exfiltration.ec2-share-ebs-snapshot.
PutBucketPolicy / PutBucketAcl allowing Principal:* or an external account; PutBucketReplication to an attacker bucketOpen a bucket or replicate it out continuously.
SendEmail, SendRawEmail (ses)Abuse the victim's SES (good deliverability from their domain) to phish downstream, and as a low-and-slow exfil channel.
Impact / destruction
DisableKey, ScheduleKeyDeletion (kms)Destructive extortion - but reversible while it lasts: EnableKey and CancelKeyDeletion reverse it during the 7-30 day window (default 30). Permanent only after the window or if imported key material was destroyed - cancel immediately.
S3 ransom via SSE-C (x-amz-server-side-encryption-customer-algorithm on PutObject/CopyObject)Re-encrypt objects with an attacker-held key (Codefinger, 2025) - the data is intact but unreadable without their key.
TerminateInstances, DeleteVolume, DeleteSnapshot (ec2), DeleteDBInstance/DeleteDBCluster (rds), DeleteBucket/DeleteObject (s3), DeleteStack (cloudformation)Wipe compute, disks, databases, buckets and whole stacks - destructive/extortion.
RunInstances (large or GPU types), RequestSpotInstances (ec2)Spin up expensive instances for crypto-mining - watch for a sudden spike in Compute spend and unusual instance types/regions.

Forensic acquisition in AWS

  • EBS cross-account snapshot workflow: snapshot the instance's EBS volume(s). A snapshot encrypted with the default aws/ebs key can't be shared - first copy it in the victim account re-encrypting with a customer-managed key and grant the IR account kms:Decrypt/CreateGrant, then ModifySnapshotAttribute to share it; in the IR account copy and re-encrypt with an IR-owned key, create a volume and attach it read-only to the forensic instance (preserve hashes). Document every step for CoC.
  • Memory - snapshot the running instance via CreateImage with no-reboot=true is not a memory capture; actually acquire RAM via SSM Agent + AVML/WinPmem pulled over Session Manager.
  • Lambda - pull the deployment package (GetFunction → Code.Location presigned URL), check layers, environment vars, resource policy, invoke history via CloudTrail data events.
  • Containers - ECS: pull task definition revision, task role, image digest; EKS: audit log + control-plane logs + runtime (GD Runtime Monitoring / Falcon Cloud Workload Protection).
  • IAM - get-account-authorization-details snapshot (one JSON of entire IAM state).
  • Automate with IR tools: aws_ir (ThreatResponse / Andrew Krug et al., deprecated but reference), Cado (Darktrace), Mitiga, Cloudtracker, Prowler, ScoutSuite, CloudSplaining.

Common AWS compromise patterns

  • Leaked long-lived keys in public GitHub / Docker Hub → recon → CreateAccessKey on self → AssumeRole privesc → S3 bulk exfil → ransom note / Codefinger (SSE-C extortion).
  • SSRF on app (IMDSv1 or proxied PUT) → EC2 role creds → S3/EBS access.
  • GitHub Actions misconfig (OIDC trust with sub:*) → AssumeRoleWithWebIdentity → account takeover.
  • Entra ID / Okta → federated SSO into AWS (SAML) → persistence by adding IAM user as fallback.
  • SES abuse - attacker uses victim's SES to phish downstream customers (deliverability from victim domain).
  • Codefinger (2025) - ransoming S3 via x-amz-server-side-encryption-customer-algorithm (SSE-C) using attacker-held key.