AI Hacking - Come gli hacker usano l'intelligenza artificiale nei cyberattacchi

Leggi ora
Per le traduzioni dei siti utilizziamo l'intelligenza artificiale e, sebbene ci sforziamo di essere accurati, non sempre le traduzioni sono precise al 100%. La vostra comprensione è apprezzata.

Scoperta tecnica di Mongoose CVE-2025-23061 e CVE-2024-53900

da OPSWAT
Condividi questo post

Mongoose è una libreria Object Data Modeling (ODM) per MongoDB che semplifica le interazioni con i database nelle applicazioni Node.js. Fornendo una soluzione basata su schemi, Mongoose consente di mappare gli oggetti JavaScript in documenti MongoDB, agendo come un livello di astrazione che aiuta a strutturare i dati per una più facile gestione e validazione. Grazie a funzioni come il middleware per l'esecuzione di logica personalizzata e un sistema intuitivo di creazione di query, Mongoose migliora l'efficienza del lavoro con MongoDB. Mongoose, descritto come "elegante modellazione di oggetti MongoDB per Node.js", ha ottenuto 27.000 stelle su GitHub, a testimonianza del suo ampio utilizzo e apprezzamento da parte degli sviluppatori.

Programma di borse di studio OPSWAT e scoperta di vulnerabilità critiche

Il programmaOPSWAT Critical Infrastructure Cybersecurity Graduate Fellowship Program, con sede in Vietnam, offre agli studenti laureati un'esperienza pratica nella sicurezza delle infrastrutture critiche. Nell'ambito di questo programma, i borsisti hanno l'opportunità di analizzare e affrontare le vulnerabilità della sicurezza informatica, collaborando con gli esperti OPSWAT per affrontare le sfide del mondo reale in aree come il rilevamento di malware, la sicurezza dei file e la prevenzione delle minacce. 

Durante il programma OPSWAT Fellowship, i partecipanti indagano e riproducono sistematicamente le CVE conosciute su vari prodotti, librerie e sistemi operativi. Nell'ambito di questa iniziativa, Dat Phung - uno dei nostri illustri borsisti - ha scelto di esaminare Mongoose a causa della sua diffusa adozione in ambienti di produzione. Nel novembre 2024, durante un'analisi approfondita della libreria, ha scoperto una vulnerabilità critica in Mongoose. La vulnerabilità consentiva a un aggressore di sfruttare il valore $where, portando potenzialmente all'esecuzione di codice remoto (RCE) sul server dell'applicazione Node.js. Dopo aver prontamente segnalato il problema a Mongoose, è stata rilasciata una patch come parte della versione 8.8.3 e la CVE-2024-53900 è stata resa nota nel National Vulnerability Database (NVD).

CVE-2024-53900 e CVE-2025-23061 Cronologia

  • 7 novembre 2024: Dat Phung ha identificato una vulnerabilità critica in Mongoose e ha inviato un rapporto di sicurezza a Snyk. 
  • 26 novembre 2024: Mongoose ha rilasciato la versione 8.8.3 per risolvere questa vulnerabilità. 
  • 2 dicembre 2024: Il National Vulnerability Database (NVD) ha reso nota la CVE-2024-53900 per questa vulnerabilità. 
  • 17 dicembre 2024: Analizzando la patch 8.8.3 di Mongoose, Dat Phung ha trovato un bypass che permetteva ancora di eseguire RCE (Remote Code Execution). Un rapporto di sicurezza dettagliato è stato inviato a Tidelift. 
  • 13 gennaio 2025: Mongoose rilascia la versione 8.9.5, introducendo una patch migliorata che risolve efficacemente il bypass. 
  • 15 gennaio 2025: Il National Vulnerability Database (NVD) ha divulgato ufficialmente CVE-2025-23061, sottolineando la gravità della vulnerabilità appena identificata.

Il metodo Populate() di Mongoose

Mongoose fornisce anche un'utile funzione chiamata populate() che migliora la capacità di lavorare con le relazioni tra documenti. Mentre le versioni di MongoDB ≥ 3.2 hanno l'operatore di aggregazione $lookup per i join, populate() di Mongoose offre un'alternativa più potente per sostituire automaticamente un riferimento con i dati corrispondenti di documenti correlati. Ciò è particolarmente utile per gestire le relazioni tra diverse raccolte di MongoDB, come quando un documento fa riferimento a un altro tramite il suo _id. [2] 

