Full Report
The author was playing around with some functionality on a website. While doing this, they realized that part of the URL was being copied into an open graph tag. Given that open graph tags are likely handled at a different level, they wanted to ensure that client side issues were being handled. They added a double quote to the URL to make it https://xss.2n.wtf/points/test" to no avail; the double quote was URL encoded. Now, they tried adding this via Burp Suite. To their amazement, the double quote had reflected back and had escaped the context of the URL! What was the issue? The URL encoding! Seems like a non-issue at this point; it may not be exploitable. They decided to check out how the caching via Cloudflare worked. Cloudflare treated both the double quote (") and the URL encoded double quote (%22) as the same thing! According to here, you are supposed to URL encode double quotes, which is why the browser does it. This creates a cache poisoning situation. Make a request with the raw double quote, get a user to click on the particular request WITH the double quote and you have stored XSS. At this point, they had to bypass the WAF as well. This was done via using slashes instead of spaces over and over again. The cache was per region as well, requiring a ton of requests to ensure a victim was hit by it. Unfortunately, there were some limitations on this. First, everything had to be lowercased and colons couldn't be used. Second, a limit on the amount of characters in a URL was placed. So, they needed to find a way to run arbitrary code. They imported code from a different location (at some URL) in order to do this. Because of the colon restriction, they added the domain to make the request to in a different URL parameter. Great find! This was probably missed for years because of the weird way to trigger it. XSS comes in weird spots; gotta look out for those reflected inputs!
Analysis Summary
# Vulnerability: Stored XSS via Web Cache Poisoning & WAF Bypass
## CVE Details
- **CVE ID**: Not Assigned (Private Bug Bounty Discovery)
- **CVSS Score**: 8.1 (High) - *Estimated based on Stored XSS impact and required user interaction via poisoned cache.*
- **CWE**: CWE-79 (Cross-site Scripting), CWE-522 (Insufficient Cache Key De-serialization)
## Affected Systems
- **Products**: Web applications utilizing Cloudflare for caching and WAF protection.
- **Versions**: Platform-agnostic; dependent on specific Cloudflare Worker configurations or Cache Key normalization settings.
- **Configurations**: Applications that reflect URL path segments into HTML meta tags (e.g., `og:url`) and share cache keys between URL-encoded and non-encoded requests.
## Vulnerability Description
The vulnerability arises from an inconsistency in how the origin server and the edge cache (Cloudflare) handle URL encoding. The origin web application reflected the URL path directly into the `og:url` Open Graph meta tag without proper sanitization.
While modern browsers automatically URL-encode special characters (like `"` becoming `%22`), the backend server was found to reflect raw double quotes if submitted via a manual request (e.g., Burp Suite). Crucially, the cache layer treated `test"` and `test%22` as the same cache key. By seeding the cache with a raw double quote via a manual request, an attacker "poisons" the version served to legitimate users, even if the users' browsers request the encoded version.
## Exploitation
- **Status**: PoC available/Exploited in a controlled bug bounty environment.
- **Complexity**: High
- **Attack Vector**: Network
- **Technical Hurdles**:
- **WAF Bypass**: Cloudflare WAF was bypassed using slashes instead of spaces and unconventional tag structures.
- **Character Restrictions**: The application forced lowercase and blocked colons (`:`).
- **Exploit Payload**: To overcome length and colon limits, the researcher used a secondary URL parameter to host the external script source and imported it into the reflected context.
## Impact
- **Confidentiality**: High (Session hijacking via cookie theft)
- **Integrity**: High (Execution of arbitrary JavaScript in the victim's browser)
- **Availability**: Low (Localized to specific cached regions)
## Remediation
### Patches
- **Origin-Side**: Implement strict output encoding on all reflected inputs, specifically those appearing in HTML attributes or meta tags. Use a "Defensive Encoding" approach where both raw and encoded characters are sanitized.
- **Infrastructure-Side**: Adjust Cloudflare "Normalization" settings to ensure strict differentiation between literal characters and their URL-encoded equivalents in cache keys.
### Workarounds
- Disable caching for pages that reflect user-controlled URL segments.
- Implement a strict Content Security Policy (CSP) to prevent the execution of inline scripts or unauthorized external scripts.
## Detection
- **Indicators of Compromise**: Presence of unexpected HTML tags (e.g., `">` or `<script>`) within `<meta property="og:url">` tags in cached responses.
- **Detection Methods**: Use automated scanners to compare responses between encoded (`%22`) and unencoded (`"`) path requests. Monitor for "Cache Hit" headers on responses containing suspicious payload strings.
## References
- [https://ltsirkov.medium.com/cross-site-scripting-via-web-cache-poisoning-and-waf-bypass-6cb3412d9e11](https://ltsirkov.medium.com/cross-site-scripting-via-web-cache-poisoning-and-waf-bypass-6cb3412d9e11)
- [https://ogp.me/](https://ogp.me/)
- [https://xss.2n[.]wtf/points/test"](https://xss.2n[.]wtf/points/test")