Level 6: DOM XSS in jQuery selector sink using a hashchange event

Objective

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

To solve this lab, exploit the hashchange-triggered DOM manipulation and deliver a payload to the victim that triggers print() in their browser.

Explanation

This vulnerability arises from the unsafe use of the jQuery $() function in combination with location.hash. When the hash part of the URL (everything after #) is changed, the application reacts by selecting an element with that ID via jQuery.

If a malicious string is passed inside the hash, jQuery treats it as a selector. This opens the door to execute arbitrary code if the selector is crafted to inject HTML and trigger JavaScript — for example, injecting an <img> tag with an onerror handler.

This vulnerability is triggered on a hashchange event, meaning the payload executes when the hash in the URL changes dynamically or upon initial load.

Resolution

  1. Click Go to exploit server.

  2. In the body of the exploit page, replace the HTML with the following:

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

    Replace YOUR-LAB-ID with the actual lab ID from the URL.

  3. Click Store and then Deliver exploit to victim.

  4. Once the victim opens the page, the print() function is called and the lab is completed.

✅ To test it yourself, copy the exploit URL shown under “Craft a response” and open it in Burp’s browser. You’ll see a print dialog triggered as proof of execution.

Mitigation

  • Avoid using user-controlled values directly inside jQuery selectors, especially from location.hash or location.search.

  • Use strict input validation or encoding to prevent the injection of dangerous characters (like <, >, ").

  • Sanitize location.hash values before use by stripping any non-alphanumeric characters or patterns that resemble selectors or HTML.

  • Consider switching to safer DOM access methods (getElementById, querySelector, etc.) with controlled inputs.

  • Enforce a Content Security Policy (CSP) that restricts inline scripts and unauthorized sources.

Last updated