Codice JavaScript che definisce uno schema Mongoose per un autore con i campi nome, età e bio.
Schema Autori
Codice JavaScript che definisce uno schema Mongoose per i libri, compresi titolo, descrizione, prezzo e riferimenti all'autore.
Schema dei libri
Frammento di codice JavaScript per una rotta Node.js che recupera i dettagli del libro e popola i campi dell'autore o delle recensioni
Applicazione Nodejs

Quando si definisce uno schema in Mongoose, un campo può essere impostato per fare riferimento a un altro modello usando l'opzione ref. Il metodo populate() viene quindi utilizzato per sostituire il campo di riferimento (un ObjectId) con il documento completo del modello correlato. Ad esempio, in un'applicazione di libreria, il campo autore nel bookSchema fa riferimento al documento Autore e il campo recensione fa riferimento al documento Recensioni. Il metodo populate() consente agli sviluppatori di sostituire il campo autore (che è un ObjectId) con l'intero documento Author quando si interroga il modello del libro.

Il populate() consente agli sviluppatori di sostituire il campo autore (che è un ObjectId) con il documento autore completo quando si interroga il modello del libro:

Rappresentazione JSON di un documento MongoDB che memorizza i dettagli del libro senza informazioni estese sull'autore
Non utilizzare populate()
Rappresentazione JSON di un documento MongoDB con i dettagli dell'autore espansi utilizzando la funzione popolate
Utilizzo di populate()

Inoltre, il metodo populate() di Mongoose supporta query personalizzate per definire quali documenti correlati vengono recuperati e come vengono recuperati. Proprietà come match e options consentono agli sviluppatori di filtrare, ordinare, limitare e saltare i documenti correlati, offrendo funzionalità flessibili di recupero dei dati.

Codice JavaScript che dimostra una query personalizzata che utilizza la funzione populate di Mongoose per filtrare gli autori in base all'età
Query personalizzata in populate() in Mongoose

Analisi CVE-2024-53900

Nell'ambito del programma OPSWAT Cybersecurity Graduate Fellowship, mentre analizzava Mongoose per riprodurre le CVE conosciute, Dat Phung ha condotto una revisione completa del funzionamento interno del metodo populate(), che svolge un ruolo chiave nella gestione delle relazioni tra i documenti MongoDB. Il metodo populate() supporta argomenti sia di tipo stringa che di tipo oggetto e gli sviluppatori possono utilizzare l'opzione match per applicare filtri specifici ai dati recuperati:

Codice JavaScript che mostra l'uso dell'operatore $where per filtrare gli autori in base all'età in una query

Nell'esempio precedente, l'opzione match è un oggetto filtro che può includere gli operatori di query di MongoDB, come illustrato nel manuale Query and Projection Operators - MongoDB Manual v8.0. Un operatore degno di nota è $where, che consente l'esecuzione di JavaScript direttamente sul server MongoDB. Tuttavia, l'esecuzione sul server MongoDB è limitata e supporta solo operazioni e funzioni di base.

Tabella che elenca le funzioni e le proprietà JavaScript disponibili per le operazioni di map-reduce di MongoDB

Dat Phung ha condotto un'analisi approfondita del codice sorgente di Mongoose per comprendere il flusso di lavoro del metodo populate(). Ha determinato che dopo che l'applicazione chiama il metodo populate() sul modello, viene attivata la funzione populate(). All'interno di questa funzione, Mongoose chiama la funzione _execPopulateQuery() , che esegue la query con l'operatore $where sul server MongoDB. Successivamente, tutti i documenti della collezione straniera vengono recuperati per essere popolati nei passi successivi.

Schermata di una sessione di debug di VS Code che analizza l'esecuzione di una query Mongoose populate

Dopo aver recuperato i dati da MongoDB, Mongoose esegue la funzione di callback _done(), che chiama _assign() per preparare i dati prima di "unire" i due modelli chiamando la funzione assignVals().

Una sessione di debug in VS Code che mostra il codice JavaScript evidenziato relativo alla query $where in Mongoose

La vulnerabilità può verificarsi quando i dati recuperati vengono elaborati dalla funzione assignVals() di Mongoose. Questa funzione controlla se l'opzione match è un array e, in caso affermativo, passa ogni operatore alla funzione sift(). La funzione sift() , importata da una libreria esterna con lo stesso nome, elabora queste query localmente sul server dell'applicazione. Questa elaborazione locale presenta un rischio per la sicurezza, soprattutto quando si tratta di input controllati dall'utente.

Una sessione di debug di VS Code che mostra le assegnazioni di variabili all'interno di una funzione JavaScript

