# AWS - S3 Post Exploitation

{{#include ../../../../banners/hacktricks-training.md}}

## S3

For more information check:

{{#ref}}
../../aws-services/aws-s3-athena-and-glacier-enum.md
{{#endref}}

### Sensitive Information

Sometimes you will be able to find sensitive information in readable in the buckets. For example, terraform state secrets.

### Pivoting

Different platforms could be using S3 to store sensitive assets.\
For example, **airflow** could be storing **DAGs** **code** in there, or **web pages** could be directly served from S3. An attacker with write permissions could **modify the code** from the bucket to **pivot** to other platforms, or **takeover accounts** modifying JS files.

### S3 Ransomware

In this scenario, the **attacker creates a KMS (Key Management Service) key in their own AWS account** or another compromised account. They then make this **key accessible to anyone in the world**, allowing any AWS user, role, or account to encrypt objects using this key. However, the objects cannot be decrypted.

The attacker identifies a target **S3 bucket and gains write-level access** to it using various methods. This could be due to poor bucket configuration that exposes it publicly or the attacker gaining access to the AWS environment itself. The attacker typically targets buckets that contain sensitive information such as personally identifiable information (PII), protected health information (PHI), logs, backups, and more.

To determine if the bucket can be targeted for ransomware, the attacker checks its configuration. This includes verifying if **S3 Object Versioning** is enabled and if **multi-factor authentication delete (MFA delete) is enabled**. If Object Versioning is not enabled, the attacker can proceed. If Object Versioning is enabled but MFA delete is disabled, the attacker can **disable Object Versioning**. If both Object Versioning and MFA delete are enabled, it becomes more difficult for the attacker to ransomware that specific bucket.

Using the AWS API, the attacker **replaces each object in the bucket with an encrypted copy using their KMS key**. This effectively encrypts the data in the bucket, making it inaccessible without the key.

To add further pressure, the attacker schedules the deletion of the KMS key used in the attack. This gives the target a 7-day window to recover their data before the key is deleted and the data becomes permanently lost.

Finally, the attacker could upload a final file, usually named "ransom-note.txt," which contains instructions for the target on how to retrieve their files. This file is uploaded without encryption, likely to catch the target's attention and make them aware of the ransomware attack.

#### SSE-C (Customer-Provided Key) Ransomware (Codefinger-like)

Another variant is abusing **SSE-C** (S3 server-side encryption with **customer-provided keys**). With SSE-C, the **client provides the encryption key on every request** and **AWS does not store the key**. This means that if an attacker rewrites objects using **their own SSE-C key**, the victim's data becomes unreadable unless the victim can provide that attacker-controlled key.

- **Preconditions:** Compromised AWS credentials (or any principal with the right permissions) and the ability to **rewrite objects** (e.g., `s3:PutObject` on the target keys/prefixes). This is often paired with the ability to set destructive lifecycle policies (see below), e.g. `s3:PutLifecycleConfiguration`.
- **Attack chain:**
  1. Attacker generates a random 256-bit key (AES-256) and keeps it.
  2. Attacker **rewrites** existing objects (same object keys) using SSE-C headers so the stored object is now encrypted with the attacker key.
  3. Victim cannot download/decrypt without providing the SSE-C key (even if IAM permissions are fine).
  4. Attacker can delete the key (or simply never provide it) to make data unrecoverable.

Example (conceptual) CLI usage:

```bash
# Upload/overwrite an object encrypted with attacker-provided SSE-C key
aws s3 cp ./file s3://<BUCKET>/<KEY> \
  --sse-c AES256 \
  --sse-c-key <BASE64_32_BYTES>

# Download requires providing the same key again
aws s3 cp s3://<BUCKET>/<KEY> ./file \
  --sse-c AES256 \
  --sse-c-key <BASE64_32_BYTES>
```

##### Adding Pressure: Lifecycle "Timer" Abuse

To remove recovery options (like old versions), attackers can pair SSE-C rewrites with **lifecycle rules** that expire objects and/or delete noncurrent versions after a short period:

- `s3:PutLifecycleConfiguration` on the bucket lets an attacker schedule deletions without issuing explicit delete operations for every object/version.
- This is especially impactful when **versioning is enabled**, because it can remove the "previous good version" that would otherwise allow recovery.

##### Detection & Mitigations

- Prefer **SSE-KMS** (or SSE-S3) over SSE-C unless you have a strong operational reason to allow SSE-C.
- Monitor/alert on `PutObject` requests using SSE-C headers (CloudTrail data events for S3).
- Monitor/alert on unexpected `PutBucketLifecycleConfiguration` (lifecycle changes).
- Monitor/alert on sudden spikes in overwrite activity (same keys updated rapidly) and delete-marker/version deletions.
- Restrict high-risk permissions: Limit `s3:PutObject` to necessary prefixes; strongly restrict `s3:PutLifecycleConfiguration` and `s3:PutBucketVersioning`; consider requiring MFA for sensitive admin actions (where applicable) and use separate admin roles with approvals.
- Recovery posture: Use **versioning**, **backups**, and immutable/offline copies (S3 replication to protected account, backup vaults, etc.); protect noncurrent versions from aggressive deletion and guard lifecycle changes with SCPs / guardrails.

### `s3:RestoreObject`

An attacker with the s3:RestoreObject permission can reactivate objects archived in Glacier or Deep Archive, making them temporarily accessible. This enables recovery and exfiltration of historically archived data (backups, snapshots, logs, certifications, old secrets) that would normally be out of reach. If the attacker combines this permission with read permissions (e.g., s3:GetObject), they can obtain full copies of sensitive data.

```bash
aws s3api restore-object \
  --bucket <BUCKET_NAME> \
  --key <OBJECT_KEY> \
  --restore-request '{
    "Days": <NUMBER_OF_DAYS>,
    "GlacierJobParameters": { "Tier": "Standard" }
  }'
```

### `s3:Delete*`

An attacker with the s3:Delete* permission can delete objects, versions, and entire buckets, disrupt backups, and cause immediate and irreversible data loss, destruction of evidence, and compromise of backup or recovery artifacts.

```bash
# Delete an object from a bucket
aws s3api delete-object \
  --bucket <BUCKET_NAME> \
  --key <OBJECT_KEY>

# Delete a specific version
aws s3api delete-object \
  --bucket <BUCKET_NAME> \
  --key <OBJECT_KEY> \
  --version-id <VERSION_ID>

# Delete a bucket
aws s3api delete-bucket \
  --bucket <BUCKET_NAME>
```



**For more info** [**check the original research**](https://rhinosecuritylabs.com/aws/s3-ransomware-part-1-attack-vector/)**.**

{{#include ../../../../banners/hacktricks-training.md}}

