# Emulating AWS S3 SSE-C Ransom for Threat Detection

Attackers with compromised IAM credentials re-encrypt S3 objects using SSE-C with attacker-held AES-256 keys, then set a 7-day deletion lifecycle, making data unrecoverable without paying.

- Payout: Real-world hack
- Severity: high
- Program: Amazon
- Analysis by: Terrance DeJesus
- Disclosed: 2025-02-20
- Write-up quality: 6/10
- Original: https://www.elastic.co/security-labs/threat-command/emulating-aws-s3-sse-c
- Library page: https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-threat-command-emulating-aws-s3-sse-c
- Tags: area:cloud domain:cloud impact:data-leak impact:dos kind:incident platform:threat-intel sev:high tech:aws tech:s3 technique:source-review vuln:access-control vuln:misconfiguration

**Target:** S3 bucket objects and lifecycle configuration
**Root cause:** SSE-C lets the caller supply the encryption key, and AWS does not store it; overwriting objects with an attacker-generated key makes them permanently unreadable without that key. Overly permissive IAM policies on programmatic users grant PutObject, GetObject, and PutLifecycleConfiguration.
**Steps:**
1. Obtain compromised AWS access keys for an IAM user with s3:ListObjects, s3:GetObject, s3:PutObject, s3:PutLifecycleConfiguration.
2. Enumerate objects via `s3:ListObjectsV2`.
3. Generate a local AES-256 key.
4. For each object: sign a GET with SigV4, fetch plaintext via `s3:GetObject`.
5. Sign a PUT with SigV4 including `x-amz-server-side-encryption-customer-algorithm: AES256`, `x-amz-server-side-encryption-customer-key`, and `x-amz-server-side-encryption-customer-key-MD5`, then overwrite via `s3:PutObject`.
6. Apply a 7-day expiration via `s3:PutLifecycleConfiguration`.
7. Upload a ransom note via `s3:PutObject`.
**How found:** Built on Halcyon's ItW report; Elastic replicated the technique in a Terraform sandbox to derive CloudTrail detection logic, inferring the required IAM permissions and bucket configuration the original report omitted.
**Exploitation:** Attacker uses stolen credentials of a programmatic IAM user (no console login/MFA) to list, download, re-encrypt, and overwrite every object with SSE-C using a locally held AES-256 key, then schedules deletion via lifecycle policy and drops a ransom note. Victim cannot decrypt without the attacker's key; AWS rejects retrieval without the correct SSE-C headers.
**Escalation:** Lifecycle policy schedules object deletion to increase pressure; versioning absence makes overwrite destructive.
**Insight:** SSE-C PutObject events in CloudTrail (SSEApplied: SSE_C, x-amz-server-side-encryption-customer-algorithm: AES256) are rare in most orgs; alert on first-seen IAM-user/bucket pairs and correlate with PutLifecycleConfiguration to catch re-encryption ransom before deletion fires.

## Proof of concept (copied exactly from the original report)

**Elastic detection query for SSE-C PutObject**

```
event.dataset: "aws.cloudtrail" and event.provider: "s3.amazonaws.com" and event.action: "PutObject" and event.outcome: "success" and aws.cloudtrail.flattened.request_parameters.x-amz-server-side-encryption-customer-algorithm: "AES256" and aws.cloudtrail.flattened.additional_eventdata.SSEApplied: "SSE_C"
```

**Detonate SSE-C ransom emulation command**

```
Command: python s3\_sse\_c\_ransom.py detonate
```

**Deploy vulnerable infrastructure command**

```
Command: python3 s3\_sse\_c\_ransom.py deploy
```

