Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Stopping typed text running as code (XSS)

After this lesson: I can stop a page from running text that a visitor typed.

50 min lesson3 commandsDVWA lab: practise SQL injection and XSS on the Damn Vulnerable Web Application

A guestbook that runs its notes

A shop adds a guestbook to its site. Visitors leave a note, and everybody reads the notes on one page.

One visitor writes a note that is not words but a tiny program. Every later visitor opens the page and their browser quietly runs it. The shop wrote none of it.

The one rule

Warning

Only test your own copy of the lab, and only with permission. It is a website made weak on purpose, with no way out to the internet. We learn this to defend a page. Doing it to a site that is not yours is a crime under the Computer Misuse Act 1990.

By the end of this lesson

Note

I can stop a page from running text that a visitor typed.

Key words

WordWhat it meansExample
Cross-site scriptinga page that runs script a visitor typedXSS
Scripta small program a browser runs inside a page
Escapeswap special characters for safe text< becomes &lt;
Reflectedsent in a request and shown straight back in the reply
Storedsaved by the site and shown to every later visitor
Cookiea small value the browser keeps and sends back to the site

The cells students fill in are left blank in this preview.

Typed text can become part of the page

A browser reads a page as text with tags in it. A <b> tag makes bold. A <script> tag runs a program.

If a site puts a visitor's text into a page unchanged, the browser cannot tell the typed text from the site's own tags. Script the visitor typed then runs as if the site had written it.

Worked example: reflected and stored

ReflectedStored
Where the text goesIn the request, then straight backInto the site's records, then later pages
Who is hitWhoever opens the crafted linkEveryone who opens the page afterwards
ExampleA search page that repeats your wordA guestbook or a product review

The cells students fill in are left blank in this preview.

Before you start

Note

Press Start the lab on the bar at the top. Your lab runs the website you will test. The three Runs only look at the sign-in page. They do not sign in and they type no script.

Is the website up?

Command
curl -s -o /dev/null -w "%{http_code}\n" http://dvwa/login.php

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

The cookies the site sets

Command
curl -s -I http://dvwa/login.php | grep -i "^set-cookie"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

How many cookies say HttpOnly?

Command
curl -s -I http://dvwa/login.php | grep -ic httponly

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

What the three answers tell you

The first prints 200, so the site is up. The second prints two lines, one for a cookie called security and one for PHPSESSID, which is the session.

The third prints 0. No cookie says HttpOnly. So a script running in a page here could read the session cookie. That is why XSS often leads to a stolen session.

Escaping turns special characters into text

The fix is to escape a visitor's text on its way into a page. < becomes &lt; and > becomes &gt;. The browser draws them as the same characters but never reads them as a tag.

Replace & first. If you replace it last, you turn the & in &lt; into &amp; and the text comes out wrong.

An escape function

Code: python
def escape(text):
    text = text.replace("&", "&amp;")
    text = text.replace("<", "&lt;")
    text = text.replace(">", "&gt;")
    return text

# Change the note and press Run. Then move the & line to the end and run again.
note = "Great bread <b>and</b> cakes & tea"
print("<p>" + escape(note) + "</p>")

A common mistake

Warning

Many people think blocking the word script when a note is saved is enough. It is not. Tags like img carry script too, and filters miss spellings. Escape when you write the text into a page, for every value, and the question never arises.

Going further

Change the code above to also escape a double quote, turning it into &quot;. Test it on the note She said "hi" <b>loudly</b>.

Then explain why a cookie marked HttpOnly is safer, in one sentence, using the word script.

About this lab and its source: DVWA lab: practise SQL injection and XSS on the Damn Vulnerable Web Application

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.