Foto de Markus Spiske na Unsplash
A injeção NoSQL é uma vulnerabilidade de segurança que afeta bancos de dados NoSQL, como o MongoDB, de maneira similar à injeção SQL em bancos de dados relacionais. A vulnerabilidade ocorre quando entradas de usuários não são devidamente validadas ou sanitizadas, permitindo que usuários mal-intencionados manipulem as consultas enviadas ao banco de dados.
Seu MongoDB não está seguro! Neste artigo, vamos explorar como essa falha de segurança pode se manifestar em aplicações que utilizam MongoDB, apresentar exemplos práticos de injeção NoSQL e sugerir medidas para corrigir e prevenir esse problema.
O que é uma Injeção NoSQL?
Injeção NoSQL ocorre quando um invasor consegue modificar consultas ao banco de dados através de dados de entrada maliciosos. Em um ambiente MongoDB, que permite consultas em formato JSON, a vulnerabilidade pode ser explorada se uma aplicação não tratar corretamente os parâmetros fornecidos por usuários.
Por exemplo, em MongoDB, uma consulta comum para buscar um usuário baseado no nome pode ser feita assim:
db.users.find({ "name": userInput });
Se o userInput
for diretamente utilizado sem validação, um invasor pode injetar um objeto no lugar de um simples nome de usuário, o que pode alterar o comportamento da consulta.
Em 2021, injeções estiveram em 3º lugar no OWASP Top Ten.
Ranking do OWASP Top 10 em 2021
Exemplos de Injeção NoSQL
Aqui estão alguns cenários comuns de injeção NoSQL no MongoDB.
1. Injeção de Objeto
Considere uma API que autentica um usuário com base em seu nome de usuário e senha. A consulta pode ser semelhante a esta:
db.users.find({ "username": userInputUsername, "password": userInputPassword });
Se a aplicação não sanitizar os inputs, um invasor pode passar um valor como o seguinte para userInputUsername
:
{ "$ne": "" }
Com isso, a consulta se torna:
db.users.find({ "username": { "$ne": "" }, "password": userInputPassword });
Aqui, a injeção $ne
(não igual a) permite que o invasor ignore a autenticação, uma vez que qualquer usuário com uma senha correspondente será retornado, independentemente do nome de usuário.
2. Injeção OR
Outro exemplo envolve o uso do operador lógico OR
. Suponha que a aplicação esteja validando um usuário com base em seu e-mail e senha:
db.users.find({ "email": userInputEmail, "password": userInputPassword });
Um invasor pode inserir algo como:
{ "$or": [{ "email": "[email protected]" }, { "password": { "$ne": "" } }] }
Isso transformaria a consulta original em:
db.users.find({ "$or": [{ "email": "[email protected]" }, { "password": { "$ne": "" } }] });
Dessa forma, a consulta irá retornar qualquer usuário, desde que a condição $ne
seja verdadeira, o que compromete a segurança do sistema.
Como Prevenir a Injeção NoSQL no MongoDB
Agora que entendemos como essas vulnerabilidades podem ser exploradas, vamos discutir algumas práticas recomendadas para prevenir a injeção NoSQL.
1. Sanitização e Validação de Entradas
A primeira linha de defesa contra injeções NoSQL é garantir que todos os dados fornecidos pelos usuários sejam devidamente validados e sanitizados. Assegure-se de que as entradas sejam do tipo e formato esperados. Para MongoDB, é importante validar o tipo de dado antes de processá-lo, especialmente ao lidar com objetos JSON.
Ferramentas como Joi, Validator.js, ou bibliotecas específicas para frameworks (como o class-validator no NestJS) podem ser utilizadas para validar os dados de entrada.
Além disto, ferramentas como content-filter e mongo-sanitize podem também auxiliar na sanitização destes inputs.
Outras formas também incluem o uso da função nativa escape()
e implementações de métodos customizados.
2. Limitação de Operadores Permitidos
Uma medida útil é restringir os operadores que podem ser utilizados em consultas. No MongoDB, operadores como $ne
, $or
, e $gt
são poderosos, mas também potencialmente perigosos. Ao controlar quais operadores são permitidos nas consultas, você reduz o risco de injeção.
3. Princípio de Menor Privilégio
Outra prática importante é aplicar o princípio de menor privilégio aos usuários do banco de dados. Isso significa garantir que a conta do MongoDB usada pela aplicação tenha apenas os direitos necessários para realizar suas funções, evitando que um eventual ataque tenha amplo acesso ao banco de dados.
4. Uso de Bibliotecas de ORM/ODM Seguras
Bibliotecas ORM (Object-Relational Mapping) ou ODM (Object-Document Mapping), como o Mongoose, podem ajudar a mitigar vulnerabilidades ao fornecer mecanismos seguros para construir consultas. Essas bibliotecas geralmente impõem uma camada de abstração que dificulta a inserção de código malicioso diretamente nas consultas.
Por que injeções não são tão comuns e citadas?
Assim como citado no “Como o MongoDB aborda SQL ou injeção de Query?” no MongoDB as consultas são criadas como objetos BSON, não como strings, o que elimina o risco de injeções SQL tradicionais. As bibliotecas de clientes oferecem maneiras seguras de gerar esses objetos sem expor a aplicação a ataques de injeção.
Conclusão
Injeções NoSQL são uma ameaça real para aplicações que utilizam MongoDB sem uma sanitização adequada de entrada. Elas podem comprometer tanto a integridade quanto a confidencialidade dos dados. Para se proteger contra essas vulnerabilidades, é essencial validar entradas, restringir o uso de operadores perigosos, aplicar o princípio de menor privilégio e utilizar bibliotecas seguras para acessar o banco de dados.
A adoção dessas práticas permitirá que sua aplicação seja mais robusta e segura, evitando ataques que poderiam comprometer seriamente o sistema.