L'operatore $where
in MongoDB è una funzione che è meglio evitare. Le sue prestazioni sono abissali e non solo perché non beneficiano degli indici. Quasi tutti i casi d'uso comuni possono essere risolti in modo molto più efficiente con una query di ricerca o aggregazione comune, in particolare una banale come questa. Ma questo è security stackexchange, non stackoverflow, quindi concentriamoci sulle implicazioni per la sicurezza.
L'istruzione $where
passa uno snippet di codice javascript al database che il database eseguirà una volta per ciascun documento nella raccolta. Fortunatamente questo script non ha accesso all'oggetto db
e ad altre pericolose funzioni della shell e funziona su copie dei documenti, quindi l'autore dell'attacco può almeno non modificare il contenuto del database come con molte iniezioni SQL. Ad esempio, è vulnerabile agli attacchi in cui l'autore dell'attacco desidera restituire altri risultati rispetto a quanto previsto.
Facciamo un esempio. Diciamo che abbiamo un blog. Il nostro blog ha molti articoli che possono essere letti in pubblico, ma abbiamo anche alcuni articoli privati che sono per uso interno e che non dovrebbero essere pubblicati. Quindi abbiamo un campo hidden
nei nostri documenti che può essere true
o false
a seconda che i nostri visitatori debbano o meno vedere l'articolo. La nostra query MongoDB per ottenere un elenco di tutti gli articoli in una determinata categoria per visualizzarla al visitatore del sito Web è simile alla seguente:
db.articles.find({"$where": "this.hidden == false && this.category == '"+category+"'" });
Questo dovrebbe fare in modo che nessuno guardi i nostri articoli nascosti. O lo fa? Quando l'utente controlla la variabile category
, può impostarla su questa stringa:
'; return '' == '
Lo snippet di Javascript risultante che viene inviato al database è questo:
this.hidden == false && this.category == ''; return '' == ''
Quando hai uno snippet di javascript con più comandi separati da ;
, saranno eseguiti come una funzione e un'istruzione return
è necessaria per determinare quale valore verrà passato al chiamante. Questa funzione restituirà sempre true. Ciò significa che l'utente vedrà anche tutti gli articoli della nostra collezione, inclusi quelli che dovrebbero essere nascosti.