- by x32x01 ||
A powerful XS-Leak vulnerability was discovered in CTFd versions below 3.7.2, allowing attackers to leak secret CTF flags from admin accounts - without using XSS.
This wasn’t a classic injection flaw.
This was browser side-channel exploitation at its finest. 💀
If you’re serious about bug bounty, web security, or advanced exploitation techniques, this is the kind of vulnerability that separates beginners from real researchers.
Instead, they abuse tiny side effects caused by cross-origin requests.
Even though the Same-Origin Policy (SOP) prevents attackers from reading responses directly, browsers still expose small signals like:
Combined? They become a data exfiltration channel.
That’s the power of XS-Leaks.
Here’s where things broke:
An oracle in security terms means:
There were protections in place:
If the page was opened in a top-level navigation context, cookies were still sent.
That reopened the attack surface.
This is where understanding browser behavior becomes a real advantage.
Example:
If the prefix was correct →
If incorrect →
Now the challenge becomes:
How do you detect that difference from another origin?
That’s where things get creative.
But failed loads (404) may not be stored the same way.
This created a new side channel:
And CSS provided the answer.
Modern browsers block JavaScript from directly reading computed styles.
But attackers can still:
If one URL was previously loaded successfully (200), it becomes
That leaks one character.
Repeat the process.
Flag extracted.
No XSS required. 😈
Instead of tricking the victim into clicking links, attackers used:
Subtle rendering differences reveal which link was visited.
That made the attack:
Together? Critical data leak.
This is why logic flaws often become high-impact vulnerabilities.
No signal → No leak.
Modern exploitation is no longer just:
XS-Leaks are advanced skills - but they’re incredibly powerful.
Keep responses uniform in:
Understand how browsers actually work.
They leak more than you think. 💀
This wasn’t a classic injection flaw.
This was browser side-channel exploitation at its finest. 💀
If you’re serious about bug bounty, web security, or advanced exploitation techniques, this is the kind of vulnerability that separates beginners from real researchers.
What Are XS-Leaks? (Cross-Site Leaks) 🔍
XS-Leaks don’t directly steal response data.Instead, they abuse tiny side effects caused by cross-origin requests.
Even though the Same-Origin Policy (SOP) prevents attackers from reading responses directly, browsers still expose small signals like:
- HTTP status code differences (200 vs 404)
- Page size variations
- Frame count differences
- Timing discrepancies
- History state changes
- CSS rendering differences like
:visited
Combined? They become a data exfiltration channel.
That’s the power of XS-Leaks.
The Target: Admin Flag Submissions in CTFd 🎯
In vulnerable CTFd versions, admins could search flag submissions using: Code:
GET /admin/submissions?q=FLAG_VALUE - ✅ If a matching flag existed →
200 OK - ❌ If no match existed →
404 Not Found(on specific paginated pages)
An oracle in security terms means:
And that’s exactly what happened.A behavior difference that reveals whether a guess is correct.
Why Traditional XS-Leak Techniques Failed 🚧
At first glance, the attack shouldn’t have worked.There were protections in place:
SameSite=Laxcookies- Framing protections
- Cross-origin restrictions
If the page was opened in a top-level navigation context, cookies were still sent.
That reopened the attack surface.
This is where understanding browser behavior becomes a real advantage.
Step 1: Turning Search into a Flag Oracle 🧪
The attacker brute-forced the flag one character at a time.Example:
Code:
/admin/submissions?q=FLAG{A
/admin/submissions?q=FLAG{B
/admin/submissions?q=FLAG{C 200 OKIf incorrect →
404 Not FoundNow the challenge becomes:
How do you detect that difference from another origin?
That’s where things get creative.
Step 2: Abusing Browser History 📜
Browsers store successful page loads (200 OK) in history.But failed loads (404) may not be stored the same way.
This created a new side channel:
- 200 → Stored in history
- 404 → Not stored
And CSS provided the answer.
Step 3: Leaking Data Using CSS :visited 🎨
Browsers allow styling of visited links: Code:
a:visited {
color: red;
} But attackers can still:
- Generate many candidate links
- Only one becomes :visited
- Detect layout/rendering differences
- Infer which character is correct
HTML:
<a href="https://target.com/admin/submissions?q=FLAG{A">A</a>
<a href="https://target.com/admin/submissions?q=FLAG{B">B</a>
<a href="https://target.com/admin/submissions?q=FLAG{C">C</a> :visited.That leaks one character.
Repeat the process.
Flag extracted.
No XSS required. 😈
Fully Automated XS-Leak (No User Click Needed) 🤯
The exploit evolved further.Instead of tricking the victim into clicking links, attackers used:
- CSS layout differences
- Rendering measurements
- Timing side channels
JavaScript:
const start = performance.now();
document.body.offsetHeight;
const end = performance.now();
console.log(end - start); That made the attack:
- Stealthy
- Automated
- Scalable
Root Cause Analysis 🛠️
The vulnerability happened because of three things combined:- Secret-dependent HTTP status codes
- Browser history behavior
- CSS
:visitedrendering differences
Together? Critical data leak.
This is why logic flaws often become high-impact vulnerabilities.
The Fix in CTFd 3.7.2 🛡️
The patch included:- Removing
404behavior in pagination (error_out=False) - Ensuring consistent HTTP response codes
- Adding
Cross-Origin-Opener-Policyheaders - Reducing cross-window references
No signal → No leak.
Why This Matters for Bug Bounty Hunters 🎯
If you’re serious about bug bounty and penetration testing, here’s the takeaway:Modern exploitation is no longer just:
- XSS
- SQL Injection
- Command Injection
- Side channels
- Browser internals
- Logic flaws
- Subtle behavioral differences
XS-Leaks are advanced skills - but they’re incredibly powerful.
Key Security Lessons 🔥
Never return secret-dependent status codes.Keep responses uniform in:
- Size
- Timing
- Status
- Structure
- COOP
- COEP
- CORP
Understand how browsers actually work.
They leak more than you think. 💀