NodeJS - __proto__ & prototype Pollution
Oggetti in JavaScript
Gli oggetti in JavaScript sono essenzialmente collezioni di coppie chiave-valore, note come proprietà. Un oggetto può essere creato utilizzando Object.create
con null
come argomento per produrre un oggetto vuoto. Questo metodo consente la creazione di un oggetto senza proprietà ereditate.
Un oggetto vuoto è simile a un dizionario vuoto, rappresentato come {}
.
Funzioni e Classi in JavaScript
In JavaScript, le classi e le funzioni sono strettamente collegate, con le funzioni che spesso fungono da costruttori per le classi. Nonostante il supporto nativo alle classi manchi in JavaScript, i costruttori possono emulare il comportamento delle classi.
Prototipi in JavaScript
JavaScript consente la modifica, l'aggiunta o l'eliminazione degli attributi del prototipo durante l'esecuzione. Questa flessibilità consente l'estensione dinamica delle funzionalità della classe.
Funzioni come toString
e valueOf
possono essere modificate per cambiare il loro comportamento, dimostrando la natura adattabile del sistema di prototipi di JavaScript.
Ereditarietà
Nella programmazione basata su prototipi, le proprietà/metodi vengono ereditati dagli oggetti dalle classi. Queste classi vengono create aggiungendo proprietà/metodi o a un'istanza di un'altra classe o a un oggetto vuoto.
Va notato che quando una proprietà viene aggiunta a un oggetto che funge da prototipo per altri oggetti (come myPersonObj
), gli oggetti che ereditano ottengono accesso a questa nuova proprietà. Tuttavia, questa proprietà non viene visualizzata automaticamente a meno che non venga esplicitamente invocata.
Inquinamento di __proto__
Esplorare l'Inquinamento del Prototipo in JavaScript
Gli oggetti JavaScript sono definiti da coppie chiave-valore e ereditano dal prototipo dell'oggetto JavaScript. Ciò significa che modificare il prototipo dell'oggetto può influenzare tutti gli oggetti nell'ambiente.
Utilizziamo un esempio diverso per illustrare:
L'accesso al prototipo dell'oggetto è possibile tramite:
Aggiungendo proprietà al prototipo dell'oggetto, ogni oggetto JavaScript erediterà queste nuove proprietà:
inquinamento del prototipo
Per uno scenario in cui l'uso di __proto__
è limitato, modificare il prototipo di una funzione è un'alternativa:
Questo influisce solo sugli oggetti creati dal costruttore Vehicle
, conferendo loro le proprietà beep
, hasWheels
, honk
e isElectric
.
Due metodi per influenzare globalmente gli oggetti JavaScript attraverso l'inquinamento del prototipo includono:
Inquinare direttamente il
Object.prototype
:
Inquinamento del prototipo di un costruttore per una struttura comunemente utilizzata:
Dopo queste operazioni, ogni oggetto JavaScript può eseguire i metodi goodbye
e greet
.
Inquinamento di altri oggetti
Da una classe a Object.prototype
In uno scenario in cui puoi inquinare un oggetto specifico e hai bisogno di arrivare a Object.prototype
puoi cercarlo con un codice simile al seguente:
Inquinamento degli elementi dell'array
Si noti che poiché è possibile inquinare gli attributi degli oggetti in JS, se si ha accesso per inquinare un array è anche possibile inquinare i valori dell'array accessibili tramite gli indici (si noti che non è possibile sovrascrivere i valori, quindi è necessario inquinare gli indici che vengono in qualche modo utilizzati ma non scritti).
Inquinamento degli elementi Html
Quando si genera un elemento HTML tramite JS, è possibile sovrascrivere l'attributo innerHTML
per farlo scrivere codice HTML arbitrario. Idea ed esempio da questo articolo.
Esempi
Esempio di Base
Una contaminazione del prototipo avviene a causa di una falla nell'applicazione che consente di sovrascrivere le proprietà su Object.prototype
. Ciò significa che poiché la maggior parte degli oggetti deriva le loro proprietà da Object.prototype
L'esempio più semplice è aggiungere un valore a un attributo non definito di un oggetto che verrà verificato, come:
Se l'attributo admin
è non definito, è possibile sfruttare una PP e impostarlo su True con qualcosa del genere:
Il meccanismo di base coinvolge la manipolazione delle proprietà in modo tale che se un attaccante ha il controllo su determinati input, può modificare il prototipo di tutti gli oggetti nell'applicazione. Questa manipolazione di solito implica impostare la proprietà __proto__
, che, in JavaScript, è sinonimo di modificare direttamente il prototipo di un oggetto.
Le condizioni in cui questo attacco può essere eseguito con successo, come descritto in uno specifico studio, includono:
Eseguire una fusione ricorsiva.
Definire proprietà basate su un percorso.
Clonare oggetti.
Sovrascrittura della funzione
Inquinamento del prototipo per RCE
pagePrototype Pollution to RCEAltri payload:
Inquinamento del prototipo lato client per XSS
pageClient Side Prototype PollutionCVE-2019–11358: Attacco di inquinamento del prototipo tramite jQuery $ .extend
Per ulteriori dettagli consulta questo articolo In jQuery, la funzione $ .extend
può portare all'inquinamento del prototipo se la funzione di copia profonda viene utilizzata in modo improprio. Questa funzione è comunemente utilizzata per clonare oggetti o unire proprietà da un oggetto predefinito. Tuttavia, quando è configurata in modo errato, le proprietà destinate a un nuovo oggetto possono essere assegnate al prototipo invece che all'oggetto stesso. Ad esempio:
Questa vulnerabilità, identificata come CVE-2019-11358, illustra come una copia profonda possa modificare involontariamente il prototipo, portando a potenziali rischi per la sicurezza, come l'accesso amministrativo non autorizzato se proprietà come isAdmin
vengono verificate senza una corretta verifica dell'esistenza.
CVE-2018-3721, CVE-2019-10744: Attacco di inquinamento del prototipo tramite lodash
Per ulteriori dettagli consulta questo articolo
Lodash ha riscontrato vulnerabilità simili di inquinamento del prototipo (CVE-2018-3721, CVE-2019-10744). Queste problematiche sono state risolte nella versione 4.17.11.
Un altro tutorial con CVE
Strumenti per rilevare l'Inquinamento del Prototipo
Server-Side-Prototype-Pollution-Gadgets-Scanner: Estensione di Burp Suite progettata per rilevare e analizzare vulnerabilità di inquinamento del prototipo lato server in applicazioni web. Questo strumento automatizza il processo di scansione delle richieste per identificare potenziali problemi di inquinamento del prototipo. Sfrutta gadget noti - metodi per sfruttare l'inquinamento del prototipo per eseguire azioni dannose - concentrandosi in particolare sulle librerie Node.js.
server-side-prototype-pollution: Questa estensione identifica vulnerabilità di inquinamento del prototipo lato server. Utilizza tecniche descritte nel server side prototype pollution.
Inquinamento del Prototipo AST in NodeJS
NodeJS utilizza ampiamente gli Alberi di Sintassi Astratta (AST) in JavaScript per funzionalità come i motori di template e TypeScript. Questa sezione esplora le vulnerabilità legate all'inquinamento del prototipo nei motori di template, in particolare Handlebars e Pug.
Analisi della Vulnerabilità di Handlebars
Il motore di template Handlebars è suscettibile a un attacco di inquinamento del prototipo. Questa vulnerabilità deriva da funzioni specifiche all'interno del file javascript-compiler.js
. La funzione appendContent
, ad esempio, concatena pendingContent
se presente, mentre la funzione pushSource
reimposta pendingContent
su undefined
dopo aver aggiunto il codice sorgente.
Processo di Sfruttamento
Lo sfruttamento sfrutta l'AST (Albero di Sintassi Astratta) prodotto da Handlebars, seguendo questi passaggi:
Manipolazione del Parser: Inizialmente, il parser, tramite il nodo
NumberLiteral
, impone che i valori siano numerici. L'inquinamento del prototipo può aggirare questo, consentendo l'inserimento di stringhe non numeriche.Gestione da parte del Compilatore: Il compilatore può elaborare un oggetto AST o un modello di stringhe. Se
input.type
è uguale aProgram
, l'input viene trattato come pre-analizzato, il che può essere sfruttato.Iniezione di Codice: Attraverso la manipolazione di
Object.prototype
, è possibile iniettare codice arbitrario nella funzione del modello, il che potrebbe portare all'esecuzione remota di codice.
Un esempio che dimostra lo sfruttamento della vulnerabilità di Handlebars:
Questo codice mostra come un attaccante potrebbe iniettare del codice arbitrario in un template Handlebars.
Riferimento Esterno: È stata trovata una problematica legata all'inquinamento del prototipo nella libreria 'flat', come dettagliato qui: Problema su GitHub.
Riferimento Esterno: Problema legato all'inquinamento del prototipo nella libreria 'flat'
Esempio di exploit di inquinamento del prototipo in Python:
Vulnerabilità di Pug
Pug, un altro motore di template, affronta un rischio simile di inquinamento del prototipo. Informazioni dettagliate sono disponibili nella discussione su AST Injection in Pug.
Esempio di inquinamento del prototipo in Pug:
Misure Preventive
Per ridurre il rischio di inquinamento del prototipo, possono essere adottate le seguenti strategie:
Immutabilità dell'oggetto: Il
Object.prototype
può essere reso immutabile applicandoObject.freeze
.Validazione dell'Input: Gli input JSON dovrebbero essere rigorosamente validati rispetto allo schema dell'applicazione.
Funzioni di Unione Sicure: Evitare l'uso non sicuro di funzioni di unione ricorsive.
Oggetti Senza Prototipo: Gli oggetti senza proprietà del prototipo possono essere creati utilizzando
Object.create(null)
.Utilizzo di Mappe: Invece di
Object
, dovrebbe essere utilizzatoMap
per memorizzare coppie chiave-valore.Aggiornamenti delle Librerie: Le patch di sicurezza possono essere incorporate aggiornando regolarmente le librerie.
Linter e Strumenti di Analisi Statica: Utilizzare strumenti come ESLint con plugin appropriati per rilevare e prevenire vulnerabilità di inquinamento del prototipo.
Revisioni del Codice: Implementare revisioni del codice approfondite per identificare e risolvere i rischi potenziali legati all'inquinamento del prototipo.
Formazione sulla Sicurezza: Educare gli sviluppatori sui rischi dell'inquinamento del prototipo e sulle migliori pratiche per scrivere codice sicuro.
Utilizzo Cauteloso delle Librerie: Essere cauti nell'utilizzo delle librerie di terze parti. Valutare la loro postura sulla sicurezza e revisionare il loro codice, specialmente quelli che manipolano gli oggetti.
Protezione in Esecuzione: Utilizzare meccanismi di protezione in esecuzione come l'utilizzo di pacchetti npm orientati alla sicurezza che possono rilevare e prevenire attacchi di inquinamento del prototipo.
Riferimenti
Last updated