◆ Acme Portal customer portal this page's origin … Message monitor
postMessage XSS lab

Acme Portal

This is the application under test. It embeds third-party widgets in iframes and talks to them with postMessage. Every scenario below is the flow from “postMessage XSS” (Arash Shahbazi, Jan 2025), reproduced exactly — including the parts that need correcting.

How the lab is wired. Every participant runs on its own real origin — a separate hostname under pmlab.amir.baby, all served by this one server. Origin checks are genuine and a blocked message really is blocked. Open the victim page and the attacker page in two tabs — they must be different origins for the attack to mean anything.

Scenarios

#Writeup findingVictim pageAttacker page
S1 Insecure listener + postMessage(data, "*") → XSS in the receiver /s1-widget https://attacker.pmlab.amir.baby/s1
S2 Weak domain validation → a subdomain of the trusted domain is accepted /s2-base (weak)
/s2-exact (as written in the writeup)
https://attacker.trusted-domain.pmlab.amir.baby/s2
S3 Weak regex in the origin check → bypassed by a crafted subdomain /s3-regex https://attacker.com.trusted-origin.pmlab.amir.baby/s3
S4 Data exposure — sensitive data sent with "*" is sniffed /s4-session https://attacker.pmlab.amir.baby/s4
S5 The fix — same flow, done correctly /s5-fixed —

How the writeup's flow works

Sender Window                                    Receiver Window
──────────────                                   ───────────────
const receiverURL = "http://localhost/receiver.html";
const childWindow = window.open(receiverURL);      window.addEventListener('message', (event) => {
                                                     document.querySelector('p').textContent = event.data;
function sendMessage() {                           });
  const message = "Hello, Receiver!";
  childWindow.postMessage(message, "*");

The receiver decides how much it trusts the sender. Everything in this lab is a variation of that one line — what the receiver checks, and what it does with the payload when it believes the sender.