Loading HuntDB...

DOM XSS on multiple Automattic domains through postMessages

High
A
Automattic
Submitted None
Reported by renniepak

Vulnerability Details

Technical details and impact analysis

Cross-site Scripting (XSS) - DOM
Hi Automattic team, I have found a 2 flaws that when combined lead to DOM XSS on every website that is using Jetpack with the [Likes](https://jetpack.com/support/likes/) feature enabled. The 2 flaws are respectively: - A DOM XSS vulnerability on https://widgets.wp.com/sharing-buttons-preview/ - The Jetpack plugin creates a postMessage listener allowing messages from the "widgets.wp.com" origin, but will not validate nor encode the `avatar_url` parameter before applying it to the DOM causing XSS. ## Reproduction: - Navigate to https://0-a.nl/jetpackxssclick.html?url=https://wordpress.com/blog/2024/01/31/http3/ and click the `PoC link`. ## Result In the newly opened window a `alert(document.domain)` will pop on https://wordpress.com {F3044196} ## Root causes ### XSS on widgets.wp.com The DOM XSS here is caused by the following included script: *https://widgets.wp.com/sharing-buttons-preview/js/preview.js* ```javascript if (_.isArray(r.custom)) { i = _.template(e("#tmpl-custom-button").html()); s = _.map(r.custom, function(e) { var t = g.parseUrl(e.icon); return new d({ ID: e.name, markup: i({ icon: o + "/" + t.host + t.pathname, name: e.name }) }) }); n = n.concat(s) } ``` It's not that obvious because of the minified javascript but what happens is that 2 url parameters are parsed and used to add a UI element to the DOM: ?custom[0][icon]=iconurl&custom[0][name]=name We can abuse the `name` parameter to create an XSS. https://widgets.wp.com/sharing-buttons-preview/?custom[0][icon]=iconurl&custom[0][name]=%22%3E%3Cimg%20src%20onerror=alert()%3E {F3044216} ### Insecure postMessage listener / codeblock When we navigate to a website that has the Jetpack Likes feature enabled, a postMessage listener will be launched that will execute the `JetpackLikesMessageListener` function when a message arrives. We can see it contains an origin check to only allow messages from widgets.wp.com. We can bypass this now since we have XSS on that domain: ```javascript const allowedOrigin = 'https://widgets.wp.com'; if ( allowedOrigin !== event.origin ) { return; } ``` When we follow the code to the `showOtherGravatars` case, you'll see it use a `liker.avatar_URL` parameter (that is received via a postMessage) directly with innerHTML. This will allow us to send a tampered postMessage causing the XSS to be triggered. ```javascript element.innerHTML = ` <a href="${ encodeURI( liker.profile_URL ) }" rel="nofollow" target="_parent" class="wpl-liker"> <img src="${ liker.avatar_URL }" alt="" style="width: 28px; height: 28px;" /> <span></span> </a> `; ``` ## Mitigation - Applying input validation and output encoding on the sharing-button page to mitigate the XSS https://widgets.wp.com/sharing-buttons-preview/ - Defence in depth: now any XSS on widgets.wp.com will lead to multiple XSSes all over the internet (anyone using the Jetpack Likes features). To mitigate this, I would also apply `encodeURI` to the avatar_url before using it in `innerHTML`. Upon further research it seemed older version of the plugin did exactly this, but in later versions this was removed. ## Impact XSS on a number of Automattic domains: https://0-a.nl/jetpackxssclick.html?url=https://wordpress.com/blog/2024/01/31/http3 https://0-a.nl/jetpackxssclick.html?url=https://jetpack.com/blog/wordpress-navigation-menu/ You probably have better insights in this (also I'd love to hear the actual number :) ) but searching publicwww.com revealed over 100k websites using this feature, meaning 100k domains vulnerable to this XSS. This is also the reason I picked `High` for severity. If it was just wordpress.com I would probably have gone for `Medium` which is more typical for these kind of XSSes without providing more impact specific to the vulnerable domain. But in this case the vulnerability reaches far beyond the 1 domain. In general, if an attacker can control a script that is executed in the victim's browser, then they can typically fully compromise that user. Amongst other things, the attacker can: * Perform any action within the application that the user can perform. * View any information that the user is able to view. * Modify any information that the user is able to modify.

Report Details

Additional information and metadata

State

Closed

Substate

Resolved

Submitted

Weakness

Cross-site Scripting (XSS) - DOM