Understanding the PostMessage Vulnerabilities and its implications

PostMessages are widely used to send messages from one window to another. Over time, there have been many security implications in post messages as many modern applications use them, so it becomes a security risk if it is not implemented correctly.

This blog is targeted at the folks who want to deep dive into postMessage vulnerabilities but before reading this article, Knowledge of the Document object model (DOM) is necessary to understand this blog.

What you are Going to Learn From this Blog?

  • We are going to discuss a little bit about the Same Origin Policy.
  • What is a postMessage? Why is it used? Their syntax to define.
  • How to identify whether postMessage is being used or not?
  • We will discuss about postMessage() Vulnerabilities
  • We will discuss about one scenario for exploiting postMessage() Vulnerabilities.
  • Remediation

Same Origin Policy

Modern web browsers employ an important security mechanism known as the Same Origin Policy (SOP) that acts as a security boundary between web pages loaded from different origins

What are Origins here?

Origin is a portion of the URl consisting of a specific protocol(scheme), host, and port. Schemes are the HyperText Transfer Protocols (http:// & https://). The host is the website (www.example.com or example.com). The port is a number code at the end of the host (FTP 21 or WWW 80). When no port is specified, the browser defaults to port 80. The endpoints (ex./abcde ) are not part of the origin. If scheme, hostname or port anything get’s changed, then it will be considered as a different origin.

Origin-URI

  • Comparing the origin of different URL’s with https://example.com:8080/abcde

URL-comparison

Why we Need SOP ?

This is what Mozilla doc says about SOP.

The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. It is a critical security mechanism for isolating potentially malicious documents, reducing possible attack vectors.

It means that a server can restrict access to it’s data if the browser sends a request from a different origin than the server.

  • Scripts can only make HTTP requests and process responses between hosts that reside within the same origin.
  • Scripts can only read and write to frames that reside within the same origin.

But suppose there is one large integrated applications such as those offered by Google present a wide range of services, each shown via different URLs (e.g. webmail via https://mail.google.com and video sharing via https://youtube.com). Youtube.com cannot access cookies set via mail.google.com due to the Same Origin Policy. Because of these limitations, most sites use Cross-Origin Resource Sharing (CORS) to relax the SOP instead. CORS is a mechanism that protects the data of the server. It allows servers to explicitly specify a list of origins that are allowed to access its resources via the HTTP response header Access-Control-Allow-Origin

Introduction to postMessage()

Sometimes a web application needs to embed an iframe or open a new window, for example, a third party contact form on an application. Now when this happens, the origin of the parent and child windows is different. THE SAME ORIGIN Policy won’t allow them to communicate with each other, and this is where the JavaScript postmessage method comes into play.

parent-child-window

postMessage() sends data locally between the Window objects and does not generate an HTTP request to send data. It is used for DOM-based communication.

  • The method window.postMessage() is used by the application to allow cross-origin communication between different window objects, e.g. between a page and a pop-up that it spawned or between a page and an iframe embedded within it. This method provides a way to circumvent the Same Origin Policy restrictions securely.

window.postMessage() method – Sending Window

The method window.postMessage() is used by the application to allow cross-origin communication between different window objects, Since using postMessage() requires the sender to obtain a reference to the receiver’s window, messages can be sent only between a window and its iframes or pop-ups. That’s because only windows that open each other will have a way to reference each other. For example, a window can use window.open to refer to a new window it opened.

Alternatively, it can use window.opener to reference the window that spawned the current window. It can use window.frames to reference embedded iframes, and window.parent to reference the parent window of the current iframe. This method provides a way to circumvent the Same Origin Policy restrictions securely. You can use it to send text-based messages to another window.

Syntax:

targetWindow.postMessage(message, targetOrigin, [transfer]);
  1. targetWindow: A reference to the window that will receive the message. Methods for obtaining such a reference include: window.open, window.opener, window.parent, window.frames, etc.
  2. message : Data to be send to the other window.
  3. targetOrigin : The origin of the targetWindow that is supposed to receive the message. If the origin of targetWindow does not match with the targetOrigin specified here then message won’t be send at all. This adds a layer of security to the postMessage() functionality. The targetOrigin can also be specified by “*” which means that the targetWindow can have any origin. However, one needs to be pretty careful while using “*” with sensitive data being passed in the functionality.
  4. transfer(Optional): It is a sequence of Transferable objects that are transferred with the message.

window.addEventListener() method – Receiving Window

If a message is sent, there must be receiving window who handles the message by using an event handler that will be triggered when the receiving window receives a message.

Syntax:

window.addEventListener("message", function()=> {
  //Whatever you want to do with message data...
}, false/true);
  1. message : It is data that is sent from the source window to the targetWindow
  2. function : Describes the actions to be performed with the data received.
  3. false/true at the end is optional useCapture parameter that tells if the event should be executed in the capturing or in the bubbling phase (False by default).

Understanding the Flow of Sending and Receiving postMessage

For example, we want to pass the following JSON blob located at a.example.com/userinfo to b.example.com :

{'username': 'dn0m1n8tor', 'secret_ID': 'sRrsvRIMHSDBHeqAnhfdfnFB668LDR9Y'}

a.example.com can open b.example.com and send a message to its window. The window.open() function opens the window of a particular URL and returns a reference to it:

var recipient_window = window.open("https://b.example.com", b_domain)
recipient_window.postMessage("{'username': 'dn0m1n8tor', 'secret_ID': 'sRrsvRIMHSDBHeqAnhfdfnFB668LDR9Y'}", "*");

At the same time, b.example.com would set up an event listener to process the data it receives:

function parse_data(event) {
// Parse the data
}
window.addEventListener("message", parse_data);

As you can see, postMessage() does not bypass SOP directly but provides a way for pages of different origins to send data to each other.

Identifying the use of postMessage():

Detection of these vulnerabilities is not pretty straightforward. It requires knowledge and understanding of JavaScript to read the target application’s JavaScript to identify potential attack points. It is required to trace the execution flow to perform a successful attack.

To exploit the postMessage() vulnerabilities, first, it is required to know if the target application is using web messaging or not. If the target application uses web messaging, it is essential to identify the various listeners. There are several methods to do so, including:

  1. Searching for the keywords: Use the developer tool’s global search option to search for specific keywords such as postMessage(), addEventListener(“message, .on(“message” in the javascript files.
  2. Using MessPostage Browser Extension: Using this extension is an easy way to detect whenever an application usage postMessage() APIs. This also shows which messages were sent and where event listeners have been added.
  3. Using Developer Tools: The “Global Listener” feature present in the “Sources” pane of Developer tools can be used to identify the use of postMessage(). After opening the Global Listener, click on “messages” to view the message handlers.Dev-tools
  4. Using Posta: Posta is a tool for researching Cross-document Messaging communication. It allows you to track, explore and exploit postMessage vulnerabilities, and includes features such as replaying messages sent between windows within any attached browser.
  5. Using PMHook: PMHook is a client-side JavaScript library designed to be used with TamperMonkey in the Chrome web browser. Executed immediately at page load, PMHook wraps the EventTarget.addEventListener method and logs any subsequent message event handers as they are added. The event handler functions themselves are also wrapped to log messages received by each handler.source : Introduction to postMessage() Vulnerabilities

JavaScript postMessage() Vulnerabilities

If postMessage() is not implemented properly then it may lead to security vulnerabilities such as

  • Cross-Site Scripting (XSS) which we will discuss with example in this blog
  • Sensitive Data Exposure or information disclosure is another issue related to postMessage() in which sometimes PII-related information, leaked tokens or credentials such as API keys are leaked.
  • Due to weak implementation of regex, such as accepting the wildcards may also allow an attacker to perform exploits that are otherwise blocker due to certain domain/host-based restrictions.

Exploiting postMessage() using iframe

We will be looking at exploiting the postmessage() vulnerability in the following lab environment. Here is the lab link Vuln Nodejs App

Let’s understand the flow of application…

  1. You can see we have a change password functionality, and when we click on it, we get a child window asking for change password.
    change-password
  2. Fill the New password & Confirm password fields and click on Save.
    3.If you see we get here a message on parent window that Password update Successfull!Password-update-Successfull!
  3. Let’s sudo dig -in more in the flow…
    1. If you view the source code of Parent Window, you will see there is one addEventListener on the window object, which means that we are listening for the event message to be fired. message event fires whenever a window receives a message, which in this case will be through postMessage() method. Then we have define function to be executed whenever we receives a message which change the HTML content of an element with id="displayMessage"
      parent-window
    2. If you view the source code of Child Window
      You can see there are some XHR requests and responses code. When we enter our password in child window for updating, that request get performed and then server send 200 response code with some response text as Password update Successfull!
      child-window

      1. We pass this response to the sendMessage function.
      2. You can see in the sendMessage function definition that the child page can send a message to the parent. It identifies the parent through the window.opener and sends a message through postMessage(), which has two arguments
        1. text: The data which we want to send to the parent window which in this case is the Password update Successfull!
        2. * : The postMessage() method allows the sender to specify the receiver’s origin as a parameter. If the sender page doesn’t specify a target origin and uses a wildcard target origin instead, it becomes possible to leak information to other sites:
  4. Till now, you all have got the flow of code. So one thing to notice here is that the parent window is listening for event but not verifying from which origin the message is coming.
    • Vulnerable code
      Vulnerable-code
    • This is Secure code because here, we are verifying the origin of the sender by checking it against an acceptable origin.
      Secure-code
  5. Let’s take advantage of this vulnerable code and exploit the vulnerability. We have to write our own exploit exploit-code

Explanation of Code :

  1. We have created a submit button, and when someone clicks on it, an exploit function is called.
  2. We have loaded our lab website in an iframe.
  3. exploit() function
    1. First we have declared a variable payload which contains malicious JavaScript payload (line no. 7)
    2. The contentWindow property returns the Window object of an HTMLIFrameElement. You can use this Window object to access the iframe’s document and its internal DOM. This attribute is read-only, but its properties can be manipulated like the global Window object.(line no. 8)
    3. Then we are sending the payload to iframe through postmessage (line no. 9)

Exploit Code in Action

  • As you can see, our exploit is ready… So just click on exploit😈exploit-poc
  • Our xss get’s triggered 😎xss-triggered

Remediation:

  1. If the application does not require communication such as receiving messages from other websites, it is advised to not utilize the event listeners for the message events unnecessarily.
  2. Do not utilize a wildcard (*) target origin, instead use the expected target origin with the postMessage(). It will protect against the attack trying to use a malicious website to steal sensitive information.
  3. Always verify the sender’s identity using the origin.
  4. Setting appropriate X-Frame-Options and Content-Security-Policy headers will prevent the page from being loaded in an iframe.

Conclusion:

I hope you have learned how postMessages vulnerability occurs, how you can take advantage of it and remediate it.

References:

Subscribe to our Newsletter
Subscription Form
DOWNLOAD THE DATASHEET

Fill in your details and get your copy of the datasheet in few seconds

CTI Report
DOWNLOAD THE EBOOK

Fill in your details and get your copy of the ebook in your inbox

Ebook Download
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download ICS Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Cloud Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download IoT Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Code Review Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Red Team Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download AI/ML Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download DevSecOps Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Product Security Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Mobile Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Web App Sample Report

Let’s make cyberspace secure together!

Requirements

Connect Now Form

What our clients are saying!

Trusted by