S3
CLOUDTRAIL
GETOBJECT
GUARDDUTY
DetectionBlue TeamSOCOctober 12, 2026•9 min read

Detecting S3 Bucket Exfiltration with CloudTrail and GuardDuty

In the cloud the data is already where the attacker wants it. Exfiltration is a burst of reads by the wrong principal, or a policy change that opens the door.

Scroll

Bucket exfiltration does not need malware. A stolen access key or an over-permissive role can list and read every object, and a policy change can expose a bucket to the internet. Management events show the permission changes, but you only see the reads if S3 data events are enabled, which is the first control to verify.

Signals at a Glance

SignalWhereATT&CK
Burst of GetObject or ListObjectsV2 by one principalCloudTrail S3 data eventsT1530
PutBucketPolicy, PutBucketAcl or DeletePublicAccessBlock making a bucket publicCloudTrail management eventsT1530
Reads from an unfamiliar IP, ASN or Tor exit by a long-lived access keyCloudTrail, GuardDutyT1078.004
Replication or copy of objects to a bucket in another accountCloudTrail, S3 replication configT1537
GuardDuty Exfiltration:S3/AnomalousBehavior or Exfiltration:S3/MaliciousIPCallerGuardDutyT1530

CloudTrail Data Events

Data events must be enabled per bucket or per account, and they are billed, which is why many environments lack them. Without them, you can see who changed the bucket but not who read from it. A GetObject record carries the principal, source address and object key:

{
  "eventSource": "s3.amazonaws.com",
  "eventName": "GetObject",
  "userIdentity": { "type": "IAMUser", "arn": "arn:aws:iam::111122223333:user/svc-report", "accessKeyId": "AKIA..." },
  "sourceIPAddress": "203.0.113.45",
  "userAgent": "[aws-cli/2.15.0 ...]",
  "requestParameters": { "bucketName": "corp-finance-archive", "key": "2026/q3/ledger.parquet" },
  "additionalEventData": { "bytesTransferredOut": 48211734 }
}
// tune/validate: the key fields to aggregate are userIdentity.arn, sourceIPAddress and bytesTransferredOut

Aggregate by principal and source address, and compare with the principal’s usual pattern. A reporting key that normally makes a few hundred reads from one address and now pulls tens of thousands from a hosting provider is the shape you want:

index=aws sourcetype="aws:cloudtrail" eventSource="s3.amazonaws.com" eventName IN ("GetObject","ListObjectsV2")
| bin _time span=15m
| stats count as reads sum(additionalEventData.bytesTransferredOut) as bytes_out
        dc(requestParameters.key) as objects dc(sourceIPAddress) as ips
        by _time, userIdentity.arn, requestParameters.bucketName
| where reads > 5000 OR bytes_out > 5000000000
| sort - bytes_out
``` tune/validate: lookup known data-pipeline principals and exclude by ARN, not by name ```

Exposure and Posture Changes

Vetted sources

AWS CloudTrail and GuardDuty documentation, Splunk ESCU AWS analytic stories, Elastic AWS detection rules, and SigmaHQ cloud rules. Baseline your own environment — ETL jobs, backups and analytics services read large volumes of objects by design.

Build Detections That Fire

Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.

Detection EngineeringManaged Detection & ResponseThreat HuntingIncident ResponsePurple Teaming
  • Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
  • Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
  • 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Written by: Mjolnir Threat Research (MTAC)  |  Published: October 12, 2026  |  Last reviewed: October 12, 2026