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

## <mark style="color:purple;">Objective</mark>

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.

## <mark style="color:purple;">Explanation</mark>

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.

## <mark style="color:purple;">Resolution</mark>

1. Click **Go to exploit server**.
2. In the **body** of the exploit page, replace the HTML with the following:

   ```html
   <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.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeZBvnuvXpf30ApyijXtJ0karDQ1m0337ZQzqewDMLn84_E_8pf_wE_2sSEIHqyAzzCvy5dkjJQeohxlGOALWLgGBotK4ob4QZaeEWF65uPG-Pfdw2wr9o7CJy4OTgTZybpCiUISw?key=-BCZ-tSX4vSf40JHJNVK-jBl" alt="" width="375"><figcaption></figcaption></figure>

## <mark style="color:purple;">Mitigation</mark>

* **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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://patricio-burattini.gitbook.io/burattini-machines/portswigger-labs/xss/apprentice/level-6-dom-xss-in-jquery-selector-sink-using-a-hashchange-event.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
