To: eventListener # From: postMessage

In this post, we are going to see what is window.postMessage and how we can send data accross domains in a safe way.

WHAT IS POSTMESSAGE?

window,postMessage is a HTML5 API used to exchange data messages in a safe way across domains which allow us to enable a Cross-Domain communication also called Cross-origin.

This API can be used to send messages in the following ways:

  • From parent window to their frames or iframes
  • From parent window to child window (opened through window.open call)
  • From child window to parent window

In the other hand, the event listener receives the following attributes:

  • data: the incoming data message
  • origin: scheme, hostname and port from the sender
  • source: the source window

Following image represents a postmessage from parent window to iframe:

Following image represents a postmessage from parent window to child window and viceversa (child window must be opened with window.open):

INTRO

While looking for vulnerabilities in a Bug Bounty program, we identified a web page with a simple event listener which was not correctly validating neither data nor origin. Due to this, it was possible to exploit it with a crafted postMessage and execute javascript on browser. Let’s see it.

DEVTOOLS

Before continuing, let’s see quickly the browser’s development tools, in this case Chrome’s Devtools. We will use the following components:

  • Event Listeners Tab (number 1): shows all listeners for the web page
  • message option (number 2): shows the files related with event listeners
  • Console (number 3): needed to test postMessage and debugging

POSTMESSAGE RECON

When nagigating on the web, one of installed plugins advertised me about event listeners. So we opened Devtools and went to message option in Event Listeners tab in order to review the files:

Accessing to the source code, we observed that a new event listener was added to window, referencing the functionallity to the function ReceiveMessage:

In ReceiveMessage‘s body, it was being compared the event.data with some method names (number 1) and if event.data.match succeded, it would be passed to eval function (number 2):

As we could see, there was no origin validation to ensure only the allowed domains can send a postmessage and discard the rest ones. An example of origin’s validation would be:

To interact with event listener, we put a breakpoint in ReceiveMessage function and used the Console from Devtools. In there, we sent a postMessage through the call window.postMessage using as parameters “TEST” and “*”, corresponding to the data and the origin:

ReceiveMessage handler received the message with “TEST” as data (number 1) and the origin from which was sent (number 2). As “TEST” didn’t match with any method name (number 3) it got out from the function (number 4):

To get into the if, we needed a match. So, we sent the first method name in the if clause:

Going back to the Console, we sent a new postMessage with “LogRegHelper.LoginCallBackMethod” as data:


Once launched, the if clause in the ReceiveMessage function matched with the first ocurrence, logically:

As there was a match, the data got to the eval function:

EXPLOITATION

Ok but, if we could get to the eval function, what would happen if we send javascript code?. Would it be executed?. We appended the payload alert(‘Pwned’) to the method name LogRegHelper.LoginCallBackMethod so the call was as follows:

window.postMessage("LogRegHelper.LoginCallBackMethod;alert('Pwned');","*")

Once sent, the data would match because LoginCallbackMethod was found in LogRegHelper.LoginCallBackMethos;alert(‘Pwned’); and the payload got to the eval function:

In the website, a popup was shown with message Pwned:

As we could execute an alert(‘Pwned’); in the web page through postmessage, we created a file with the following content:

  • Open the website in a new child window through window.open (number 1)
  • Send a postmessage to the child window (number 2)

Once saved in our server, when the file was open by an user, postmessage was posted after some seconds and javascript code was executed, showing user’s cookies:

PLUGINS

There are some plugins that allow us to know if the web page declares event listeners. Following image is from MessPostage extension:

One of the most known plugins is postMessage-tracker from Frans Rosén, available in his github https://github.com/fransr/postMessage-tracker :

For trying postMessages, there is a web page very intuitive:

https://robertnyman.com/html5/postMessage/postMessage.html

I hope you enjoyed the article.

“Don’t give up. Great things take time”

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *