Val Node.js aan deur JavaScript-objekprototipes te manipuleer

Navorsers by die Helmholtz-sentrum vir inligtingsekuriteit (CISPA) en die Royal Institute of Technology (Swede) het die toepaslikheid van die JavaScript-prototipe objekbesoedelingstegniek (“prototipe-besoedeling”) ontleed om aanvalle op die Node.js-platform en gewilde toepassings te skep wat gebaseer is op dit, wat lei tot kode-uitvoering.

Die prototipe besoedelingsmetode gebruik 'n kenmerk van die JavaScript-taal wat jou toelaat om nuwe eienskappe by die wortelprototipe van enige voorwerp te voeg. In toepassings kan daar kodeblokke (gadgets) wees waarvan die werk deur 'n vervangende eienskap geraak word, byvoorbeeld, in die kode kan daar 'n konstruksie soos 'const cmd = options.cmd || "/bin/sh"', waarvan die logika verander sal word as die aanvaller daarin slaag om die "cmd"-eienskap in die wortelprototipe te vervang.

'n Suksesvolle aanval vereis dat die toepassing insette van buite kan gebruik om 'n nuwe eienskap in die objek se wortelprototipe te skep, en dat 'n gadget wat afhanklik is van die veranderde eienskap tydens uitvoering teëgekom word. Die verandering van die prototipe word gedoen deur Node.js wat die "__proto__" en "constructor" nutseienskappe hanteer. Die "__proto__"-eienskap gee die objek se klas prototipe terug, en die "constructor"-eienskap gee die funksie terug wat gebruik is om die objek te skep.

As die toepassingskode die opdrag "obj[a][b] = waarde" teëkom en die waardes word vanaf eksterne data gestel, kan die aanvaller "a" op die waarde "__proto__" stel en die instelling van sy eiendom bereik met die naam "b" en die waarde "waarde" in die wortelprototipe van die voorwerp (obj.__proto__.b = waarde;), terwyl die eienskap wat in die prototipe gestel is in alle voorwerpe sigbaar sal wees. Net so, as daar uitdrukkings soos "obj[a][b][c] = waarde in die kode is", deur "a" op die waarde "konstruktor" en "b" na "prototipe" in alle bestaande voorwerpe te stel, jy kan 'n nuwe eiendom definieer met die naam "c" en die waarde "waarde".

'n Voorbeeld van die verandering van die prototipe: const o1 = {}; const o2 = nuwe Voorwerp(); o1.__proto__.x = 42; // skep die "x"-eienskap in die wortelprototipe console.log(o2.x); // verwys na die eienskap "x" van 'n ander voorwerp // ons kry 42 by die uitset, aangesien die wortelprototipe verander is deur die o1 voorwerp, wat ook in die o2 voorwerp gebruik word

Kwesbare kode voorbeeld: funksie entryPoint (arg1, arg2, arg3){ const obj = {}; const p = obj[arg1]; p[arg2] = arg3; terugkeer p; }

As die argumente van die entryPoint-funksie uit die invoerdata gevorm word, kan die aanvaller die waarde "__proto__" na arg1 deurgee en 'n eienskap met enige naam in die wortelprototipe skep. As jy die waarde "toString" na arg2 en 3 na arg1 deurgee, kan jy die "toString"-eienskap (Object.prototype.toString=1) definieer en veroorsaak dat die toepassing ineenstort wanneer die toString()-funksie geroep word.

As 'n voorbeeld van situasies wat kan lei tot die uitvoering van aanvallerkode, word die skepping van die "hoof", "dop", "uitvoer", "kontekstuitbreidings" en "env" eienskappe gegee. Byvoorbeeld, 'n aanvaller kan 'n "hoof"-eienskap in die objek se wortelprototipe skep, en die pad na sy skrif daarin skryf (Object.prototype.main = "./../../pwned.js") en hierdie eienskap sal opgeroep word ten tyde van uitvoering in die kode van die require("my-package") konstruk, as die ingeslote pakket nie eksplisiet die eienskap "main" in package.json definieer nie (as die eiendom nie gedefinieer is nie, sal dit verkry word vanaf die wortelprototipe). Net so kan die "shell", "exports" en "env" eienskappe vervang word: let rootProto = Object.prototype; rootProto["exports"] = {".":"./changelog.js"}; rootProto["1"] = "/pad/na/npm/skrifte/"; // sneller oproep vereis("./target.js"); Object.prototype.main = "/pad/na/npm/scripts/changelog.js"; Object.prototype.shell = "node"; object.prototype.env = {}; Object.prototype.env.NODE_OPTIONS = "--inspect-brk=0.0.0.0:1337"; // sneller oproep vereis ("grepe");

Die navorsers het die 10 1958 NPM-pakkette met die meeste afhanklikhede ontleed en gevind dat 4420 van hulle nie 'n hoofeienskap in package.json het nie, 355 gebruik relatiewe paaie in die vereiste stelling, en XNUMX gebruik die bevelvervangings-API direk.

'n Werkende voorbeeld is 'n uitbuiting om die Parse Server-agtergrond aan te val wat die evalFunctions-eienskap ignoreer. Om die identifisering van sulke kwesbaarhede te vereenvoudig, is 'n gereedskapstel ontwikkel wat metodes van statiese en dinamiese analise kombineer. Tydens die toetsing van Node.js is 11 toestelle geïdentifiseer wat gebruik kan word om aanvalle te organiseer wat lei tot die uitvoering van die aanvaller se kode. Benewens Parse Server, is twee ontginbare kwesbaarhede ook in die NPM CLI geïdentifiseer.

Bron: opennet.ru

Voeg 'n opmerking