FlawOpen

flawopen.com/Referência/Injeção NoSQL no MongoDB: quando a entrada muda a consulta

Injeção NoSQL no MongoDB: quando a entrada muda a consulta

Guia de segurança de banco de dados

MongoDB não executa SQL, portanto a concatenação de strings SQL não é o problema. Ainda pode haver NoSQL Injection quando a aplicação aceita um objeto aninhado não confiável onde esperava um valor escalar e o passa a um filtro MongoDB. É uma falha de validação de entrada na aplicação, não uma CVE do servidor MongoDB.

Em linguagem simples: um valor vira uma regra

Imagine um formulário que pede um nome, mas o atendente aceita um conjunto inteiro de instruções no campo. O banco segue as instruções em vez de comparar um nome. Valide o tipo de valor esperado e construa você mesmo a regra de busca.

Limite de confiança: do JSON da requisição ao filtro MongoDB

Filtro de consulta
Documento BSON interpretado pelo MongoDB como comparações de campos e, quando presentes, operadores de consulta.
Injeção de operador
A aplicação recebe uma estrutura controlada pelo usuário onde deveria aceitar apenas um valor literal.
Validação de escalar
Verificar tipo, tamanho e formato permitido antes que a entrada influencie uma operação no banco.
Projeção
Lista de campos selecionada pelo servidor para limitar a exposição acidental de dados.

Como a falha acontece

1

O endpoint espera um valor escalar

O contrato da API define username como uma string, mas o parser JSON também aceita arrays, objetos, booleanos e null.

2

A aplicação ignora a validação do tipo

O handler insere o valor analisado diretamente em um filtro criado pelo servidor; um objeto continua sendo estrutura de consulta, em vez de uma string literal.

3

O MongoDB avalia a estrutura recebida

Se o documento aninhado contiver operadores de consulta, o predicado pode diferir da comparação exata pretendida. Os registros afetados dependem da consulta e das verificações de autorização da aplicação.

4

A resposta determina a exposição

Campos retornados e quantidade de registros dependem da projeção, do endpoint e dos privilégios da conta do banco. Isso, por si só, não comprova bypass de autenticação nem acesso ao banco inteiro.

Escopo e evidências

A documentação oficial dos drivers MongoDB descreve esse limite quando um endpoint converte JSON não validado em BSON e o usa como filtro. Este guia modela essa falha na aplicação. Não afirma que toda instalação MongoDB é vulnerável, não identifica uma CVE do servidor e não ensina bypass de autenticação.

Padrões vulnerável e endurecido em Node.js

VULNERABLE — UNVALIDATED VALUE ENTERS FILTER
app.post("/users/lookup", async (req, res, next) => {
  try {
    // The route expects a string, but req.body.username is untrusted JSON.
    const user = await users.findOne({ username: req.body.username });
    res.json(user ? { username: user.username } : null);
  } catch (error) {
    next(error);
  }
});
HARDENED — VALIDATE SHAPE, BUILD FILTER, VERIFY HASH
const loginSchema = z.object({
  username: z.string().trim().min(1).max(128),
  password: z.string().min(1).max(1024)
}).strict();

app.post("/login", async (req, res, next) => {
  try {
    const parsed = loginSchema.safeParse(req.body);
    if (!parsed.success) return res.sendStatus(400);

    const { username, password } = parsed.data;
    // The application owns the filter key; input supplies only a string value.
    const user = await users.findOne(
      { username },
      { projection: { _id: 1, username: 1, passwordHash: 1 } }
    );
    const passwordMatches = user &&
      await argon2.verify(user.passwordHash, password);
    if (!passwordMatches) return res.sendStatus(401);

    return res.sendStatus(204); // Session creation is application-specific.
  } catch (error) {
    next(error);
  }
});

O fluxo protegido rejeita campos que não sejam texto antes de acessar o banco, não aceita filtros enviados pelo cliente, monta em código da aplicação uma chave fixa para o filtro, retorna apenas os campos selecionados e verifica o hash da senha depois de localizar o usuário. O exemplo pressupõe que z seja Zod, users seja a coleção MongoDB e argon2 seja uma biblioteca configurada para hash de senhas; a criação da sessão fica fora do exemplo.

Verificações para validar a correção

Fontes primárias

Explore guias de segurança relacionados:Abrir o diretório de segurança →
Veja também SQL Injection (CWE-89): como funciona e como evitar em todas as linguagens — flawopen.com String de IDs numéricos também pode causar SQL Injection? O que é uma consulta parametrizada? Prisma $queryRaw: é seguro contra SQL Injection? Interpolação em where() do Rails é segura? Sequelize query() é seguro contra SQL Injection? SQLAlchemy text() é seguro contra SQL Injection?