
đ Exposure Overview
This post covers a widely overlooked information leakage behavior across cloud storage providers â particularly AWS S3 and GCP Cloud Storage â where âAccess Deniedâ error messages still return traceable metadata. These leaks are not CVEs, but they should be considered recon-surface failures by any defender worth their salt.
When probing private or misconfigured buckets, the following data is frequently returned in the HTTP response or XML error body, even when access is correctly denied:
AccountIdâ the unique cloud account that owns the bucketRequestIdâ an operation-level UUID, often logged internallyHostIdâ internal routing metadata, which can reveal infrastructure regions or nodes
Attack Vector and Scope
- Vector: Remote unauthenticated access via HTTP GET or HEAD
- Scope: Any public-facing or guessable cloud bucket endpoint
- Privileges Required: None
- User Interaction: None
đŹ Exploitation Detail
Hereâs how it plays out:
- An attacker sends an HTTP GET or HEAD request to a guessed or discovered bucket URL
- The cloud service responds with a 403 Access Denied error
- Despite the denial, metadata is embedded in the response body or headers
Sample Response
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<AccountId>REDACTED-ACCOUNT-ID</AccountId>
<RequestId>REDACTED-REQUEST-ID</RequestId>
<HostId>REDACTED-HOST-ID</HostId>
</Error>
This data may seem harmless at first glance, but:
- It allows enumeration of valid bucket names and resource presence
- It leaks account or infrastructure identifiers
- It gives threat actors a way to trace actions across cloud services, logs, and misconfigured systems
đ Attacker Behavior Snapshot
- What the attacker sends: GET or HEAD to
https://bucket-name.s3.amazonaws.com/ - What the system does: Returns 403 + XML body with metadata
- What comes back that shouldnât:
AccountId,HostId,RequestId
đ§Ș YARA Rule
rule Exposed_CloudBucket_Metadata
{
strings:
$access_denied = "AccessDenied"
$request_id = /<RequestId>[A-Za-z0-9+\/=]+<\/RequestId>/
$host_id = /<HostId>[A-Za-z0-9+\/=]+<\/HostId>/
$account_id = /<AccountId>[A-Za-z0-9\-]+<\/AccountId>/
condition:
all of them
}
đ Suricata Rule
alert http any any -> any any (
msg:"Potential Cloud Bucket Metadata Leak";
content:"AccessDenied";
http_client_body;
pcre:"/<RequestId>[A-Za-z0-9+\/=]+<\/RequestId>/";
classtype:attempted-recon;
sid:2025091201;
rev:1;
)
⥠Sigma Rule
title: Cloud Storage Bucket Metadata Leak
logsource:
category: webserver
detection:
selection:
EventID: 403
Message|contains:
- "Access Denied"
- "RequestId"
- "HostId"
- "AccountId"
condition: selection
level: medium
đ Splunk Query
index=web OR index=proxy
status=403
("Access Denied" AND ("RequestId" OR "HostId" OR "AccountId"))
| stats count by uri_path, src_ip, user_agent
đ ïž SOC Detection Strategy
Tier 1â3 Triage Recommendations
- Tier 1: Monitor external traffic hitting known cloud bucket URLs with 403s
- Tier 2: Correlate source IPs and user agents for mass enumeration or scanning
- Tier 3: Tie
HostIdto backend infrastructure or leaked internal topology
Log Sources
- AWS CloudTrail or GCP Audit Logs
- Web server logs (Apache, Nginx, CloudFront, etc.)
- Firewall and proxy logs
đ Hardening & Mitigation
- Enforce âBlock Public Accessâ or equivalent on all cloud storage buckets
- Use explicit deny policies on IAM roles and bucket permissions
- Mask or suppress metadata in error responses using API Gateway or HTTP header manipulation
- Enable audit logging to catch repeated probes on denied endpoints
đ Incident Response Snippets
- IR Hunt Query:
index=web "Access Denied" "RequestId" "HostId" "AccountId" src_ip!=internal - IR Questions: Was the bucket ever public? Is the
AccountIdreused across other buckets or services? - Indicators to Hunt: Leaked
HostIdvalues, repeated enumeration attempts, unusual User-Agent strings - Cleanup: Rotate bucket names, review IAM policy scope, inspect logs for related enum attempts
đ Suggested Reading & External References
đ§Ÿ Final Thoughts
This isnât a zero-day â itâs a zero-effort leak that most orgs never see coming. âAccess Deniedâ isnât the end of the conversation. Itâs often just the start of the metadata breadcrumb trail. HostId values can fingerprint regions. AccountId values can correlate services. RequestId values can be replayed or abused in other AWS services.
If your cloud bucket returns anything other than a dead silent 403 â youâve got a recon hole. Seal it. Log it. Monitor it.
Published: September 12, 2025
Leave a Reply