Per approfondire questo aspetto, Dat Phung ha modificato i valori dell'opzione match per garantire che le condizioni fossero soddisfatte, invocando così la funzione sift() per un'ulteriore analisi del flusso di dati.

Uno snippet di codice JavaScript che dimostra una query Mongoose con una condizione di filtro $where

Con la condizione in atto, l'operatore $where è stato successivamente passato alla funzione sift().

Una sessione di debug di VS Code che mostra i valori filtrati in una funzione JavaScript

La libreria sift è una leggera utility JavaScript progettata per filtrare e interrogare collezioni di dati come array o oggetti JSON utilizzando una sintassi simile a quella di MongoDB. Secondo la documentazione ufficiale, "Sift è una piccola libreria per utilizzare le query MongoDB in JavaScript". La funzione sift() valuta le operazioni di filtro simili a MongoDB sul server dell'applicazione invece che sul server del database, il che può esporre il sistema a rischi significativi per la sicurezza quando si elaborano input non attendibili.

Un semplice snippet JavaScript che utilizza Sift.js per filtrare un array di oggetti in base a criteri di età
Un esempio di codice Sift

Continuando la sua analisi, il nostro collega ha identificato un problema nella funzione createDefaultQueryTester() della libreria sift. Questa funzione converte ogni operazione dell'array match in funzioni JavaScript eseguibili, che vengono poi utilizzate per filtrare ed elaborare localmente i dati dei documenti MongoDB. A tale scopo, createDefaultQueryTester() richiama la funzione createNamedOperation(), passando come argomenti operazioni come $where dall'array di corrispondenze. 

Una sessione di debug di VS Code incentrata sulle operazioni di query e sull'esecuzione di funzioni.

Per ogni operazione nell'array match, createNamedOperation verifica se l'operazione è supportata e la passa alla funzione corrispondente.

Una sessione di debug di JavaScript che mostra operatori di query come $where, $eq e $exists

Se l'operazione è $where, viene generata una funzione JavaScript usando il valore grezzo "params", che deriva dall'operatore $where nell'array match e può essere controllato dall'utente.

Uno snippet JavaScript evidenziato che dimostra l'esecuzione della funzione quando CSP (Content Security Policy) è abilitato

CVE-2024-53900: Dettagli dell'exploit

Mentre MongoDB limita l'esecuzione di funzioni JavaScript tramite l'operazione $where, come analizzato in precedenza, la funzione sift() consente l'esecuzione di tali funzioni senza tali restrizioni. Questa mancanza di validazione e restrizione dell'input introduce una significativa vulnerabilità di sicurezza, in quanto il valore "params", controllato direttamente dall'input dell'utente, può essere sfruttato, portando potenzialmente ad attacchi di iniezione di codice. Per esaminare più a fondo questo problema, Dat Phung ha costruito la seguente query:

Uno snippet JavaScript che mostra una query Mongoose che utilizza la condizione $where con un'esecuzione di funzione potenzialmente non sicura

Inizialmente, la query non è riuscita a eseguire un altro processo, generando il seguente errore:

Un registro degli errori di MongoDB che mostra un fallimento dell'esecuzione del server a causa di un riferimento globale non definito

Questo errore indica che Mongoose tenta di eseguire l'operazione $where sul server MongoDB prima di passare il controllo alla funzione sift(). Tuttavia, a causa delle restrizioni sulle funzioni JavaScript nella clausola $where di MongoDB, si verifica un errore che impedisce l'esecuzione della query. Di conseguenza, Mongoose arresta il processo prima di raggiungere la funzione sift() .

Per aggirare la limitazione, il nostro collega ha sfruttato la variabile "global" presente sull'application server, che non esiste sul server MongoDB. Questo approccio gli ha permesso di aggirare la restrizione sul server MongoDB e di consentire alla query di raggiungere la funzione sift():

Il monitor di un computer mostra il testo "il codice non funziona", evidenziando un problema nel processo di codifica.

Con questo valore, quando Mongoose esegue l'operazione $where su MongoDB, l'assenza della variabile "global" fa sì che l'operatore ternario (typeof global != "undefined" ?global.process.mainModule.constructor._load("child_process").exec("calc") : 1) per restituire 1, evitando che MongoDB lanci un errore. Di conseguenza, la query viene eseguita sul server MongoDB senza problemi.

Tuttavia, quando lo stesso valore raggiunge la funzione sift(), che viene eseguita sul server dell'applicazione in cui è disponibile la variabile "globale", si attiva la creazione della funzione seguente:

