Full Report
This is a Cross-Site (XS) Leaks CTF challenge with a couple of nifty tricks. The user creates a page with HTML injection that the admin then clicks on using a tool like Selenium. The goal is to leak the user's session cookie using this with a known token format. This uses a PHP server that is behind Caddy. The limitations are also interesting. The content for the HTML injection is limited to 1024 characters. The characters can be 0x20-0x7E and newlines, but block several things like astriks, backslashes, and a few keywords. There's a CSP that prevents outbound loading of scripts, inline JavaScript, or web requests. The browser has what is called Quirks Mode that relaxes some MIME checks. If the document loads a page with the wrong content type, it will treat it as text/css anyway. This challenge was set up to NOT use quirks mode because of the at the beginning of the page. Can this be forced into Quirks mode? If the beginning part of the page were to change in some way before loading, then this would be possible. In PHP, there are multiple ways to trigger errors that will be put at the top of the file instead. In previous research, this was done to drop CSP headers. In this case, if you added a large number of variables (more than a thousand), PHP gives a warning that ends up disabling quirks mode! Neat! The HTML injection occurs. However, there is no practical way to exfiltrate the data due to the CSP. So, the only way is to use CSS data exfiltration. This is why the issue pointed out above with the Quirks mode is so helpful! With a simple payload, it's possible to change the color of the page. Because of some character limitations, we need to find a way to load more data for our stylesheet. Luckily, the PHP 404 page will reflect input and can be used for this. Using /not-found.txt?{}body{background:limegreen} is a good sink for this. Finally, in the CSS selectors, use the input:valid flag to decide whether to render the data or not based on the input from the previous step. Why does this matter? Frame counting! By viewing the page and counting the frames, we can figure out if the code was correct or not. Overall, a pretty neat set of tricks! CTFs are sometimes on the cutting edge and niche; this is a perfect example of that.
Analysis Summary
# Research: Forcing Quirks Mode with PHP Warnings + CSS Exfiltration without Network Requests
## Metadata
- Authors: Self-authored (Implied: the author of the blog post/challenge creator)
- Institution: N/A (CTF Challenge write-up/analysis)
- Publication: XS-Spin Blog (Author's blog)
- Date: September 8, 2025 (Based on the article date)
## Abstract
This research documents the technical analysis and exploitation techniques used to solve a complex Cross-Site (XS) Leaks Capture The Flag (CTF) challenge. The solution involved a multi-stage bypass targeting strict security mitigations, including Content Security Policy (CSP) and standard HTML rendering rules. Key innovations include forcing the browser into Quirks Mode via a controlled PHP error, utilizing a server component (the 404 handler) as a controlled sink for CSS injection, and performing data exfiltration entirely via CSS properties combined with frame counting, bypassing traditional network request restrictions.
## Research Objective
The primary objective of this analysis is to detail the methodology required to successfully exfiltrate sensitive data (a session cookie formatted as a known token) from an administrative user context in an XS-Leaks scenario, specifically overcoming restrictive security policies like CSP and the standard requirement for non-Quirks Mode rendering of external stylesheets.
## Methodology
### Approach
The approach was a layered, step-by-step bypass of security restrictions:
1. **Quirks Mode Induction:** Manipulating the environment to disable the browser's strict rendering mode.
2. **CSS Sink Identification:** Finding an injection point that allows arbitrary CSS content to be loaded without triggering existing comment filters or MIME-type restrictions.
3. **Data Exfiltration Bypass:** Applying CSS data leakage techniques that circumvent CSP restrictions against outgoing network requests (e.g., `fetch`, `XMLHttpRequest`, `beacon`) by leveraging visual feedback mechanisms (frame counting).
### Dataset/Environment
The targeted environment was a custom challenge setup featuring:
* **Vulnerability:** HTML injection via a GET parameter (`/?content=...`) limited to 1024 characters and a restricted character set (0x20-0x7E, excluding characters like `*`, `\`).
* **Backend:** PHP server.
* **Proxy/Security Layer:** Caddy, which enforces a restrictive Content Security Policy (CSP) and handles load balancing across multiple PHP instances.
* **Goal:** Leak a session cookie with a known token format from an admin bot clicking the injected content.
### Tools & Technologies
* HTML/CSS injection payloads.
* PHP error handling (specifically triggering `max_input_vars` warnings).
* Browser rendering engine features (Quirks Mode).
* CSS selectors (`:valid`) and styling properties (color/background).
* Frame counting for exfiltration verification.
* Node.js/JavaScript environment (implied, for the automated bot/exfiltration frame).
## Key Findings
### Primary Results
1. **Forced Quirks Mode:** The page, designed to load external stylesheets only if they are `text/css`, can be forced into Quirks Mode by injecting over 1000 query parameters, triggering a PHP warning that outputs before the initial DOCTYPE declaration, thereby disabling standard rendering coherence.
2. **CSS Injection via 404 Handler:** Controlled HTML injection in the main page was blocked from loading arbitrary CSS due to validation restrictions preventing comment closure (`*` disallowed). This was bypassed by leveraging the PHP 404 error page, which reflects the requested path, allowing CSS rules to be injected directly into the URL path of a request to a non-existent file (e.g., `/not-found.txt?{}body{...}`).
3. **Exfiltration via Frame Counting:** Due to a CSP that blocked all standard network requests (like `beacon` or `fetch`), data exfiltration was achieved by modifying the color based on input validation flags (`:valid`). By embedding these styles within multiple elements (frames/iframes) and counting the frames that successfully render (or change color based on the leaked character), the attacker can reconstruct the remote token one character at a time without making prohibited outbound network calls.
### Supporting Evidence
* Triggering $1000+$ parameters causes a PHP warning, resulting in `document.compatMode === "BackCompat"` (Quirks Mode).
* In Quirks Mode, the browser relaxes the `Content-Type` check for same-origin stylesheets, allowing the CSS payload to execute even if the response claims to be non-CSS.
* The final exfiltration relied on iteratively guessing characters of the token and confirming the successful rendering via the count of frames that exhibited the expected style change.
### Novel Contributions
The solution combines several niche security bypasses in a novel chain:
* **PHP-based Quirks Mode manipulation:** Adapting a known PHP header-spoofing technique (via overflow warnings) to manipulate browser rendering mode.
* **Environment-Specific CSS Sink:** Successfully pivoting from a restricted HTML injection point to an unrelated server feature (the 404 handler) to achieve unconstrained CSS input.
* **Non-Network CSS Exfiltration:** Using frame counting *in conjunction with* conditional CSS based on input selectors to achieve brute-force exfiltration when standard data channels are blocked by CSP.
## Technical Details
The payload structure exploited the following relationships:
1. **Quirks Mode Bypass Preparation:** The attacker sends a URL with $>1000$ query parameters, causing the PHP server (before processing the main vulnerable logic) to issue a warning and skip the strict DOCTYPE declaration, forcing Quirks Mode.
2. **CSS Loading:** Because the page is now in Quirks Mode and the payload is same-origin, the browser accepts the CSS loaded via `<link>` even if Caddy returns a non-`text/css` `Content-Type` (which it would normally do if the request was routed normally).
3. **Injection Vector:** The payload must land in a location where it can be loaded as a stylesheet. By making the injection look like a request for a non-existent resource (e.g., `/not-found.txt?{}body{...}`), the attacker uses the reflected path in the 404 response body as the stylesheet content itself.
4. **Exfiltration:** The token character state is encoded in CSS selectors (e.g., `input:valid`). By iterating through possible characters which, when applied, cause a color change only if the character matches the secret token, and verifying this change across multiple rendering frames, the data is leaked serially.
## Practical Implications
### For Security Practitioners
This analysis highlights that security assumptions based on a single defense layer (like a strict CSP) are often insufficient. XS-Leaks vulnerabilities remain potent when combined with environment manipulation techniques, such as browser rendering mode confusion.
### For Defenders
Defenders must recognize that server configurations (like PHP error reporting) can directly impact client-side security context (like Quirks Mode). Furthermore, mitigating XS-Leaks requires a defense-in-depth approach that restricts not only direct data exfiltration vectors (like network requests via CSP) but also visual/timing leakage channels (like CSS manipulation combined with input selectors).
### For Researchers
This work provides a sophisticated case study template for combining environmental tampering (Quirks Mode), unusual injection sinks (404 pages), and advanced blind exfiltration techniques (frame counting/CSS visibility). Future research could explore other server-side errors or configuration artifacts that could similarly impact client-side rendering modes.
## Limitations
The core prerequisite for this complex exploit chain was **Quirks Mode enforcement through a PHP warning**, which only works because the initial HTML injection point was blocked from serving CSS directly *and* the server configuration allowed an error to be emitted early enough to precede the document type declaration. The success is dependent on the admin session being processed by a browser instance controlled by the attacker's generated environment (e.g., an automated rendering bot).
## Comparison to Prior Work
This challenge builds upon established RPO (Relative Path Overwrite) techniques, which traditionally required Quirks Mode, but solves the challenge of **entering** Quirks Mode when it was explicitly disabled by the initial HTML structure. It also extends known CSS exfiltration (which often uses `background-image` requests) by adapting it to a CSP where *all* network requests are forbidden, substituting network exfiltration with visual state counting.
## Real-world Applications
While this is a CTF scenario, the underlying principle—using server-side unexpected behavior (PHP errors) to disrupt client-side security contexts (Quirks Mode) to enable advanced side-channel attacks—is relevant to testing the robustness of sandboxed content rendering environments.
## Future Work
Further investigation into how various server technologies (beyond PHP) can be coerced into outputting non-HTML content or metadata before expected headers are sent could yield parallel exploitation techniques for browser mode manipulation.
## References
- Pilvar's previous research on dropping CSP headers via PHP warnings (Cited concept).
- W3C/WHATWG specifications regarding stylesheet processing and Quirks Mode relaxation.