Diventa Autore per CoreTech | Scopri di più
02/07/20 CoreTech Blog
Una vulnerabilità legata all'iniezione NoSQL è un errore in un'applicazione Web che utilizza un database NoSQL. Questo problema di sicurezza delle applicazioni Web consente a una parte malintenzionata di ignorare l'autenticazione, estrarre dati, modificare i dati o persino ottenere il controllo completo sull'applicazione. Gli attacchi di iniezione NoSQL sono il risultato di una mancanza di sanificazione dei dati.
Le iniezioni di NoSQL sono solo uno dei tanti attacchi di iniezione , simili alle tradizionali iniezioni di SQL . Sono progettati per sfruttare database moderni che non utilizzano SQL. Il termine NoSQL (non solo SQL) viene utilizzato per descrivere database che utilizzano una struttura meno rigida e possono fare riferimento a molti tipi diversi di database, inclusi quelli che utilizzano modelli come valore-chiave, documento-chiave, famiglia di colonne o grafico.
Mentre i motori di database NoSQL hanno una struttura diversa e non supportano istruzioni SQL e query SQL, consentono comunque agli utenti di eseguire query. Non supportano un linguaggio standardizzato e pertanto il linguaggio delle query dipende dall'implementazione: database (ad es. MongoDB, Redis, Google Cloud Datastore, ecc.), Linguaggio (ad es. Python, PHP, ecc.) E framework (ad es. Nodo. js, angolare). Tuttavia, le query NoSQL si basano spesso su JSON e possono includere input dell'utente. Se questo input non è disinfettato, sono vulnerabili alle iniezioni.
Per capire come è costruita una query NoSQL e come è vulnerabile a un attacco di iniezione, ci concentreremo sul database NoSQL più popolare: MongoDB e accederemo ad esso tramite PHP. Ecco un semplice esempio di frammento di codice che accede a MongoDB a fini di autenticazione.
$username = $_POST['username'];
$password = $_POST['password'];
$connection = new MongoDB\Client('mongodb://localhost:27017');
if($connection) {
$db = $connection->test;
$users = $db->users;
$query = array(
"user" => $username,
"password" => $password
);
$req = $users->findOne($query);
}
Come puoi vedere, in questo esempio, il nome utente e la password utilizzati per l'autenticazione sono presi da una richiesta POST e quindi utilizzati direttamente nella query. Simile ad altri tipi di iniezione, un utente malintenzionato può fornire un payload di iniezione NoSQL che inganna il database.
Per eseguire correttamente un'iniezione MongoDB, è sufficiente che l'attaccante fornisca i seguenti dati di input dannosi come richiesta POST:
username[$eq]=admin&password[$ne]=foo
L' [$ne]operatore di query significa non uguale . Pertanto, la query risultante troverà il primo record in cui il nome utente è admin e la password non è foo . Se questo codice viene utilizzato per l'autenticazione, l'utente malintenzionato accede come utente amministratore.
È possibile utilizzare più operatori in modo simile, ad esempio [$lt]e [$gt]anche [$regex]. Le espressioni regolari possono persino consentire all'attaccante di enumerare tutti gli utenti nello scenario sopra, provando combinazioni in sequenza e valutando il risultato.
Le query MongoDB supportano un operatore di uso comune $where, che introduce possibilità di gravi attacchi NoSQL che includono oggetti JavaScript.
Ad esempio, uno sviluppatore potrebbe voler utilizzare l' $whereoperatore nel modo seguente per accedere a un record per un determinato utente:
$query = array('$where' => 'this.name === \''.$name.'\'');
In questa situazione, l'attaccante può fornire il seguente trucco di confronto tra stringhe vuote come $name:
'; return '' == '
Di conseguenza, la query diventerà:
"$where": "this.name === ''; return '' == ''"
E l'attaccante riceverà l'intero elenco di utenti.
Poiché l' $whereoperatore viene effettivamente valutato come codice JavaScript, l'attaccante potrebbe anche passare una stringa dannosa che include JavaScript arbitrario, ad esempio:
'; while(true){}'
Questo esempio crea un loop infinito e provoca un attacco denial of service.
Per evitare iniezioni di NoSQL, è sempre necessario considerare l'input dell'utente come non attendibile. Ecco cosa puoi fare per convalidare l'input dell'utente: