In this post, we’re going to be solving the lab: “DOM XSS in jQuery selector sink using a hashchange event”:

DOM XSS in jQuery selector sink lab start screen

To solve the lab, we need to send a victim an exploit that leverages the lab’s vulnerability to execute the print() function.

First of all, let’s access the lab:

Lab main page showing blog articles

In this case, we don’t see any search bar or feedback page as has happened in other XSS challenges. However, if we go to the source code, we find the following piece of code:

Vulnerable JavaScript code with jQuery selector

This code basically searches for a value on the website when something is specified in the URL after a hashtag and scrolls to the match.

For example, if we go all the way down to the bottom of the lab, we can see that there’s a post that has the word “Resume” in the title:

Blog article with title containing the word Resume

Knowing this, we’re going to search for:

  • <URL>/#Resume

URL with hash fragment Resume in the address bar

We press enter.

Automatic scroll to the article with the word Resume

And although it can’t be appreciated in the image, it automatically redirects us to the post that contains the word.

To see how to exploit this, let’s bring back the code:

JavaScript code showing vulnerable jQuery selector

As we can observe, what really happens in the code is that when we specify something after the hashtag, jQuery tries to find an h2 element that contains what we said. When it finds the element, it’s stored in the post variable, so now what it contains is a jQuery element that looks like this:

jQuery object in console showing found element

Note: a different lab URL shows up because this is a screenshot I took at another time :P

Subsequently, if the post variable has any stored data, the first element of the jQuery object is obtained and the scrollIntoView() method is used.

Here the vulnerability as such is found in the first line, in the jQuery selector sink ($()):

Vulnerability in jQuery selector highlighted in the code

Detail of vulnerable jQuery selector in the console

Note: this image is also from another time :P

If it’s not sanitized properly, what happens approximately in the code is the following:

  • $('section.blog-list h2:contains(' + decodeURIComponent(window.location.hash.slice(1)) + ')');
  • $('section.blog-list h2:contains(' + Hello + ')');

Therefore, if we put a payload like the following:

  • <img src=/ onerror=print()>

More or less, something like this would happen:

  • $('section.blog-list h2:contains(' + <img src=/ onerror=print()> + ')');

This way, it would be interpreted. Let’s test it:

XSS payload injected in the hash fragment of the URL

We press enter:

Successful execution of the print function through the payload

And indeed it executes. Now we need to create an exploit that we send to the victim and makes use of this vulnerability. To do this, we go to the exploit server:

Button to access the exploit server

Exploit server interface in PortSwigger

In this case, the idea is to automate the exploitation using a simple <iframe>:

HTML code with malicious iframe in the exploit server

Before sending it, let’s see what it would look like:

Button to preview the exploit before sending it

Exploit preview showing loaded iframe

The victim when visiting a website with our code would see what we’re seeing, a small iframe of the website, and immediately after the website loads, the print() function would execute:

Print dialog automatically executed by the exploit

So, seeing that it works, we simply save it and send it to the victim:

Buttons to save and deliver the exploit to the victim

Confirmation of exploit delivery to the victim

This way, we successfully solve the lab:

Lab solved successfully message

Final confirmation of lab success