Menyerang Node.js melalui manipulasi prototipe objek JavaScript

Para peneliti dari Pusat Keamanan Informasi Helmholtz (CISPA) dan Royal Institute of Technology (Swedia) menganalisis penerapan teknik polusi prototipe JavaScript untuk menciptakan serangan pada platform Node.js dan aplikasi populer berdasarkan platform tersebut, yang mengarah pada eksekusi kode.

Metode pencemaran prototipe menggunakan fitur bahasa JavaScript yang memungkinkan Anda menambahkan properti baru ke prototipe akar objek apa pun. Aplikasi mungkin berisi blok kode (gadget) yang pengoperasiannya dipengaruhi oleh properti pengganti; misalnya, kode mungkin berisi konstruksi seperti 'const cmd = options.cmd || "/bin/sh"', yang logikanya akan berubah jika penyerang berhasil mengganti properti “cmd” di prototipe root.

Serangan yang berhasil mengharuskan aplikasi dapat menggunakan data eksternal untuk membuat properti baru di prototipe akar objek, dan eksekusi tersebut akan menemui gadget yang bergantung pada properti yang dimodifikasi. Mengubah prototipe dilakukan dengan memproses properti layanan “__proto__” dan “konstruktor” di Node.js. Properti "__proto__" mengembalikan prototipe kelas objek, dan properti "konstruktor" mengembalikan fungsi yang digunakan untuk membuat objek.

Jika kode aplikasi berisi penugasan “obj[a][b] = value” dan nilainya ditetapkan dari data eksternal, penyerang dapat menyetel “a” ke nilai “__proto__” dan mencapai instalasi propertinya sendiri dengan nama “b” dan nilai “value” pada prototipe root objek (obj.__proto__.b = value;), dan kumpulan properti dalam prototipe akan terlihat di semua objek. Demikian pula, jika kode berisi ekspresi seperti “obj[a][b][c] = value”, dengan menyetel “a” ke nilai “konstruktor”, dan “b” ke “prototipe” di semua objek yang ada, Anda bisa tentukan properti baru dengan nama "c" dan nilai "value".

Contoh perubahan prototype: const o1 = {}; const o2 = Objek baru(); o1.__proto__.x = 42; // buat properti “x” di prototipe root console.log (o2.x); // mengakses properti “x” dari objek lain // outputnya akan menjadi 42, karena prototipe root diubah melalui objek o1, ​​yang juga digunakan dalam objek o2

Contoh kode yang rentan: function entryPoint (arg1, arg2, arg3){ const obj = {}; const p = obj[arg1]; p[arg2] = arg3; kembali p; }

Jika argumen fungsi entryPoint dibentuk dari data masukan, maka penyerang dapat meneruskan nilai “__proto__” ke arg1 dan membuat properti dengan nama apa pun di prototipe root. Jika Anda memberikan arg2 nilai "toString" dan arg3 nilai 1, Anda dapat mendefinisikan properti "toString" (Object.prototype.toString=1) dan membuat aplikasi crash selama panggilan ke toString().

Contoh situasi yang dapat menyebabkan eksekusi kode penyerang mencakup pembuatan properti "main", "shell", "exports", "contextExtensions" dan "env". Misalnya, penyerang dapat membuat properti "utama" di prototipe akar suatu objek, menulis di dalamnya jalur ke skripnya (Object.prototype.main = "./../../pwned.js") dan properti ini akan dipanggil pada saat eksekusi dalam kode konstruk require("paket saya"), jika paket yang disertakan tidak secara eksplisit mendefinisikan properti "utama" di package.json (jika properti tidak ditentukan, itu akan diperoleh dari prototipe root). Properti “shell”, “exports” dan “env” dapat diganti dengan cara yang sama: let rootProto = Object.prototype; rootProto["ekspor"] = {".":"./changelog.js"}; rootProto["1"] = "/path/ke/npm/scripts/"; // pemicu panggilan require("./target.js"); Objek.prototipe.main = "/path/to/npm/scripts/changelog.js"; Objek.prototipe.shell = "simpul"; Objek.prototipe.env = {}; Objek.prototipe.env.NODE_OPTIONS = "—inspect-brk=0.0.0.0:1337"; // pemicu panggilan require("byte");

Para peneliti menganalisis 10 paket NPM dengan jumlah dependensi terbesar dan menemukan bahwa 1958 di antaranya tidak memiliki properti utama di package.json, 4420 menggunakan jalur relatif dalam pernyataan persyaratannya, dan 355 langsung menggunakan API substitusi perintah.

Contoh yang berfungsi adalah eksploitasi untuk menyerang backend Parse Server yang mengambil alih properti evalFunctions. Untuk menyederhanakan identifikasi kerentanan tersebut, sebuah toolkit telah dikembangkan yang menggabungkan metode analisis statis dan dinamis. Selama pengujian Node.js, diidentifikasi 11 gadget yang dapat digunakan untuk mengatur serangan yang mengarah pada eksekusi kode penyerang. Selain Parse Server, dua kerentanan yang dapat dieksploitasi juga diidentifikasi di NPM CLI.

Sumber: opennet.ru

Tambah komentar