Angreb på Node.js gennem manipulering af JavaScript-objektprototyper

Forskere ved Helmholtz Center for Informationssikkerhed (CISPA) og Royal Institute of Technology (Sverige) analyserede anvendeligheden af ​​JavaScript-prototype-objektkontamineringsteknikken ("prototype pollution") til at skabe angreb på Node.js-platformen og populære applikationer baseret på det, hvilket fører til kodeudførelse.

Prototypeforureningsmetoden bruger en funktion i JavaScript-sproget, der giver dig mulighed for at tilføje nye egenskaber til rodprototypen af ​​ethvert objekt. I applikationer kan der være kodeblokke (gadgets), hvis arbejde er påvirket af en substitueret egenskab, for eksempel kan der i koden være en konstruktion som 'const cmd = options.cmd || "/bin/sh"', hvis logik vil blive ændret, hvis angriberen formår at erstatte "cmd"-egenskaben i rodprototypen.

Et vellykket angreb kræver, at applikationen kan bruge input udefra til at skabe en ny egenskab i objektets rodprototype, og at en gadget, der afhænger af den ændrede egenskab, stødes på under udførelsen. Ændring af prototypen udføres af Node.js, der håndterer egenskaberne "__proto__" og "constructor". Egenskaben "__proto__" returnerer objektets klasseprototype, og egenskaben "constructor" returnerer den funktion, der blev brugt til at oprette objektet.

Hvis applikationskoden støder på tildelingen "obj[a][b] = værdi" og værdierne er sat fra eksterne data, kan angriberen indstille "a" til værdien "__proto__" og opnå indstillingen af ​​sin egenskab med navnet "b" og værdien "værdi" i objektets rodprototype (obj.__proto__.b = værdi;), mens egenskaben sat i prototypen vil være synlig i alle objekter. Tilsvarende, hvis der i koden er udtryk som "obj[a][b][c] = værdi", ved at sætte "a" til værdien "konstruktør" og "b" til "prototype" i alle eksisterende objekter, du kan definere en ny egenskab med navnet "c" og værdien "værdi".

Et eksempel på ændring af prototypen: const o1 = {}; const o2 = nyt objekt(); o1.__proto__.x = 42; // opret egenskaben "x" i rodprototypen console.log(o2.x); // referer til egenskaben "x" fra et andet objekt // vi får 42 ved udgangen, da rodprototypen blev ændret gennem o1-objektet, som også bruges i o2-objektet

Eksempel på sårbar kode: function entryPoint (arg1, arg2, arg3){ const obj = {}; const p = obj[arg1]; p[arg2] = arg3; returnere p; }

Hvis argumenterne for entryPoint-funktionen er dannet ud fra inputdataene, kan angriberen videregive værdien "__proto__" til arg1 og oprette en egenskab med et hvilket som helst navn i rodprototypen. Hvis du sender værdien "toString" til arg2 og 3 til arg1, kan du definere egenskaben "toString" (Object.prototype.toString=1) og få applikationen til at gå ned, når funktionen toString() kaldes.

Som et eksempel på situationer, der kan føre til udførelse af angriberkode, er oprettelsen af ​​egenskaberne "main", "shell", "exports", "contextExtensions" og "env". For eksempel kan en angriber oprette en "main" egenskab i rodprototypen af ​​et objekt ved at skrive stien til sit script (Object.prototype.main = "./../../pwned.js") ind i det, og denne egenskab vil blive kaldt på tidspunktet for udførelse i koden for require("min-pakke")-konstruktionen, hvis den inkluderede pakke ikke eksplicit definerer egenskaben "main" i package.json (hvis egenskaben ikke er defineret) , vil den blive hentet fra rodprototypen). På samme måde kan egenskaberne "shell", "exports" og "env" erstattes: let rootProto = Object.prototype; rootProto["exports"] = {".":"./changelog.js"}; rootProto["1"] = "/sti/til/npm/scripts/"; // trigger call require("./target.js"); Object.prototype.main = "/sti/to/npm/scripts/changelog.js"; Object.prototype.shell = "node"; object.prototype.env = {}; Object.prototype.env.NODE_OPTIONS = "--inspect-brk=0.0.0.0:1337"; // trigger call require("bytes");

Forskerne analyserede de 10 NPM-pakker med flest afhængigheder og fandt ud af, at 1958 af dem ikke har en hovedegenskab i package.json, 4420 bruger relative stier i require-sætningen, og 355 bruger direkte kommandoerstatnings-API'en.

Et fungerende eksempel er en udnyttelse til at angribe Parse Server-backend, der tilsidesætter egenskaben evalFunctions. For at forenkle identifikationen af ​​sådanne sårbarheder er der udviklet et værktøjssæt, der kombinerer metoder til statisk og dynamisk analyse. Under testen af ​​Node.js blev der identificeret 11 gadgets, der kan bruges til at organisere angreb, der fører til eksekvering af angriberens kode. Ud over Parse Server er der også identificeret to sårbarheder, der kan udnyttes i NPM CLI.

Kilde: opennet.ru

Tilføj en kommentar