> For the complete documentation index, see [llms.txt](https://simon-6.gitbook.io/simoncyber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://simon-6.gitbook.io/simoncyber/portswigger-web-academy/xss/dom-based-xss/lab-1.md).

# Lab 1

<figure><img src="/files/jfQwibamQj4rpFzVnQef" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/M026eAIHbpcN1OMS7V55" alt=""><figcaption></figcaption></figure>

### Explaining the Code

```javascript
var stores = ["London","Paris","Milan"];
var store = (new URLSearchParams(window.location.search)).get('storeId');
document.write('<select name="storeId">');
if(store) {
    document.write('<option selected>'+store+'</option>');   // ← VULNERABLE LINE
}
for(var i=0;i<stores.length;i++) {
    if(stores[i] === store) {
        continue;
    }
    document.write('<option>'+stores[i]+'</option>');
}
document.write('</select>');
```

### **`window.location`**

`window` is the JavaScript object that represents the browser tab. It has tons of properties. One of them is `location`, which holds info about the current URL.

So **`window.location.search` is just a string containing the query string of the current URL**. That's it. If your URL is `?storeId=hello`, then `window.location.search` is the string `"?storeId=hello"`.

```
var raw = window.location.search;              // "?productId=2&storeId=London"
var params = new URLSearchParams(raw);          // wraps it in a helper object
var store = params.get('storeId');              // "London"
```

Every DOM XSS has the same shape:

1. **Source** — somewhere attacker data enters JavaScript. Almost always one of:
   * The URL (`window.location.search`, `window.location.hash`)
   * User input fields
   * Stored data (cookies, localStorage)
   * Messages from other windows (`postMessage`)
2. **Sink** — somewhere JavaScript does something dangerous with that data. Common ones:
   * `document.write(x)` ← writes `x` as HTML
   * `element.innerHTML = x` ← also writes as HTML (but won't run `<script>` tags!)
   * `eval(x)` ← executes `x` as JavaScript code
   * `setTimeout(x, ...)` if `x` is a string ← same thing

```
/product?productId=2&storeId=%3Cscript%3Ealert(1)%3C/script%3E
```

`product?productId=1&storeId=1234"></select><img%20src=1%20onerror=alert(1)>`

Now you can see what each character of `"></select><img src=1 onerror=alert(1)>` is doing:

| Character                      | What it does                                                                       |
| ------------------------------ | ---------------------------------------------------------------------------------- |
| `"`                            | Closes the `value="..."` attribute that the JS was building                        |
| `>`                            | Closes the `<option>` tag that the JS was building                                 |
| `</select>`                    | Closes the parent `<select>` so the `<img>` ends up somewhere it can actually load |
| `<img src=1 onerror=alert(1)>` | The actual payload — a broken image whose failure runs JS                          |

<figure><img src="/files/QDlnyuUycZlTevDoqtXd" alt=""><figcaption></figcaption></figure>

What we want to do is use the storeId parameter to break out, hence we want to break it out.

<figure><img src="/files/405Qhr4C83bAY32blsHo" alt=""><figcaption></figcaption></figure>

We always want to use Inspect (f12) instead of inspecting the source.

{% hint style="info" %}
**View Source (Ctrl+U)** = the raw HTML the server sent. Pre-JavaScript.

**Inspect (F12 → Elements)** = the live DOM after JavaScript has run.\
\
For finding YOUR injection point, use Inspect (Image 1)

Because the JavaScript is what's building the dangerous HTML, what matters is **what the DOM looks like after the JS runs**. That's where your payload will actually land.
{% endhint %}

1. Browser sends request to server
2. Server sends back HTML ← this is what View Source shows you (a snapshot)
3. Browser parses the HTML and builds the DOM (an internal tree representation)
4. Browser runs any tags it finds
5. Those scripts can ADD, REMOVE, or MODIFY parts of the DOM
6. The DOM is now different from the original HTML ← this is what Inspect shows you (the current state)
