Prototype Pollution — Security

Refresh: Prototype Chain Di JavaScript, setiap object mewarisi property dari Object.prototype. Kalau kita membaca property yang tidak ada di object, JS mencari

Refresh: Prototype Chain

Di JavaScript, setiap object mewarisi property dari Object.prototype. Kalau kita membaca property yang tidak ada di object, JS mencari ke prototype-nya, lalu ke prototype dari prototype, dan seterusnya.

const obj = {};
console.log(obj.toString); // ada — diwariskan dari Object.prototype
obj.__proto__ === Object.prototype; // true

Apa itu Prototype Pollution?

Prototype pollution adalah serangan dimana attacker memodifikasi Object.prototype (atau prototype class tertentu), sehingga semua object di aplikasi terpengaruh. Vektor biasanya adalah fungsi deep-merge yang tidak hati-hati memproses key bernama __proto__, constructor, atau prototype.

BURUK: Deep Merge Vulnerable

function deepMerge(target, source) {
  for (const key in source) {
    if (typeof source[key] === "object") {
      target[key] = target[key] || {};
      deepMerge(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

// Attacker mengirim JSON:
const payload = JSON.parse('{"__proto__":{"isAdmin":true}}');
deepMerge({}, payload);

// Sekarang SEMUA object punya isAdmin === true
const newUser = {};
console.log(newUser.isAdmin); // true → auth bypass!

BAIK: Cek Key Berbahaya

function safeDeepMerge(target, source) {
  for (const key in source) {
    if (key === "__proto__" || key === "constructor" || key === "prototype") {
      continue; // skip key berbahaya
    }
    if (typeof source[key] === "object" && source[key] !== null) {
      target[key] = target[key] || Object.create(null);
      safeDeepMerge(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

Lebih Baik: Object.create(null)

// Object tanpa prototype — tidak bisa dicemari
const store = Object.create(null);
store.hello = "world";
console.log(store.__proto__); // undefined
console.log(store.toString);  // undefined — tidak ada warisan

Dampak Nyata

CVE Terkenal

Pencegahan

Deteksi di Code Review

// Red flag: deep merge tanpa key check
function merge(a, b) { /* ... source[key] ... */ }

// Red flag: Object.assign recursive tanpa filter
// Red flag: JSON.parse(userInput) langsung ke merge
// Red flag: pakai [] bracket notation dengan key dari user

Yang akan kamu pelajari