Sigurnost MongoDB baze podataka
Sadržaj |
Mrežna izloženost i sigurnost
Standardne postavke MongoDB baze podataka omogućuju pristup bazi podataka svim vanjskim IP adresama koristeći port 27017. Iako je to dobra mogućnost za brzo testiranje i lakši ‘’deployment’’ aplikacije koja tu bazu koristi, ostavlja i velik broj ranjivosti i olakšava udaljen pristup podacima.
U konfiguracijskoj datoteci Mongo baze podataka postoji nekoliko rizičnih opcija koje daju kontrolu nad načinom povezivanja, dopuštenim sučeljima, IP adresama i portovima.
Prva rizična opcija jest nohttpinterface. Navedena opcija omogućuje uvid u bitne aspekte postojeće baze podataka u obliku HTML izvještaja. Naime, potencijalni napadač može posjetom na url_stranice:28017 dobiti potpuni opis baze podataka, počevši od verzije, broja kolekcija, načina korištenja i sl.
Osim generalnih podataka, napadač također može dobiti uvid u cijeli log te time popis direktorija u kojem se nalazi konfiguracijska datoteka i podatke o operacijskom sustavu.
Razlog zbog kojeg ova opcija postoji u standardnim postavkama je da administrator može jednostavno provjeriti ispravnost nove instalacije same baze ili nekog od modula. Način za deaktivaciju jest postavljanje opcije na true u mongodb.conf datoteci.
Sljedeća bitna opcija je sam port na kojem sluša baza podataka. Kombinacija IP_adresa:Port omogućuju udaljenu administraciju baze podataka. Standardni port na kojem Mongo baza sluša jest 27017 i to predstavlja dosta velik sigurnosni rizik. Uzmimo neku web aplikaciju za koju smo saznali da u pozadini koristi MongoDB bazu podataka. U našem primjeru to će biti vlastita aplikacija uboxie.me. Koristeći neki od postojećih alata za pretvorbu imena domene u IP adresu, dobit ćemo točan IP od željene aplikacije. HCIdata.
Pomoću alata Robomongo koji služi za jednostavnu administraciju Mongo baze podataka dobivenu IP adresu i port 27017 lako iskoristimo za spajanje na bazu podataka i uvid u sve kolekcije i podatke u njoj. Mongo po standardnim postavkama ne zahtjeva posebnu autentikaciju korisnika, te su podaci o IP adresi i portu na kojem radi baza podataka dovoljni za uvid u sve podatke u bazi.
Port je potrebno promijeniti u neki port koji je slobodan i različit od standardne postavke. U ovom slučaju postavljen je port 14412. Uz sam port, jako je važno definirati i IP adrese koje mogu pristupati bazi podataka. Definirana vrijednost za Mongo jest localhost (127.0.0.1) i na taj način onemogućuje udaljeni pristup bazi podataka. No zbog potreba razvoja aplikacija i mogućnosti udaljenog pristupa u polje bind_ip u config datoteci definiramo listu dozvoljenih IP adresa kojima se omogućuje udaljeni pristup.
Mongo također omogućuje i REST sučelje koje programeru daje način interakcije s bazom pomoću poziva validnih metoda. Tako i neovlaštena osoba može doći do podataka o samoj bazi. U najnovijoj verziji 2.6. Mongo baze opcija rest je podešena na false automatski, no na starijim verzijama to nije slučaj i mora se posebno definirati u config datoteci. Crest
Osim same konfiguracije baze podataka, na mrežnu sigurnost utječe i konfiguracija samog operacijskog sustava. Na Ubuntu operacijskom sustavu potrebno je koristiti iptables program koji daje mogućnost definiranja pravila za firewall. Pravila imaju nekoliko ‘’chain’’ elemenata kroz koje moraju proći, a ovdje ćemo spomenuti dva najvažnija: INPUT i OUTPUT. Pravila će koristiti politiku koja odbacuje sav promet koji nije eksplicitno dopušten.
iptables -A INPUT -s < ip-address> -p tcp --destination-port 14412 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -d < ip-address> -p tcp --source-port 14412 -m state --state ESTABLISHED -j ACCEPT
Prvo pravilo definira sav ulazni promet prema bazi podataka na portu 14412. U polju <ip-address> potrebno je definirati adresu (ili raspon adresa) koje se odnose na aplikacijski server koji pristupa bazi podataka. Drugo pravilo definira odlazni promet od baze podataka prema aplikacijskom serveru. Postavljanjem ovih jednostavnih pravila uvelike smo poboljšali filtriranje prometa i osigurali pristup bazi podataka samo s ovlaštenih adresa. Kao što je spomenuto, pravila moraju odbaciti sav promet koji nije dopušten.
Standardna konfiguracija dozvoljava sav promet pa je to potrebno promijeniti u DROP konfiguraciju:
Nakon prilagodbe iptables konfiguracije, potrebno ju je spremiti trajno jer je konfiguracija inače spremljena samo u privremenu memoriju.
Također, nekonfigurirani MongoDB omogućuje napadaču zlouporabu pomoću REST apija kojeg podržava svaka instanca Mongo baze podataka. Napadač može jednostavno iskoristiti neki od postojećih alata kako bi dobio uvid u strukturu baze, kolekcije i sl. Kao praktični primjer iskoristili smo Node.js/Express razvojni okvir s dodatkom mongo-rest. Mongo rest pruža sljedeća sučelja za dobivanje informacija o bazi podataka:
- GET /dbs - Vraća imena svih baza.
- GET /<db>/ - Ime svih kolekcija u određenoj bazi
- GET /<db>/<collection> - Svi dokumenti u određenoj kolekciji
- GET /<db>/<collection>?output=csv - Svi dokumenti u određenoj kolekciji u csv formatu
- GET /<db>/<collection>?query=%7B%22isDone%22%3A%20false%7D Dokumenti koje zadovoljaju određeni upit
- GET /<db>/<collection>?query=%7B%22isDone%22%3A%20false%7D&limit=2&skip=2 - Mogućnost definiranja limit i skip opcija
- GET /<db>/<collection>/id - Vraća dokument s određenim id-em
- POST /<db>/<collection> - Sprema određeni dokument u kolekciju
- PUT /<db>/<collection>/id - Ažurira dokument s određenm id-em
- DELETE /<db>/<collection>/id - Briše dokument s id-em
SSL podrška
Standardna, besplatna inačica Mongo baze podataka nema podršku za SSL. Da bi omogućili podršku, potrebno je instalirati plaćenu Enterprise verziju ili kompajlirati besplatnu inačicu iz source koda i pritom ju konfigurirati da omogućuje spajanje preko SSL-a. Mongo za build sustav koristi SCons koji je potrebno instalirati i pomoću njega kreirati Mongo instancu spremnu za instalaciju. Sam proces zahtjeva dosta radne memorije te neće raditi na većini osnovnih serverskih paketa.[Scons]
Sam certifikat je moguće kreirati (za potrebe testiranja) ili u produkcijskoj verziji koristiti potpisani SSL certifikat (.pem datoteku). Za potrebe ove konfiguracije kreiran je certifikat bez posebne lozinke, trajanja 365 dana:
cd /etc/ssl/openssl req -newkey rsa:2048 -new -x509 -days 365 -nodes -out mongodb-cert.crt -keyout mongodb-cert.key
Kako bi sam proces izgradnje instalacijske verzije Mongo bio jednostavniji, kreirali smo bash skriptu koja poziva tražene naredbe
Kontrola pristupa
Kontrola se pristupa definira na razini kolekcije te omogućuje definiranje dozvoljenih akcija nad pojedinim resursima (kolekcijama).
Kod specifikacije privilegije, administrator sustava može definirati bazu, kolekciju te listu privilegija koje se nad navedenom kolekcijom mogu izvoditi.
Kontrola pristupa definira se kod kreiranja uloge kao polje objekata koje specificiraju privilegije na različitim kolekcijama.
Za svaku kolekciju moguće je dobiti korisnika i dodijeljene mu privilegije pomoću naredbe:
Privilegije su uvijek polje objekata oblika:
privileges: [ { resource: { db: "dbName", collection: "colName" }, actions: [ "find", "update", "insert" ] }, { resource: { db: "dbName", collection: "colName" }, actions: [ "find" ] }]
Autorizacija i autentikacija
MongoDB baza podataka prije određivanja razine pristupa od korisnika zahtjeva da se on autenticira. Nadalje, MongoDB baza podataka podržava više mehanizama autentikacija identiteta korisnika od kojih su neki x.509 certifikati te autentikacija pomoću MONGODB-CRa. Kod Enterprise verzije postoje još dodatna dva mehanizma, a oni su autentikacija pomoću Kerberos servisa te LDAP autentikacija. Također, dodatno se mogu autenticirati članstva krajnjih korisnika prilikom njihovog pristupanja određenom klasteru koji se može održavati između više instanci MongoDB baze podataka.
MONGODB-CR
Ovaj način autentikacije unutar MongoDB baze podataka predstavlja autentikaciju putem korisničkih imena te lozinki. Ovakva autentikacija predstavlja načelni odnosno zadani oblik autentikacije kod MongoDB baze podataka.
x.509 Certifikati
Jedan od načina autentikacija identiteta korisnika jest korištenjem x.509 certifikata koji se koriste kod SSL pristupa. Umjesto klasičnog načina razmjene korisničkog imena te lozinke korisnika sa samim poslužiteljima se razmjenjuju certifikati. Kako bi certifikat bio ispravan on mora biti izdan i za sam poslužitelj i za krajnjeg klijenta od strane jednog tijela. Kako bi omogućili ovakav način autentikacija potrebno je unutar same konfiguracije MongoDB baze podataka postaviti sljedeće (datoteka je u YAML formatu):
security: clusterAuthMode: x509 net: ssl: mode: requireSSL PEMKeyFile: <putanja do SSL certifikata te KEY PEM datoteke> CAFile: <putanja do CA PEM datoteke>
Kako bi se autentikacija preko samog x.509 certifikata mogla obaviti potrebno je kreirati novog korisnika same baze podataka koji će odgovarati samom certifikatu krajnjeg klijenta. Prilikom toga sam subjekt certifikata se pretvara u novog korisnika baze podataka. Prilikom ovog postupka autentikacije jedan certifikat uvijek odgovara samo jednom korisniku te nije moguće autenticirati više različitih korisnika baze podataka preko jednog jedinstvenog x.509 certifikata.
Autorizacija korištenjem korisničkih uloga
Prilikom ovog postupka samom korisniku baze podataka se određuje razina pristupa samim resursima te operacijama nad bazom podataka. MongoDB baza podataka u osnovi nema omogućenu autorizaciju, no ona se može jednostavno uključiti kada je potrebno. Kako bi se sama autorizacija uključila u rad baze podataka potrebno je koristiti --auth ili --keyFile opcije, također autorizacija može biti uključena i korištenjem konfiguracijske datoteke. MongoDB kao baza podataka sadrži nekoliko ugrađenih korisničkih uloga koje se mogu odmah koristiti ili ukoliko je potrebno nove uloge za same korisnike mogu biti kreirane od strane administratora baze podataka. Kod kreiranja novih korisničkih uloga koristi se naredba createRole dok se kod uklanjanja i ažuriranja koriste naredbe dropRole te updateRole. Krajnji korisnik može sadržavati više uloga prilikom čega on ima sve privilegije koje sadrže pojedina od uloga koje su mu dodjeljene. Privilegije koje su dodjeljene korisničkim ulogama sadržavaju određeni resurs te akcije koje su omogućene nad samim danim resursom. Resurs u toj domeni predstavlja sama baza podataka, određena kolekcija ili skup kolekcija podataka unutar same baze itd.. Akcije s druge strane predstavljaju određene metode ili komande koje sam korisnik koji sadrži privilegiju smije izvršavati nad danim resursom.
Prilikom korištenja metode db.createRole(), potrebno je definirati naziv nove uloge, privilegije koja će sama uloga imati te uloge od kojih će novokreirana uloga preuzeti privilegije. Primjer korištenja ove metode možemo vidjeti na slici ispod:
Ukoliko želimo pobrisati određenu korisničku ulogu koristiti ćemo metodu db.dropRole() te u istu prosljediti naziv uloge koju želimo ukloniti. Primjer korištenja ove metode možemo vidjeti niže:
Ako smo krivo definirali korisničku ulogu ili na istu želimo dodati nove privilegije to ćemo postići korištenjem metode db.updateRole(). U samu metodu potrebno je proslijediti naziv korisničke uloge te objekt koji opisuje nove privilegije koje će sama uloga dobiti ili naslijediti od strane već postojećih korisničkih uloga. Primjer možemo vidjeti ispod:
Upravljanje korisnicima
Unutar MongoDB baze podataka kako bi kreirali novog korisnika potrebno je definirati osnovne korisničke podatke te novom korisniku dodjeliti jednu ili više korisničkih uloga ukoliko to želimo. Ako koristimo autentikaciju unutar same baze podataka potrebno je prilikom kreiranja novih korisnika autenticirati se kao administrator korisnika. Ukoliko administrator korisnika ne postoji potrebno ga je kreirati. Administrator korisnika predstavlja korisnika sa ulogom userAdminAnyDatabase ili userAdmin. Nadalje, kreiranje novog korisnika se provodi korištenjem db.createUser() metode. Primjer korištenja ovakve metode možemo vidjeti na slici ispod:
Kako se novi korisnik kreira na razini određene zadane baze podataka isti se može autenticirati unutar te zadane baze. Taj postupak možemo vidjeti na slici ispod:
Nadalje ukoliko zbog određenih razloga trebamo ukloniti jednog ili više korisnika iz same baze podataka to možemo napraviti pozivom metode db.dropUser() koja kao argument uzima korisničko ime korisnika kojeg želimo ukloniti iz baze podataka. Primjer korištenja ove metode možemo vidjeti na slici ispod:
Ukoliko želimo dohvatit određenog korisnika te podatke vezane uz njega to možemo preko poziva metode db.getUser() čiji će rezultat dati sve potrebne informacije o samom korisniku te njemu dodjeljenim ulogama i privilegijama. Jedan primjer korištenja ove metode možemo vidjeti ispod:
Default Konfiguracija
Pokretanje MongoDB-a uz navođenje konfiguracijske datoteke se vrši pomoću izvršne datoteke mongod ( ili mongos) uz naredbu --config (-f):
Konfiguracijska datoteka je u YAML formatu, koji podatke predstavlja u hijerarhijskoj strukturi. YAML format je uveden kao zadani format od verzije 2.6, no podržan je i stari klasični format koji nije strukturiran poput YAML-a. Primjer konfiguracije sa par postavki je vidljiv ispod.
systemLog: destination: file path: "/var/log/mongodb/mongodb.log" logAppend: true storage: journal: enabled: true processManagement: fork: true net: bindIp: 127.0.0.1 port: 27017
U zadanoj konfiguraciji, postoji mnogo postavki koji su predefinirane, te ih je moguće promjeniti.
U systemLog kategoriji moguće je postaviti različite postavke vezane za log datoteku. Format vremena (systemLog.timeStampFormat) je zadan na lokalno vrijeme u ISO-8601 formatu. Također, postavkom systemLog.logAppend zadano je da prilikom restartiranja mongod (mongos) procesa log datoteka ne čuva prethodno upisani sadržaj, te je moguće navedenu postavku podesiti na vrijednost True kako bi se novi unosi dodali na kraj postojeće log datoteke.
Zadani TCP port na kojoj MongoDB osluškuje veze je 27017. Moguće ga je podesiti pomoću net.port postavke. Povezivanje IP adresa je moguće pomoću net.bindIp postavke koja je zadana na 127.0.0.1. Maksimalni broj istovremenih veza je ograničen na 1000000, te ga je moguće promjeniti postavkom net.maxIncomingConnections. Po zadanim postavkama uključena je validacija svih zahtjeva od klijenta (net.wireObjectCheck) kako bi se spriječio nevažeći ili neispravni unos u MongoDB bazu. Zadana distribucija MongoDB-a ne uključuje podršku za SSL, te ukoliko želimo tu opciju uključiti, instalacija se mora lokalno izvršiti sa dodatnim parametrom za SSL nakon čega se u konfiguraciji može podesiti postavka. net.ssl.mode zajedno sa nizom drugih postavki u kategoriji net.ssl.
MongoDB instance koriste djeljenu tajnu (engl. shared secret) kako bi autentificirali jednu drugu unutar tzv. sharded clustera ili replica set. Postavkom security.keyFile navodimo putanju do te datoteke. Za klastersku autentifikaciju zadano se koristi keyFile, no preporučeno je koristiti x.509 certifikat za autentifikaciju, što je moguće navesti pomoću security.clusterAuthMode: x509. Ukoliko koristimo x509, potrebno je podesiti putanje do PEMKeyFile te do CAFile koje prethodno moramo dobaviti. Autorizacija, odnosno kontrola pristupa na temelju uloga (engl. Role-Based Access Control) je zadano isključena i moguće ju je uključiti postavkom security.authorization: enabled. Pošto MongoDB može izvršavati JavaScript naredbe, moguće ih je i isključiti postavkom security.javascriptEnabled: false, u tom slučaju naredbe $where, mapReduce, group te mnoge druge su također onemogućene.
NOSQL Injection
Kod klasičnih relacijskih baza podataka dolazi do problema SQL Injection-a. Sam SQL Injection predstavlja vrstu napada koja se najčešće koristi protiv aplikacija bogatih podacima koji se ujedno i čuvaju unutar samih baza podataka. Prilikom SQL Injection napada maliciozni SQL kod se dodaje na same krajnje podatke koji se vežu uz SQL upite koje sama baza podataka ili aplikacija izvodi.
Prilikom toga napadač može naštetit samim podacima ili doznati određene privatne podatke vlasnika samih baza odnosno aplikacija. S druge strane NoSQL baze podataka poput MongoDB baze podataka ne onemogućuju napade preko SQL Injection-a no omogućuju napade poput NoSQL Injection-a. NoSQL baze podataka sadrže manje ograničenja nego klasične SQL baze podataka pa radi toga NoSQL baze podataka često pružaju razne benificije u obliku skaliranja i performansi.
NoSQL Injection napadi se mogu izvrišiti unutar proceduralnog jezika umjesto deklarativnog poput SQL-a, pa samim time rizici zbog toga su veći nego kod klasičnih napada putem SQL Injection-a. Pozivi unutar NoSQL baza podataka su često napisani unutar samog programskog jezika aplikacije ili u obliku dogovorenom prema određenoj konvenciji. Maliciozni podaci preko kojih se izvodi sam napad u ovom slučaju mogu proči same validacijske provjere aplikacije poput isključivanja dodatnih HTML znakova poput <, >, ;, & no i nadalje to ne znači da će doći do uspješnog zaustavljanja napada. Jedan primjer ovdje jest JSON API unutar kojeg specijalni simboli uključuju i sljedeće simbole: /, {, }, :.
Prednost koja se javlja kod korištenja NoSQL baza podataka jest njihova raznovrsnost. Baš zbog te raznolikosti i različitih funkcionalnosti pojedini Injection napadi neće uspjeti na svim različitim NoSQL bazama podataka na isti način. NoSQL Injection napadi se mogu dogoditi unutar različitih područja aplikacije. S druge strane SQL Injection se događa unutar samog engine-a baze dok kod NoSQL Injection-a do napada može doći na razini same aplikacije ali isto tako i na razini baze podataka ovisno o samoj bazi podataka te podatkovnom modelu. Najčešće NoSQL Injection napadi se izvršavaju prilikom parsiranja te validiranja samog poslanog podatka.
NoSQLMap
NoSQLMap predstavlja jedan od alata koji ima mogućnosti testiranja samih NoSQL baza podataka u vezi Injection napada. MongoDB te CouchDB baze podataka predstavljaju baze koje sam alat trenutno cilja prilikom provođenja napada. Kako bi instalirali alat potrebno je isti klonirati sa github repozitorija koji se nalazi na sljedećem linku:
Nadalje, potrebno je nakon kloniranja samog github repozitorija pokrenuti instalaciju alata tako da pokrenemo datoteku setup.py. Nakon instalacije alata pokrenuti ga možemo preko konzole pozivanjem naredbe NoSQLMap. Kako bi proveli napad na NoSQL bazu podataka moramo prvo podesiti opcije unutar samog alata. Prvo potrebno je definirati IP adresu i port baze podataka koja je cilj napada. Nakon postavljanja IP adrese i porta potrebno je definirati IP adresu lokalne NoSQL baze podataka unutar koje će se spremiti podaci koji budu dohvaćeni sa ciljane baze podataka. Nakon postavljanja ovih parametara potrebno je vratiti se na početni izbornik na kojem ovaj put biramo opciju NoSQL DB Access Attacks prilikom čega će se provjeriti pristup ciljanoj bazi podataka. Ukoliko se uspješno pristupi udaljenoj bazi podataka mogu se krenuti koristiti dodatne opcije poput kloniranja baza te listanja baza. Alat također omogućuje opciju skeniranja IP range-a ili IP adresa iz datoteke te prilikom toga daje informacije ukoliko je moguće spojiti se na određenu NoSQL bazu koja se nalazi na zadanoj IP adresi. Primjer postupka provođenja napada možemo vidjeti na sljedećim slikama: