Saksamaa Helmholzi Tehnikaülikooli infoturbe keskuse (CISPA) ja Rootsi Kuningliku Tehnoloogiainstituudi teadlased analüüsisid prototüüpide saastamise tehnikate ("prototype pollution") rakendatavust rünnakute loomiseks Node.js platvormile ja selle põhjal loodud populaarsetele rakendustele, mis võivad viia koodikäivitamiseni.
Prototüüpide saastamise meetod kasutab JavaScripti keele omadust, mis võimaldab lisada uusi atribuute mis tahes objekti juureprototüüpi. Rakendustes võivad esineda koodiplokid (gadgetid), mille toimimist mõjutavad sisestatud atribuudid, näiteks koodis võib esineda konstruktsioon, nagu ‘const cmd = options.cmd || "/bin/sh"’, mille loogika muutub, kui ründaja suudab sisestada atribuudi „cmd” juureprototüüpi.
Rünnaku eduka teostamise jaoks on vajalik, et rakenduses saaks välised andmed kasutada uue atribuutide loomise jaoks juureprototüüpis, samuti peab olema olemas gadget, mis sõltub muudetud atribuudist. Prototüübi muutmine toimub Node.js-s teenuslike omaduste „__proto__” ja „constructor” töötlemise kaudu. Atribuut „__proto__” tagastab objekti klassi prototüübi, samas kui atribuut „constructor” tagastab objekti loomiseks kasutatava funktsiooni.
Kui rakenduse koodis esineb määramine „obj[a][b] = value” ning väärtusi määratakse väliseid andmeid kasutades, võib ründaja määrata „a” väärtuseks „__proto__” ja saavutada oma atribuudi seadmiseks nimega „b” ja väärtusega „value” juureprototüübis (obj.__proto__.b = value;), kusjuures prototüübis määratud atribuut on nähtav kõigis objektides. Samamoodi, kui koodis esinevad sellised väljendid nagu „obj[a][b][c] = value”, minnes „a” väärtusega „constructor” ja „b” väärtusega „prototype”, saab kõikides olemasolevates objektides määrata uue atribuudiga nimega „c” ja väärtusega „value”.
Prototüübi muutmise näide: const o1 = {}; const o2 = new Object(); o1.__proto__.x = 42; // loome juureprototüübi atribuudiga „x” console.log(o2.x); // pöördume teise objekti kaudu atribuudi „x” poole // tulemuseks on 42, kuna objekti o1 kaudu on muudetud juureprototüüpi, mida kasutatakse ka objekti o2 jaoks
Vulnertse koodi näide: function entryPoint (arg1, arg2, arg3){ const obj = {}; const p = obj[arg1]; p[arg2] = arg3; return p; }
Kui funktsiooni entryPoint argumendid on loodud sisseseadetest, saab ründaja edastada arg1-s väärtuse "__proto__" ja luua juureprototüüpidesse omaduse mis tahes nimega. Kui edastada arg2-s väärtus "toString" ja arg3-s 1, saab määrata omaduse "toString" (Object.prototype.toString=1) ja tekitada rakenduse krahhi funktsiooni toString() kutsumise ajal.
Näiteks on olukordi, mis võivad viia ründaja koodi täitmiseni, loodes omadusi "main", "shell", "exports", "contextExtensions" ja "env". Näiteks võib ründaja luua juureprototüüpi objekti omaduse "main", salvestades sinna oma skripti tee (Object.prototype.main = "./../..//pwned.js") ja see omadus kutsutakse välja, kui koodis kasutatakse konstruktsiooni require("my-package"), kui lisatav pakett ei määra package.json-is selgelt omadust "main" (kui omadust pole määratud, saadakse see juureprototüübist). Samamoodi võivad omadused "shell", "exports" ja "env" olla vaikimisi sisestatud: let rootProto = Object.prototype; rootProto["exports"] = {".":"./changelog.js"}; rootProto["1"] = "/path/to/npm/scripts/"; // käivita kõne 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"; // käivita kõne require ("bytes");
Uurijad analüüsisid 10 000 NPM-pakki, millel on kõige rohkem sõltuvusi, ning tuvastasid, et 1958 neist ei oma package.json-is omadust main, 4420 kasutavad relative teid require väljendis, ja 355 kasutavad otse API-d käskude sisestamiseks.
Töötava näitena võib tuua exploiti Parse Serveri tagaküljele rünnaku jaoks, mis üle määrab omaduse evalFunctions. Sarnaste haavatavuste tuvastamise lihtsustamiseks on välja töötatud tööriistakomplekt, mis ühendab staatilise ja dünaamilise analüüsi meetodeid. Node.js testimise käigus tuvastati 11 nurgakivi, mida saab kasutada rünnakute korraldamiseks, mis viivad ründaja koodi täitmiseni. Peale Parse Serveri leiti ka kaks ekspluateeritavat haavatavust NPM CLI-s.
Allikas: opennet.ru
