Introduction to postMessage() Vulnerabilities

August 25, 2021

Each month, YesWeHack publishes articles on exploitation techniques, tools and tips to help hunters find vulnerabilities in their reconnaissance process and hunting routine. The goal is to provide ideas and keys to attack and understand the various web technologies hunters may face on their private programs.

The increased research in application security allows researchers to identify various security loopholes and attacks, sometimes, totally new and sometimes, upgrading the attack potential of existing techniques or features and turning them into interesting attack vectors.

In this blog, we will discuss postMessage(), what it is about, why it is used, and the security risks while using postMessage() along with some exploitation techniques.

Introduction to postMessage()

The method window.postMessage() is used by the application to allow cross-origin communication between different window objects. This method provides a way to securely circumvent the restrictions of the Same Origin Policy.

Syntax:

targetWindow.postMessage(message, targetOrigin, [transfer]); 

window.postMessage() Components

  • targetWindow
  • message
  • targetOrigin
  • transfer

More detailed information on the window.postMessage() specification can be found at: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

For example: If an application wants to communicate between its webpage and an iframe embedded within it, window.postMessage() can be used for the same. The window.postMessage() method safely enables cross-origin communication between Window objects.

postMessage() Vulnerabilities

It is essential to ensure that the postMessage() is implemented properly, if not, it may lead to security vulnerabilities such as Cross-Site Scripting (XSS), Sensitive Data Exposure, Information Theft, and others.

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.

Identifying the use of PostMessage():

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.
  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.

Dom Based XSS using Insecure postMessage():

HTML5 postMessage introduces a new taint source in the form of the message payload (Event.data). A DOM-based Cross-Site Scripting (XSS) vulnerability occurs when the payload of a message event is handled in an unsafe way. The table below lists some of the most common functions and attributes that can lead to an XSS vulnerability.

Source: https://docs.ioin.in/writeup/www.exploit-db.com/_docs_40287_pdf/index.pdf

Impact of postMessage() Exploitation

  1. Insecure implementation of postMessage() can lead to multiple attack scenarios and one of the widely exploited scenarios is to perform a postMessage() based Cross-Site Scripting as discussed in one of the above sections.
  2. Sensitive Data Exposure or Information Disclosure is another impact of the postMessage() related issues. This information sometimes may include PII related information, sensitive tokens or credentials such as API Keys.
  3. Additionally, 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()

In this article, we will be looking at exploiting the postMessage() vulnerability in the following lab environment:

Lab: https://github.com/shurmajee/postmessage-vulnerability-demo

Note: Please ensure to make changes in the host entries/code to work properly in the lab. For this demonstration, we have changed all the hostname in the code to “127.0.0.1” and started a server on port 8090.

Exploitation Steps

  1. Navigate to the following URL: http://127.0.0.1:8090/demo/rewards.html and click on Play.

2. Observe that the application sends a message using postMessage() to another window that is hosted on http://127.0.0.1:8090/demo/start.html

3. Now, navigate to http://127.0.0.1:8090/demo/evilrewards.html. This page is controlled by an attacker attempting to send a malicious payload, cross-site scripting payload in this case, to the child window located at start.html

4. Click on Play and hit on OK.

5. Observe that the malicious payload sent by the attacker is successfully executed on the child window.

Explanation of Attack Execution:

According to the source code of the lab, it can be observed that the rewards.html will perform a postMessage() event to start.html. This happens when the user clicks on Play which envokes the pop1() function performing the communication using the postMessage() function.

Since the pop-up window always assumes that the message will be received by the specified domain, for example, 127.0.0.1. The code also doesn’t validate the sender’s origin.

Due to a lack of validation, the message can be sent from any origin. An attacker can leverage this to send malicious messages to the pop-up window using an attacker-controlled domain. As observed in the code evilrewards.html, the attacker has cloned a similar code as rewards.html, adding a malicious JavaScript payload as the message.

When the attacker clicks on the Play button, it invokes the pop2() function, which will launch the communication using the postMessage() function that sends a malicious payload to the pop-up window resulting in the execution of a Cross-Site Scripting attack.

Remediations

  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.

Further References & End Notes

References:

This article covers the basics of postMessage(), some common vulnerabilities, identification and exploitation that will allow you to understand and start hunting similar vulnerabilities. In future, we may come up with an advance guide to postMessage() attacks. Thank you for reading!