flawopen.com/Kerentanan/Prototype pollution JavaScript
Prototype pollution JavaScript
Bayangkan bengkel tempat setiap perangkat baru memeriksa buku aturan bersama ketika pengaturannya sendiri tidak menjawab pertanyaan. Jika petugas menulis aturan yang dikendalikan penyerang ke buku itu, perangkat lain mungkin membacanya sebagai nilai bawaan. Dalam prototype pollution, penulisan properti dinamis yang tidak aman dapat mengubah prototipe objek, terkadang Object.prototype. Dampaknya tidak otomatis bersifat global; kode aplikasi harus kemudian memercayai properti yang diwariskan.
__proto__, atau jalur constructor.prototype yang mencapai penulisan tidak amanMap atau dictionary tanpa prototipe untuk key yang tidak tepercayaKonsep inti dan istilah subsistem
- Object.prototype
- Prototipe bersama yang diwarisi objek biasa. Pencemarannya dapat berdampak pada banyak objek, tetapi tidak pada semua objek JavaScript atau semua realm.
- __proto__
- Accessor lama pada objek biasa untuk mengambil atau mengatur prototipe. Dalam teks JSON, ejaan yang sama awalnya hanyalah nama properti biasa sampai kode berikutnya menanganinya secara tidak aman.
- Penggabungan mendalam rekursif
- Fungsi penyalin yang menelusuri key bertingkat dan menulisnya ke objek lain. Fungsi ini berbahaya jika key tidak tepercaya dapat memilih properti terkait prototipe atau jalur tidak aman.
- CWE-1321
- Perubahan atribut prototipe objek yang tidak dikendalikan dengan semestinya. Kelemahannya adalah mutasi yang tidak terkendali; dampak berikutnya bergantung pada perilaku aplikasi yang dapat dicapai.
Alur serangan langkah demi langkah
Input properti tidak tepercaya
Endpoint menerima key objek yang dikendalikan penyerang. Mem-parse JSON dengan properti own __proto__ saja tidak mengubah prototipe.
Penulisan dinamis tidak aman
Recursive merge atau setter jalur mengikuti key tersebut dan menulis secara dinamis tanpa memvalidasi setiap segmen jalur.
Perubahan prototipe target atau bersama
Bergantung pada target dan urutan penulisan, operasi mengubah prototipe target atau mencapai prototipe bersama seperti Object.prototype. Keduanya adalah hasil yang berbeda.
Dampak ditentukan oleh gadget
Gadget berikutnya membaca nilai warisan dalam operasi yang sensitif terhadap keamanan. Dampaknya bergantung pada gadget itu; jangan mengasumsikan bypass autentikasi atau eksekusi kode.
Mekanisme dan akar masalah
Pencarian properti JavaScript mengikuti rantai prototipe. Merge rentan atau setter jalur dapat membiarkan key tidak tepercaya seperti __proto__ atau constructor.prototype mengarahkan penulisan ke prototipe. Field own __proto__ yang dibuat oleh JSON.parse bukan pencemaran dengan sendirinya; kode berikutnya harus menafsirkannya lewat assignment yang tidak aman. Perubahan prototipe target berdampak pada target itu; perubahan Object.prototype berdampak pada objek biasa yang mewarisinya. Gadget terpisah harus menggunakan properti warisan agar timbul dampak keamanan.
// RENTAN: key yang dikendalikan penyerang mencapai penulisan rekursif
function merge(target, source) {
for (const key in source) {
const value = source[key];
if (value && typeof value === 'object') {
if (!target[key]) target[key] = {};
merge(target[key], value);
} else {
target[key] = value;
}
}
return target;
}
// JSON.parse membuat properti data own __proto__; merge yang tidak amanlah risikonya.
const input = JSON.parse('{"__proto__": {"isAdmin": true}}');
merge({}, input);
// DIPERKUAT: salin hanya field yang memang diterima endpoint ini
const PROFILE_KEYS = new Set(['displayName', 'theme']);
function parseProfile(input) {
if (!input || typeof input !== 'object' || Array.isArray(input)) {
throw new TypeError('profile must be an object');
}
const profile = Object.create(null);
for (const key of Object.keys(input)) {
if (!PROFILE_KEYS.has(key)) continue;
const value = input[key];
if (typeof value !== 'string' || value.length > 80) {
throw new TypeError('invalid profile field');
}
profile[key] = value;
}
return profile;
}
Urutan serangan dan eksploitasi
- 1Input: permintaan menyertakan key objek tak terduga seperti
{"__proto__": {"admin": true}}. Parsing JSON saja tidak mengubah prototipe. - 2Penulisan tidak aman: merge generik atau setter jalur memproses key tanpa allowlist.
- 3Jangkauan prototipe: penulisan dapat mengubah prototipe target atau mencapai prototipe bersama, bergantung pada jalur kode.
- 4Gadget dampak: pencemaran memengaruhi keputusan sensitif hanya jika kode berikutnya memercayai properti warisan. Uji gadget dan jalur otorisasi yang sebenarnya.
Rekayasa pertahanan dan aturan pencegahan
- ✓Utamakan allowlist schema: buat target hanya dari field yang memang diterima endpoint. Jika penulis jalur generik tidak dapat dihindari, tolak segmen jalur terkait prototipe pada setiap tingkat.
- ✓Gunakan dictionary aman: simpan key pengguna arbitrer dalam
Mapatau dictionaryObject.create(null); validasi sebelum memberikannya ke API yang mengharapkan objek biasa. - ✓Periksa properti own: gunakan
Object.hasOwn(record, key)untuk pemeriksaan sensitif; jangan biarkan nilai warisan mengotorisasi tindakan. - ✓Gunakan penguatan runtime sebagai pertahanan berlapis: Node.js
--disable-proto=throwmenghapus satu jalur tetapi tidak memblokirconstructor.prototype. Membekukan built-in dapat merusak polyfill dan dependensi; uji kompatibilitas dan jangan menggantikannya dengan penulisan aman.
Pertanyaan umum
Tidak. JSON.parse() membuat properti data milik sendiri bernama __proto__ dan tidak memanggil setter warisan. Risiko muncul jika merge atau assignment berikutnya memanggil setter tersebut. Lihat Apakah JSON.parse() menyebabkan Prototype Pollution?
Ini dapat mencegah penulisan ke Object.prototype yang dibekukan itu sendiri, tetapi tidak menghentikan setter mengubah prototipe satu objek atau melindungi semua prototipe lain. Ini juga dapat merusak pustaka yang memperluas built-in. Gunakan hanya sebagai defense-in-depth, bukan perbaikan pengolahan data.
Tidak. Tipe dihapus saat runtime. Nilai bertipe Record<string, string> masih dapat memiliki kunci __proto__; validasi kunci tak tepercaya dan buat objek dengan aman.
- MDN — prototype pollution JavaScript
- OWASP — Panduan pencegahan prototype pollution
- CWE-1321 — Perubahan atribut prototipe objek yang tidak dikendalikan dengan semestinya
- MDN — accessor Object.prototype.__proto__