Skip to contentExploitQuest

Lesson 1 of 3 in Cross-Site Scripting · 6 min left in this chapter

Whose Code Runs

A browser cannot tell the markup you typed from the markup the site wrote — it runs both with the same authority. When a page prints your input into its HTML without escaping it, your script runs as if the site had written it.

3 min read

Not yet reviewed

Wrenlearner

The last four labs all broke the server — its query, its files, its tokens. What is left to break?

Rookmentor

Everyone else's browser. Cross-site scripting does not attack the server at all. It gets *your* script to run in *another user's* page — with their session, their cookies, their rights. The server just carries it there.

Two kinds of code in one page

When a browser loads a page, everything in the HTML is the site's — the text, the buttons, and any <script>. The browser trusts all of it equally, because it has no way to tell which parts the site's authors wrote and which parts arrived from somewhere else. A script in the page runs with the page's authority: it can read the page's cookies, make requests as the logged-in user, and change what the user sees. That is fine while the whole page really is the site's — and it stops being fine the moment the page prints something a *user* supplied straight into its HTML. Now the user's text is code in the site's page, running with the site's authority.

The sink is the same as ever

A comment rendered into the page

page += "<div class=comment>" + comment.body + "</div>"

What an attacker puts in the body

<img src=x onerror="/* my code, in your page */">

The body is concatenated into HTML with no escaping. <img src=x> fails to load on purpose, so its onerror handler runs — and that handler is whatever the attacker wrote. No <script> tag required.

You have seen this shape four times. Injection let input act as a query; traversal let it act as a path; a forged token let a field decide who you are. Here, input rendered into a page acts as script. The vulnerability is never the <img> — it is that the page built its HTML by gluing untrusted text into it.

Stored, and reflected

Where the script comes from splits XSS into two families. Reflected XSS rides in the request — a search term echoed into the results page — and only fires for someone who follows the attacker's link. Stored XSS is saved: a comment, a profile, a forum post the server keeps and shows to everyone who views it. Stored is the worse of the two, because the victim does nothing unusual. They read a thread. The script was already waiting.

The attacker writes the post, but their own browser running it would only expose their own cookies. So who is the victim of a stored XSS in a forum post?