The Ravens’ forum has a search box. The server replies with a page that writes your search term straight into the page HTML, untouched. The Lookout opens whatever search results you send him.
The Ravens forum is an app with a thread list and a search page. You type a term, it posts to /search, and the server builds a results page that pastes your term into the page HTML with no encoding. The Lookout button simulates the victim opening your results link in his browser.
Make the results page run code that calls steal() — the code that, in a real attack, would send the victim’s session to the Ravens.
The results page contains running code that calls steal.
Why the solution worked
This is reflected XSS: what you typed came straight back inside the response page and ran. The server built HTML by pasting your input in with no encoding, so the text became a script element. The fix is to encode output for its context before placing it in the page: characters like <, >, " and & become their entities (<, >), so user input stays text and never becomes code.
The root cause
The server builds HTML by concatenating user input with no output encoding, so text becomes an element. The flaw is in output, not input.
How the code is fixed
Rule: encode on output, not on input, with the right encoding for each context (HTML text, HTML attribute, JavaScript, URL). Modern template engines do this for you by default.
Vulnerable code
app.get('/search', (req, res) => {
const q = req.query.q;
// The term is pasted straight into HTML: text becomes markup.
res.send('<p class="results">No posts match: ' + q + '</p>');
});
Safe code
app.get('/search', (req, res) => {
const q = req.query.q;
// Encode for the HTML text context, so < > " & can never start a tag.
res.send('<p class="results">No posts match: ' + escapeHtml(q) + '</p>');
});
Impact in the real world
Reflected XSS arrives in a crafted link sent to the victim; opening it runs the attacker code in the site context, stealing sessions and acting as the victim. It is one of the most common web bugs.
How defenders detect it
Defenders watch request logs for parameters carrying tags and characters like < >, and words like onerror, and deploy a strict CSP that blocks unauthorized script execution as a second layer.