Una schermata monocromatica con la frase "hello world" in grassetto

Prova di concetto dell'esecuzione di codice remoto (RCE)

Nell'esempio di applicazione fornito all'inizio del blog, se un aggressore inviasse la seguente richiesta, potrebbe eseguire con successo un attacco di tipo Remote Code Execution (RCE):

Schermo in bianco e nero che visualizza il testo "the new york times" in grassetto
Diagramma che illustra i dettagli tecnici delle vulnerabilità CVE di Mongoose, mostrando il flusso di dati e i punti di violazione della sicurezza

Il video mostra il Proof of Concept per la CVE-2024-53900 che interessa le versioni di Mongoose precedenti alla 8.8.3, che mancano di un'adeguata convalida dell'input per prevenire l'uso improprio dell'operatore $where insieme alla libreria sift.

Correzione incompleta e CVE-2025-23061

Sulla base del rapporto di sicurezza di Dat Phung, Mongoose ha introdotto una patch per risolvere la vulnerabilità precedentemente identificata (CVE-2024-53900) prima della sua divulgazione pubblica. La patch in questione(Automattic/mongoose@33679bc) ha aggiunto un controllo per impedire l'uso di $where all'interno della proprietà match passata a populate().

Questo frammento controlla se la proprietà match passata in populate() è un array. Se lo è, il codice itera ogni oggetto dell'array per vedere se contiene l'operatore $where. Se viene rilevato $where, viene sollevato un errore, impedendo al payload dannoso di propagarsi alla rischiosa funzione sift().  

Di conseguenza, il payload che sfrutta la CVE-2024-53900 non supera questo controllo perché un oggetto nell'array match contiene $where, impedendogli di fatto di raggiungere sift().

Mentre questo aggiornamento blocca correttamente l'uso diretto di $where all'interno di un singolo livello di annidamento, non riesce a rilevare $where quando è incorporato all'interno di un operatore $or, una struttura che sia MongoDB che la libreria sift supportano pienamente.

MongoDB supporta l'operatore $o
La libreria Sift supporta l'operatore $or

Di conseguenza, un aggressore può annidare $where sotto $o per eludere il controllo a livello singolo della patch. Poiché Mongoose ispeziona solo le proprietà di primo livello di ogni oggetto nell'array di corrispondenza, il payload di aggiramento non viene rilevato e alla fine raggiunge la libreria sift, consentendo l'RCE dannoso.

Payload utilizzato per aggirare la correzione in mangusta 8.8.3

Prova di concetto per CVE-2025-23061

Per illustrare la natura incompleta della correzione, Dat Phung ha ricostruito l'applicazione di esempio utilizzando una versione di Mongoose 8.9.4 (successiva alla 8.8.3). Annidando $whereall'interno di una clausola $or, un utente malintenzionato può aggirare il controllo e ottenere un RCE.

L'exploit proof-of-concept dimostra come la CVE-2025-23061 possa essere attivata nelle versioni di Mongoose precedenti alla 8.9.5, consentendo a un utente malintenzionato di eseguire codice arbitrario sul server:

Mitigazione e guida

Per ridurre le vulnerabilità discusse sopra, assicuratevi che il vostro sistema sia aggiornato all'ultima versione di Mongoose.

MetaDefender Core che utilizza il motore SBOM è in grado di rilevare questa vulnerabilità

OPSWAT MetaDefender Core, dotato di funzionalità avanzate di SBOMSoftware Bill of Materials), consente alle aziende di adottare un approccio proattivo nell'affrontare i rischi per la sicurezza. Esaminando le applicazioni software e le loro dipendenze, MetaDefender Core identifica le vulnerabilità note, come CVE-2024-53900 e CVE-2025-23061, all'interno dei componenti elencati. In questo modo i team di sviluppo e di sicurezza sono in grado di dare priorità alle attività di patch, mitigando i potenziali rischi per la sicurezza prima che possano essere sfruttati da attori malintenzionati. 

Di seguito è riportata una schermata di CVE-2024-53900 e CVE-2025-23061, rilevate da MetaDefender Core con SBOM:

Inoltre, i CVE possono essere rilevati anche da MetaDefender Software Supply Chainche sfrutta MetaDefender Core con SBOM per identificare queste vulnerabilità.

Rimanete aggiornati con OPSWAT!

Iscriviti oggi stesso per ricevere gli ultimi aggiornamenti sull'azienda, storie, informazioni sugli eventi e altro ancora.