Napad na Node.js putem manipulacije prototipovima JavaScript objekata

Istraživači Centra Helmholtz za informatičku sigurnost (CISPA) i Kraljevskog tehničkog instituta (Švedska) analizirali su primjenjivost tehnike zagađenja prototipa objekata JavaScript („prototype pollution“) za stvaranje napada na platformu Node.js i popularne aplikacije temeljen na njoj, što dovodi do izvršavanja koda.

Metoda zagađenja prototipa koristi karakteristiku jezika JavaScript koja omogućava dodavanje novih svojstava u korijenski prototip bilo kojeg objekta. U aplikacijama se mogu nalaziti dijelovi koda (gadgets) čije ponašanje ovisi o dodanom svojstvu, na primjer, u kodu može postojati konstrukcija poput ‘const cmd = options.cmd || “/bin/sh”’, čija će logika rada biti promijenjena ako napadač uspije dodati svojstvo „cmd“ u korijenski prototip.

Za uspješno provođenje napada potrebno je da aplikacija može koristiti podatke izvana za stvaranje novog svojstva u korijenskom prototipu objekta, kao i da tijekom izvršenja postoji gadget koji ovisi o promijenjenom svojstvu. Promjena prototipa vrši se zahvaljujući obradi u Node.js posebnih svojstava „__proto__” i „constructor”. S svojstvo „__proto__” vraća prototip klase objekta, dok svojstvo „constructor” vraća funkciju koja se koristi za stvaranje objekta.

Ako se u kodu aplikacije naiđe na dodjeljivanje „obj[a][b] = value“ i vrijednosti se postavljaju iz vanjskih podataka, napadač može postaviti „a“ na vrijednost „__proto__“ i postići postavljanje svog svojstva s imenom „b“ i vrijednošću „value“ u korijenskom prototipu objekta (obj.__proto__.b = value;), pri čemu će postavljeno svojstvo u prototipu biti vidljivo u svim objektima. Slično, ako se u kodu nalaze izrazi poput „obj[a][b][c] = value“, postavljanjem „a“ na vrijednost „constructor“ i „b“ na „prototype“ moguće je u svim postojećim objektima definirati novo svojstvo s imenom „c“ i vrijednošću „value“.

Primjer promjene prototipa: const o1 = {}; const o2 = new Object(); o1.__proto__.x = 42; // stvaramo u korijenskom prototipu svojstvo „x” console.log(o2.x); // pristupamo svojstvu „x” iz drugog objekta // na izlazu ćemo dobiti 42, jer je kroz objekt o1 promijenjen korijenski prototip, koji se također koristi u objektu o2.

Primjer ranjivog koda: function entryPoint (arg1, arg2, arg3){ const obj = {}; const p = obj[arg1]; p[arg2] = arg3; return p; }

Ako se argumenti funkcije entryPoint formiraju iz ulaznih podataka, napadač može poslati vrijednost "__proto__" u arg1 i stvoriti svojstvo s bilo kojim imenom u korijenskom prototipu. Ako se u arg2 pošalje vrijednost "toString", a u arg3 — 1, može se definirati svojstvo "toString" (Object.prototype.toString=1) i izazvati pad aplikacije prilikom poziva funkcije toString().

Kao primjer situacija koje mogu dovesti do izvršavanja koda napadača, navode se stvaranje svojstava "main", "shell", "exports", "contextExtensions" i "env". Na primjer, napadač može stvoriti svojstvo "main" u korijenskom prototipu objekta, upisavši put do svog skripte (Object.prototype.main = "./.../pwned.js") i ovo svojstvo će se pozvati prilikom izvršavanja koda konstrukcije require("my-package"), ako uključeni paket izričito ne definira svojstvo "main" u package.json (ako svojstvo nije definirano, ono će biti preuzeto iz korijenskog prototipa). Slično se mogu umetnuti svojstva "shell", "exports" i "env": let rootProto = Object.prototype; rootProto["exports"] = {".":"./changelog.js"}; rootProto["1"] = "/putanja/to/npm/scripts/"; // pokreni poziv require("./target.js"); Object.prototype.main = "/putanja/to/npm/scripts/changelog.js"; Object.prototype.shell = "node"; Object.prototype.env = {}; Object.prototype.env.NODE_OPTIONS = "--inspect-brk=0.0.0.0:1337"; // pokreni poziv require("bytes");

Istraživači su analizirali 10 tisuća NPM paketa s najvećim brojem ovisnosti i otkrili da 1958 od njih nema svojstvo main u package.json, 4420 koristi relativne putove u izrazu require, a 355 izravno koristi API za umetanje komandi.

Kao radni primjer može se navesti exploit za napad na backend Parse Server koji premješta svojstvo evalFunctions. Za olakšanu identifikaciju sličnih ranjivosti razvijen je alat koji kombinira metode statičke i dinamičke analize. Tijekom testiranja Node.js, otkriveno je 11 gadgeta koji se mogu koristiti za organiziranje napada koji dovode do izvršavanja koda napadača. Osim Parse Servera, dvije eksploatabilne ranjivosti također su otkrivene u NPM CLI.

Izvor: opennet.ru

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster