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
| Word | What it means | Example |
|---|---|---|
| Cross-site scripting | a page that runs script a visitor typed | XSS |
| Script | a small program a browser runs inside a page | |
| Escape | swap special characters for safe text | < becomes < |
| Reflected | sent in a request and shown straight back in the reply | |
| Stored | saved by the site and shown to every later visitor | |
| Cookie | a 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
| Reflected | Stored | |
|---|---|---|
| Where the text goes | In the request, then straight back | Into the site's records, then later pages |
| Who is hit | Whoever opens the crafted link | Everyone who opens the page afterwards |
| Example | A search page that repeats your word | A 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?
curl -s -o /dev/null -w "%{http_code}\n" http://dvwa/login.phpShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
The cookies the site sets
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?
curl -s -I http://dvwa/login.php | grep -ic httponlyShown 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 < and > becomes >. 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 < into & and the text comes out wrong.
An escape function
def escape(text):
text = text.replace("&", "&")
text = text.replace("<", "<")
text = text.replace(">", ">")
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 ". 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.