Istraživači Helmholtz centra za informatičku sigurnost (CISPA) i Kraljevskog tehnološkog instituta (Švedska) analizirali su primenljivost tehnike zagađenja prototipa objekata JavaScript („prototype pollution“) za izvođenje napada na platformu Node.js i popularne aplikacije bazirane na njoj, što dovodi do izvršavanja koda.
Metod zagađenja prototipa koristi osobinu jezika JavaScript koja omogućava dodavanje novih svojstava u korenski prototip bilo kog objekta. U aplikacijama se mogu pojaviti blokovi koda (gedžeti) koji su pogođeni ustupljenim svojstvom, na primer, u kodu može postojati konstrukcija poput ‘const cmd = options.cmd || „/bin/sh“‘, čija će logika delovanja biti promenjena ako napadač uspe da ustupi svojstvo „cmd“ u korenskom prototipu.
Za uspešno izvršenje napada potrebno je da podaci dobijeni izvana mogu da se koriste za kreiranje novog svojstva u korenskom prototipu objekta, a takođe da tokom izvođenja postoji gedžet koji zavisi od izmenjenog svojstva. Izmena prototipa se vrši zahvaljujući obradi u Node.js službenih svojstava „__proto__“ i „constructor“. Svojstvo „__proto__“ vraća prototip klase objekta, dok svojstvo „constructor“ vraća funkciju koja se koristi za kreiranje objekta.
Ako se u kodu aplikacije susreće dodeljivanje „obj[a][b] = value“ i vrednosti se ustupaju iz spoljašnjih podataka, napadač može postaviti „a“ na vrednost „__proto__“ i ostvariti postavljanje svog svojstva sa imenom „b“ i vrednošću „value“ u korenskom prototipu objekta (obj.__proto__.b = value;), pri čemu će postavljeno svojstvo u prototipu biti vidljivo u svim objektima. Slično tome, ako se u kodu pojavljuju izrazi poput „obj[a][b][c] = value“, postavljanjem „a“ na vrednost „constructor“, a „b“ na „prototype“ može se u svim postojećim objektima definisati novo svojstvo sa imenom „c“ i vrednošću „value.“
Primer izmena prototipa: const o1 = {}; const o2 = new Object(); o1.__proto__.x = 42; // kreiramo u korenskom prototipu svojstvo „x“ console.log(o2.x); // obraćamo se svojstvu „x“ iz drugog objekta // na izlazu dobijamo 42, jer je kroz objekat o1 izmenjen korenski prototip, koji koristi i objekat o2
Primer ranljivega kode: function entryPoint (arg1, arg2, arg3){ const obj = {}; const p = obj[arg1]; p[arg2] = arg3; return p; }
Če so argumenti funkcije entryPoint oblikovani iz vhodnih podatkov, lahko napadalec prenese v arg1 vrednost „__proto__“ in ustvari v korenskem prototipu lastnost z katerim koli imenom. Če prenesemo v arg2 vrednost „toString“, ter v arg3 — 1, lahko določimo lastnost „toString“ (Object.prototype.toString=1) in povzročimo zlom aplikacije med klicem funkcije toString().
Kot primer situacij, ki lahko vodijo do izvedbe napadalčevega kode, so navedene lastnosti „main“, „shell“, „exports“, „contextExtensions“ in „env“. Na primer, napadalec lahko ustvari v korenskem prototipu objekta lastnost „main“, tako da v njej zapiše pot do svojega skripta (Object.prototype.main = „.\/..\/..\/pwned.js“) in ta lastnost bo klicana ob izvajanju kode konstrukcije require(„my-package“), če vključeni paket jasno ne določa v package.json lastnosti „main“ (če lastnost ni določena, bo pridobljena iz korenskega prototipa). Podobno se lahko podstavijo lastnosti „shell“, „exports“ in „env“: let rootProto = Object.prototype; rootProto[„exports“] = {„.“:„.\/changelog.js“}; rootProto[„1“] = „\/path\/to\/npm\/scripts\/“; \/\/ sproži klic require („.\/target.js“); Object.prototype.main = „\/path\/to\/npm\/scripts\/changelog.js“; Object.prototype.shell = „node“; Object.prototype.env = {}; Object.prototype.env.NODE_OPTIONS = „—inspect-brk=0.0.0.0:1337“; \/\/ sproži klic require („bytes“);
Raziskovalci so analizirali 10 tisoč NPM paketov z največjim številom odvisnosti in odkrili, da 1958 od teh nima lastnosti main v package.json, 4420 uporablja relativne poti v izrazu require, in 355 neposredno uporablja API za podstavitev ukazov.
Kot delujoč primer lahko navedemo exploit za napad na backend Parse Server, ki prepisuje lastnost evalFunctions. Za poenostavitev odkrivanja takšnih ranljivosti je bil razvit nabor orodij, ki kombinira metode statične in dinamične analize. Med testiranjem Node.js je bilo odkritih 11 gadgetov, ki jih je mogoče uporabiti za organizacijo napadov, ki vodijo do izvajanja napadalčeve kode. Poleg Parse Serverja so bile odkrivene tudi dve izkoriščeni ranljivosti v NPM CLI.
Izvor: opennet.ru
