4

I am new to the field of Web Security and am practising labs from Portswigger Web Security Academy. In this lab, we have to call the alert function with 1337 as the parameter.

The solution given on the website is https://your-lab-id.web-security-academy.net/post?postId=5&%27},x=x=%3E{throw/**/onerror=alert,1337},toString=x,window%2b%27%27,{x:%27

The decoded version for reference is https://your-lab-id.web-security-academy.net/post?postId=5&'},x=x=>{throw/**/onerror=alert,1337},toString=x,window+'',{x:'

From what I understand, there is a JavaScript statement like var a = "get_parms" and we are trying to break out of the string, close the block and execute our own code.

x=x=>{throw/**/onerror=alert,1337} is the arrow function which assigns alert as global error handler and throws 1337.

toString=x, window+'' assigns x to toString and then forces a string conversion on window. Now, I have two questions:

  1. Why does this work only when I click the back to blog button, in spite of forcing the string conversion on window?
  2. What is the use of the bolded characters in the URL (the & and the {x:')?

https://your-lab-id.web-security-academy.net/post?postId=5&'},x=x=>{throw/****/onerror=alert,1337},toString=x,window+'',{x:'

Glorfindel
  • 2,235
  • 6
  • 18
  • 30
positron
  • 165
  • 10
  • Seems like the lab is behind an auth wall... Can you give more context about "back to blog" button and question 1? – Limit May 24 '20 at 06:42

3 Answers3

2

I have just completed this lab and have the same question as you do with regards to what is exactly happening around the JavaScript mentioned in your Question 1.

As per Question 2:

  • The & is simply a parameter separator since we are passing our user values via a GET request. This is esentially creating a new parameter named '},x with the rest of the XSS payload x=%3E{throw/**/onerror=alert,1337},toString=x,window+%27%27,{x:%27 as its value. This way the URL does not break, while the whole payload makes its way into the anchor tag containing the vulnerable JavaScript URL.
  • The last part of the payload {x:' completes the remaining JavaScript code '}.finally... ensuring that our injected payload does not break it, but allows it to execute properly.
zyk
  • 399
  • 1
  • 2
  • 11
1

As @zyk's answer states, the & separates URL parameters.

The URL parameters get reflected in an <a> tag at the bottom of the source view-source:https://your-lab-id.web-security-academy.net/post?postId=1&payload:

<a href="javascript:fetch('/analytics', {method:'post',body:'/post%3fpostId%3d1%26payload'}).finally(_ => window.location = '/')">Back to Blog</a>

To be more specific, the URL encoded payload is part of the value assigned to the href attribute. Therefore the payload is triggered when the Back to Blog button is clicked (Question 1). Originally /analytics is fetched.

Let's break the payload into different parts:

  • &: appends a new parameter to leave the postId parameter untouched.
  • '}: breaks out of body:'/post?postId=1'}. The code should now look like fetch('/analytics', {method:'post',body:'/post?postId=1&'}'}).finally(_ => window.location = '/')
  • ,x=x=>{throw/**/onerror=alert,1337},toString=x,window+'',: Is a fancy way to call alert(1337) (Breaking out of a JavaScript string). It basically overwrites the toString method and triggers it. ,toString=alert(1337),window+'', doesn't work, since ( and ) are blocked. The , separation is important to not break the JavaScript.
  • {x:': is supplied to not break the JavaScript.

In the end the fetch call looks like this:

fetch('/analytics', {method:'post',body:'/post?postId=1&'},x=x=>{throw/**/onerror=alert,1337},toString=x,window+'',{x:''}).finally(_ => window.location = '/')

To play around You might want to visit https://your-lab-id.web-security-academy.net/post?postId=5&%27},toString=alert,window+%27%27,{x:%27 and set a XHR/fetch breakpoint in your browser.

For Chrome: Open DevTools (F12) -> Sources -> Add XHR/fetch breakpoint when URL contains /analytics

Now, when you click Back to Blog the fetch instruction should be visible in DevTools. This can't be done with the solution payload, since the throw statement prevents/interrupts the fetch call.

upe
  • 113
  • 4
0

The reason we need to click on the link, is because that's where you're xss context is.

All we are doing by entering that payload in the get request, is injecting into href tag which contains the javascript that's vulnerable. There was no auto execution. It required a link to be clicked to trigger.

Markis
  • 1