Támadás a Node.js-en keresztül a JavaScript objektumok prototípusainak manipulálásával.

A Helmholtz Center for Information Security (CISPA) and Royal Institute of Technology (Sweden) researchers analyzed the applicability of the prototype pollution technique in JavaScript to create attacks on the Node.js platform and popular applications based on it, leading to code execution.

The prototype pollution method leverages a feature of JavaScript that allows adding new properties to the root prototype of any object. Applications may include code blocks (gadgets) that are influenced by the injected property; for example, the code can contain a construct like ‘const cmd = options.cmd || "/bin/sh"’, the logic of which will change if an attacker manages to inject the property ‘cmd’ into the root prototype.

For a successful attack, it is required that external data can be used in the application to create a new property in the root prototype of the object, and that during execution there exists a gadget dependent on the modified property. The prototype modification is done through the handling of the Node.js internal properties ‘__proto__’ and ‘constructor’. The ‘__proto__’ property returns the prototype of the object's class, and the ‘constructor’ property returns the function used to create the object.

If the application code contains an assignment like ‘obj[a][b] = value’, and values are extracted from external data, the attacker can set ‘a’ to ‘__proto__’ and achieve the setting of their property named ‘b’ with value ‘value’ in the root prototype of the object (obj.__proto__.b = value;), making the property set in the prototype visible across all objects. Similarly, if the code contains expressions like ‘obj[a][b][c] = value’, by setting ‘a’ to ‘constructor’ and ‘b’ to ‘prototype’, a new property named ‘c’ with value ‘value’ can be defined across all existing objects.

Example of prototype modification: const o1 = {}; const o2 = new Object(); o1.__proto__.x = 42; // create a property 'x' in the root prototype console.log(o2.x); // access the property 'x' from another object // will output 42, since the root prototype used in object o2 was modified through object o1

Example of vulnerable code: function entryPoint(arg1, arg2, arg3){ const obj = {}; const p = obj[arg1]; p[arg2] = arg3; return p; }

Ha az entryPoint függvény argumentumai a bemeneti adatokból képződnek, a támadó átadhat egy "__proto__" értéket az arg1-nek, és bármilyen nevű tulajdonságot létrehozhat a gyökér prototípusban. Ha az arg2-be "toString" értéket, az arg3-ba pedig 1-et adunk, akkor definiálható a "toString" tulajdonság (Object.prototype.toString=1), ami a toString() függvény hívása során összeomláshoz vezethet.

Például olyan helyzeteket, amelyek támadó által végrehajtott kódhoz vezethetnek, az "main", "shell", "exports", "contextExtensions" és "env" tulajdonságok létrehozása illusztrál. Például a támadó létrehozhat egy "main" tulajdonságot a gyökér prototípusban, amelybe a saját scriptjeihez vezető útvonalat írja (Object.prototype.main = ".\/..\/..\/pwned.js"), és ezt a tulajdonságot felhívják, amikor a require("my-package") kódot futtatják, amennyiben a csomag kifejezetten nem határozza meg a package.json-ban a "main" tulajdonságot (ha a tulajdonság nem kerül meghatározásra, az a gyökér prototípusból lesz lekérdezve). Hasonlóképpen lecserélhetők a "shell", "exports" és "env" tulajdonságok: let rootProto = Object.prototype; rootProto["exports"] = {".":".\/changelog.js"}; rootProto["1"] = "\/path\/to\/npm\/scripts\/"; \/\/ kiváltás hívás 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"; \/\/ kiváltás hívás require ("bytes");

A kutatók 10 ezer NPM-csomagot elemeztek, amelyek a legtöbb függőséggel rendelkeznek, és megállapították, hogy 1958 közülük nem rendelkezik a package.json fájlban "main" tulajdonsággal, 4420 pedig relatív utakat használ a require kifejezésben, míg 355 közvetlenül az API-t használja parancsok behelyettesítésére.

Működő példaként említhetjük egy Parse Server backend támadási exploitját, amely felülírja az evalFunctions tulajdonságot. Az ilyen sebezhetőségek azonosításának egyszerűsítése érdekében olyan eszközkészletet fejlesztettek ki, amely a statikus és dinamikus elemzési módszereket kombinálja. A Node.js tesztelése során 11 olyan gadgetet azonosítottak, amelyeket a támadások megszervezésére lehet használni, amelyek támadó kód végrehajtásához vezetnek. A Parse Serveren kívül két kihasználható sebezhetőséget is azonosítottak az NPM CLI-ben.

Forrás: opennet.ru

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster