I am trying to do this jQuery XSS challenge here by PortSwigger.

They have a good walkthrough for XSS attacks, however I could not find anything on jQuery, which is also a programming language I have no experience in.

The description of the challenge:

Lab: DOM XSS in jQuery selector sink using a hashchange event

This lab contains a DOM-based cross-site scripting vulnerability on the home page. It uses jQuery's $() selector function to auto-scroll to a given post, whose title is passed via the location.hash property.

To solve the lab, deliver an exploit to the victim that calls the print() function in their browser.

The answer:

Notice the vulnerable code on the home page using Burp or the browser's DevTools.

From the lab banner, open the exploit server.

In the Body section, add the following malicious iframe:

<iframe src="https://YOUR-LAB-ID.web-security-academy.net/#" onload="this.src+='<img src=x onerror=print()>'"></iframe>

Store the exploit, then click View exploit to confirm that the print() function is called.

Go back to the exploit server and click Deliver to victim to solve the lab.


Could someone please explain how this works? I cannot see the vulnerable code they mention on the homepage, and I cannot understand the process.

  • From jQuery's site: "By design, any jQuery constructor or method that accepts an HTML string — jQuery(), .append(), .after(), etc. — can potentially execute code. This can occur by injection of script tags or use of HTML attributes that execute code (for example, <img onload="">). Do not use these methods to insert strings obtained from untrusted sources such as URL query parameters, cookies, or form inputs. Doing so can introduce cross-site-scripting (XSS) vulnerabilities. Remove or escape any user input before adding content to the document." Commented Apr 4, 2023 at 21:26
  • I haven't looked at the code in question, but it sounds like this might pass a part of the URL (onhashchange fires when the URL changes) directly into script... can you include the jQuery bit of code at play here? Commented Apr 4, 2023 at 21:30

2 Answers 2


I am at the same place. Have you figured out why the exploit works from the exploit server? It makes no sense to me.

The vulnerable code is the piece of javascript using Jquery at the end of the page, just in case.

Still, I tried solving this through injectio to no avail, and don't understand the inner working of the correct answer.


The vulnerable code is this:

<script src="/resources/js/jquery_1-8-2.js"></script>
$(window).on('hashchange', function(){
var post = $('section.blog-list h2:contains(' + decodeURIComponent(window.location.hash.slice(1)) + ')');
if (post) post.get(0).scrollIntoView();

You don't actually need the iframe for an attack, you can just visit


And then add a char to the hash (but of course for a realistic attack, that's a lot of user interaction, hence the iframe trick).

The issue here is that $('[anything][user input]') in old jquery versions is vulnerable. If you pass it an XSS payload, it will execute.

Note that this doesn't work with current jquery versions if there's a string before the user input. If there isn't, it's still vulnerable:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
var post = $(decodeURIComponent(window.location.hash.slice(1)));

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .