Skip to main content

52. Prototype Pollution: JavaScript's Hidden Vulnerability

Prototype Pollution is an attack technique that changes an application's overall behavior by polluting JavaScript's prototype chain. The name may be unfamiliar, but it appears fairly often in real-world CTFs and bug bounty programs.

How It Works

In JavaScript, every object references a parent prototype through __proto__.

const obj = {};
obj.__proto__.isAdmin = true;

const newObj = {};
console.log(newObj.isAdmin); // true ← polluted

Modifying obj.__proto__ changes Object.prototype itself, affecting every object created afterward.

Attack Scenarios

1. Authorization Bypass

// Server code (Express)
if (req.user.isAdmin) { ... }

// Attack payload (JSON merge vulnerability)
{ "__proto__": { "isAdmin": true } }

Deep-merge functions such as lodash.merge and jquery.extend are common entry points.

2. Escalating to RCE

In a Node.js environment, injecting child_process-related options into the prototype can lead to Remote Code Execution.

// When a particular library reads execution options from the prototype
{ "__proto__": { "shell": "bash", "env": { "NODE_OPTIONS": "--inspect=0.0.0.0" } } }

Detection & Defense

Detection:

  • Periodically check Object.prototype for unexpected properties
  • Filter __proto__ and constructor keys after JSON.parse

Defense:

  • Object.create(null) — Use plain objects without a prototype
  • Object.freeze(Object.prototype) — Freeze the prototype
  • Never deep-merge untrusted input

CTF Tips

When facing a Prototype Pollution challenge, try both the __proto__ and constructor.prototype paths. Checking the library version and known CVEs is also essential.

lodash < 4.17.19, jquery < 3.4.0 — Notable vulnerable versions

The appeal of Prototype Pollution is how one small object can shake an entire application. 🥞