Sulmi ndaj Node.js përmes manipulimit të prototipëve të objekteve JavaScript

Kërkuesit e Qendrës Helmholtz për Sigurinë e Informacionit (CISPA) dhe Institutit Mbretëror të Teknologjisë (Suedi) analizuan aplikueshmërinë e teknikës së ndotjes së prototipit të objekteve JavaScript («prototype pollution») për të krijuar sulme mbi platformën Node.js dhe aplikacionet e njohura që bazohen në të, të cilat çojnë në ekzekutimin e kodit.

Metoda e ndotjes sĂ« prototipit shfrytĂ«zon njĂ« veçori tĂ« gjuhĂ«s JavaScript qĂ« lejon shtimin e pronarive tĂ« reja nĂ« prototipin rrĂ«njĂ«sor tĂ« çdo objekti. NĂ« aplikacione mund tĂ« shfaqen blloqe kode (gadgets) qĂ« ndikohen nga prona e vendosur; pĂ«r shembull, nĂ« kod mund tĂ« ketĂ« njĂ« strukturĂ« si ‘const cmd = options.cmd || «/bin/sh»‘, logjika e sĂ« cilĂ«s do tĂ« ndryshonte nĂ«se sulmuesi arrin tĂ« vendosĂ« pronĂ«n «cmd» nĂ« prototipin rrĂ«njor.

Për të realizuar me sukses një sulm, është e nevojshme që në aplikacion të dhënat që vijnë nga jashtë të mund të përdoren për të krijuar një pronë të re në prototipin rrënjësor të objektit, si dhe që gjatë ekzekutimit të ketë një gadget që varet nga prona e ndryshuar. Ndryshimi i prototipit bëhet përmes përpunimit në Node.js të pronave të veçanta "__proto__" dhe "constructor". Prona "__proto__" kthen prototipin e klasës së objektit, ndërsa prona "constructor" kthen funksionin e përdorur për të krijuar objektin.

Nëse në kodin e aplikacionit haset asignimi "obj[a][b] = value" dhe vlerat vendosen nga të dhëna të jashtme, sulmuesi mund ta vendosë "a" në vlerën "__proto__" dhe të arrijë vendosjen e pronës së tij me emrin "b" dhe vlerën "value" në prototipin rrënjësor të objektit (obj.__proto__.b = value;), ndërsa pronë e vendosur në prototip do të jetë e dukshme në të gjithë objektet. Po ashtu, nëse në kod hasen shprehje si "obj[a][b][c] = value", duke vendosur "a" në vlerën "constructor" dhe "b" në "prototype", në të gjitha objektet e ekzistuese mund të përcaktohet një pronë e re me emrin "c" dhe vlerën "value".

Shembulli i ndryshimit të prototipit: const o1 = {}; const o2 = new Object(); o1.__proto__.x = 42; // krijojmë një pronë "x" në prototipin rrënor console.log(o2.x); // qasemi në pronën "x" nga objekti tjetër // rezultati do jetë 42, sepse përmes objektit o1 u ndryshua prototipi rrënor, i përdorur gjithashtu dhe në objektin o2

Shembulli i kodit të cenueshëm: function entryPoint(arg1, arg2, arg3) { const obj = {}; const p = obj[arg1]; p[arg2] = arg3; return p; }

NĂ«se argumentet e funksionit entryPoint formohen nga tĂ« dhĂ«na hyrĂ«se, atĂ«herĂ« sulmuesi mund tĂ« dĂ«rgojĂ« nĂ« arg1 vlerĂ«n "__proto__" dhe tĂ« krijojĂ« nĂ« prototipin rrĂ«nor njĂ« pronĂ« me çdo emĂ«r. NĂ«se dĂ«rgohet nĂ« arg2 vlera "toString", dhe nĂ« arg3 — 1, mund tĂ« pĂ«rcaktohet prona "toString" (Object.prototype.toString=1) dhe tĂ« shkaktohet njĂ« dĂ«shtim i aplikacionit gjatĂ« thirrjes sĂ« funksionit toString().

Si njĂ« shembull i situatave qĂ« mund tĂ« çojnĂ« nĂ« ekzekutimin e kodit tĂ« sulmuesit, pĂ«rmendet krijimi i pronave "main", "shell", "exports" dhe "contextExtensions" si dhe "env". PĂ«r shembull, sulmuesi mund tĂ« krijojĂ« nĂ« prototipin rrĂ«nor tĂ« objektit njĂ« pronĂ« "main", duke shkruar nĂ« tĂ« rrugĂ«n e skenarit tĂ« tij (Object.prototype.main = ".\/..\/..\/pwned.js") dhe kjo pronĂ« do tĂ« thirret nĂ« momentin e ekzekutimit nĂ« kodin e konstruktit require ("my-package"), nĂ«se paketa e lidhur nuk pĂ«rcakton qartĂ« nĂ« package.json pronĂ«n "main" (nĂ«se prona nuk Ă«shtĂ« e pĂ«rcaktuar, ajo do tĂ« merret nga prototipi rrĂ«nor). Po ashtu, pronat "shell", "exports" dhe "env" mund tĂ« vendosen: let rootProto = Object.prototype; rootProto["exports"] = {".":".\/changelog.js"}; rootProto["1"] = "\/path\/to\/npm\/scripts\/"; \/\/ thirrje aktive 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"; \/\/ thirrje aktive require ("bytes");

Kërkuesit analizuan 10 mijë paketa NPM, të cilat kanë numrin më të madh të varësive, dhe zbuluan se 1958 prej tyre nuk kanë pronën main në package.json, 4420 përdorin rrugë relative në shprehjen require, dhe 355 përdorin drejtpërdrejt API për të vendosur komandat.

Si një shembull funksional, mund të përmendim një exploit për sulm ndaj backend-it të Parse Server, i cili mbi shpron son evalFunctions. Për të lehtësuar identifikimin e këtij lloji të dobësive, është zhvilluar një paketë mjetesh që kombinon metoda të analizës statike dhe dinamike. Gjatë testimit të Node.js janë identifikuar 11 gadgete që mund të përdoren për të organizuar sulme që çojnë në ekzekutimin e kodit nga sulmuesi. Përveç Parse Server, dy dobësi të tjera ishin identifikuar gjithashtu në NPM CLI.

Burimi: opennet.ru

Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster