Útok na Node.js prostřednictvím manipulace s prototypy objektů JavaScript

Výzkumníci z Helmholtzova centra pro informační bezpečnost (CISPA) a Královského technologického institutu (Švédsko) analyzovali použitelnost techniky kontaminace objektů prototypu JavaScriptu („znečištění prototypu“) k vytvoření útoků na platformu Node.js a populární aplikace založené na to vede ke spuštění kódu.

Metoda znečišťování prototypu využívá funkci jazyka JavaScript, která umožňuje přidávat nové vlastnosti do kořenového prototypu libovolného objektu. V aplikacích mohou existovat bloky kódu (gadgety), jejichž práce je ovlivněna substituovanou vlastností, například v kódu může být konstrukce jako 'const cmd = options.cmd || "/bin/sh"', jehož logika se změní, pokud se útočníkovi podaří nahradit vlastnost "cmd" v kořenovém prototypu.

Úspěšný útok vyžaduje, aby aplikace byla schopna použít vstup zvenčí k vytvoření nové vlastnosti v kořenovém prototypu objektu a aby byl během provádění nalezen gadget, který závisí na změněné vlastnosti. Změnu prototypu provádí Node.js obsluhující vlastnosti utility "__proto__" a "constructor". Vlastnost "__proto__" vrací prototyp třídy objektu a vlastnost "konstruktor" vrací funkci použitou k vytvoření objektu.

Pokud kód aplikace narazí na přiřazení "obj[a][b] = hodnota" a hodnoty jsou nastaveny z externích dat, může útočník nastavit "a" na hodnotu "__proto__" a dosáhnout nastavení své vlastnosti pomocí jméno "b" a hodnotu "value" v kořenovém prototypu objektu (obj.__proto__.b = hodnota;), přičemž vlastnost nastavená v prototypu bude viditelná ve všech objektech. Podobně, pokud jsou v kódu výrazy jako "obj[a][b][c] = hodnota", nastavením "a" na hodnotu "konstruktor" a "b" na "prototyp" ve všech existujících objektech, můžete definovat novou vlastnost s názvem "c" a hodnotou "value".

Příklad změny prototypu: const o1 = {}; const o2 = new Object(); o1.__proto__.x = 42; // vytvořte vlastnost "x" v kořenovém prototypu console.log(o2.x); // odkazujeme na vlastnost "x" z jiného objektu // na výstupu dostaneme 42, protože kořenový prototyp byl změněn prostřednictvím objektu o1, který je také použit v objektu o2

Příklad zranitelného kódu: function entryPoint (arg1, arg2, arg3){ const obj = {}; const p = obj[arg1]; p[arg2] = arg3; vrátit p; }

Pokud jsou argumenty funkce entryPoint tvořeny ze vstupních dat, pak může útočník předat hodnotu "__proto__" arg1 a vytvořit vlastnost s libovolným názvem v kořenovém prototypu. Pokud předáte hodnotu "toString" do arg2 a 3 do arg1, můžete definovat vlastnost "toString" (Object.prototype.toString=1) a způsobit selhání aplikace při volání funkce toString().

Jako příklad situací, které mohou vést ke spuštění kódu útočníka, je uvedeno vytvoření vlastností „main“, „shell“, „exports“, „contextExtensions“ a „env“. Útočník může například vytvořit vlastnost "main" v kořenovém prototypu objektu a zapsat do něj cestu ke svému skriptu (Object.prototype.main = "./../../pwned.js") a tuto vlastnost bude volána v okamžiku spuštění v kódu konstruktu require("my-package"), pokud zahrnutý balíček explicitně nedefinuje vlastnost "main" v package.json (pokud vlastnost není definována, bude získat z kořenového prototypu). Podobně lze nahradit vlastnosti "shell", "exports" a "env": let rootProto = Object.prototype; rootProto["exports"] = {".":"./changelog.js"}; rootProto["1"] = "/cesta/k/npm/skripty/"; // trigger call required("./target.js"); Object.prototype.main = "/cesta/k/npm/scripts/changelog.js"; Object.prototype.shell = "uzel"; object.prototype.env = {}; Object.prototype.env.NODE_OPTIONS = "--inspect-brk=0.0.0.0:1337"; // spuštění volání require("bytes");

Výzkumníci analyzovali 10 1958 balíčků NPM s nejvíce závislostmi a zjistili, že 4420 z nich nemá hlavní vlastnost v package.json, 355 používá relativní cesty v příkazu require a XNUMX přímo používá API pro substituci příkazů.

Pracovním příkladem je exploit k útoku na backend Parse Server, který přepíše vlastnost evalFunctions. Pro zjednodušení identifikace takových zranitelností byla vyvinuta sada nástrojů, která kombinuje metody statické a dynamické analýzy. Během testování Node.js bylo identifikováno 11 gadgetů, které lze použít k organizaci útoků vedoucích ke spuštění kódu útočníka. Kromě Parse Server byly v NPM CLI také identifikovány dvě zneužitelné chyby zabezpečení.

Zdroj: opennet.ru

Přidat komentář