/FROM0TOPENTESTINGHERO

postMessage

In today’s episode, we’ll talk about postmessage - a functionality that allows you to exchange data between different domains.

Communication between domains

Suppose we are the owners of two different domains and we want them to communicate with each other using JavaScript. By default, sites can communicate with each other only if their host name, port number and protocol match - this is the mechanism called same-origin policy. We have several options to bypass it. One of them is postmessage. Let’s see the code of domain1.

domain1 source code

We listen to messages and if they occur, we display them using an alert. Now let’s look at the second domain. Here, we open the first one using the iframe and then after it has been loaded, we send the message to it using the postMessage function.

domain2 source code

Our message has been displayed - so everything works. So where is the vulnerability today? Let’s introduce the third domain, which does exactly the same as the second - that is, it sends a message to the first domain. This time, however, this is not our domain but the attacker’s domain. As you can see, this message has also been displayed.

domain3 source code

It happened because we did not include any security mechanism - our first site receives and displays messages from everyone. This can have different consequences - it depends on what the website does with the received data. Depending on the case, there may be an XSS attack - when we send a dangerous HTML code that is displayed by the website without any verification. Sometimes we can steal cookies or publish an entry in the account of a logged-in user without his knowledge.

In the worst possible scenario - if the site would treat the message as a JavaScript code - we could do anything on the website.

Well, but how to protect against it? We must check the origin in the function that handles incoming messages - in other words - from where the given message came to us. The browser automatically sends this information along with the content of the message.

Origin header

Source: https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent

But you can also make mistakes here. Suppose we used a regular expression to check if the domain that sent the message belongs to us. Can you spot a mistake?

Regular expressions

In regular expressions, a dot means exactly one occurence of any character. For the dot to be treated as a dot, it must be preceded by a backslash. Such check will therefore work in the domain www.domain2.local but also in wwwxdomena2.local, where the dot is replaced with the x character.

Regular expressions

Another incorrect form may be to use the indexOf function - to check if our domain is included anywhere in the origin.

indexOf function

This protection mechanism can be bypassed by creating a subdomain that will start with a given prefix, like www.domain2.local.whatever.local. This domain does not belong to us but to the attacker - because it is the domain whatever.local, with subdomain www.domain2.local. However indexOf checks if the given string occurs anywhere.