====Baze i datoteke==== ===PRIMJER - Zadatak s Hacknite platforme – Baze i datoteke=== Web programerka Sara je naučila koliko je bitno ograničiti tipove datoteka koje je moguće učitati (eng. upload) u web aplikaciju. Također je naučila koliko je bitno koristiti parametrizirane SQL upite. Moli te da provjeriš postoji li ipak neka napredna ranjivost koju bi netko mogao koristiti da kompromitira web aplikaciju. Napomena: Zadatak se periodički resetira (svakih sat vremena). Ako je zadatak nedostupan pričekajte 1-2 minute. http://chal.platforma.hacknite.hr:13010  source.zip Uz zadatak dostupna je i zip datoteka source.zip. Pristup na stranicu ponuđene su opcije Login i Register, prikazano na slici 1. {{ bazeidatoteke:slika1.png }} Pregledom izvornog koda u datoteci "register.php", može se vidjeti da je jedini uvjet za registraciju da su korisničko ime i lozinka duži od 10 znakova, prikazano na slici 2. (uvjet unutar drugog IF grananja). {{ bazeidatoteke:slika2.png | Slika 2. }} Nakon prijavljivanja na stranicu, dostupna je opcija uploada profilne slike, što je prikazano na slici 3. {{ bazeidatoteke:slika3.png }} Pregledom koda koji implementira funkcionalnost uploada slike, prikazano na slici 4., može se uočiti da se uploadana slika uvijek spremi pod nazivom „profile.png“. Također može se uočiti da se direktorij u koji se pohranjuje slika generira iz sha256 hasha korisničkog imena prijavljenog korisnika. Ovaj se direktorij nalazi u direktoriju „uploads“, pa je tako puna putanja uploadane slike /uploads//profile.png {{ bazeidatoteke:slika4.png }} Kako bi se provjerila ova funkcionalnost može se uploadati slika i dohvatiti njen link korištenjem razvojnih alata internetskog preglednika (F12), ili opcijom kao što je prikazano na slici 5. (desni klik) {{ bazeidatoteke:slika5.png }} Adresa slike bi trebala izgledati otprilike ovako: http://chal.platforma.hacknite.hr:13010/uploads/fec11b83d3f57a125...... 78abf4607/profile.png Što odgovara prethodno spomenutom formatu: /uploads//profile.png Sada nakon inicijalne analize koda i vidljivih funkcionalnosti u sučelju, potrebno je napraviti detaljniju analizu koda. Nakon analize svih datoteka, može se primijetiti da se potencijalno ranjiv kod nalazi u datoteci "database.php" (slika 6.). {{ bazeidatoteke:slika6.png }} Dio koda ispod komentara // Initialize the database Je ranjiv jer u slučaju da je parametar „db“ definiran, bilo u POST ili GET requestu (koristi se $_REQUEST), vrijednost tog parametra će se koristiti kao naziv nove SQLite datoteke baze podataka. Pošto nema ograničenja na naziv datoteke, ne samo da se datoteka može definirati s proizvoljnom ekstenzijom, nego se može mijenjati i path datoteke gdje će biti stvorena, korištenjem slasheva. (npr. ../../../baza…) Sad bi napadačev logični korak bio pokušati stvoriti datoteke na različitim putanjama i pokušati dohvatiti te stvorene datoteke, no to neće uspjeti. Analizom Dockerfilea mogu se pronaći razlozi zašto ovaj postupak ne bi radio. {{ bazeidatoteke:slika7.png }} Root direktorij projekta se nalazi u „/var/www/html“ i samo datoteke iz i ispod tog direktorija mogu biti dohvaćene sa servera putem interneta, predviđenim načinom korištenja. Čak i da je taj uvjet zadovoljen, može se primijetiti da korisnik www-data, s čijim identitetom kojim se izvodi serverski program, nema dopuštenje pisanja (engl. Write) nad /var/www/html direktorijem, pa ne bi ni mogao stvoriti ikakvu datoteku na proizvoljnoj putanji. Može se vidjeti da korisnik www-data ima write dozvolu samo nad /var/www/html/uploads lokacijom, koja se izvana mapira na samo /uploads putanju. Uzevši ova ograničenja u obzir, sljedeći logičan korak napadača bi bio pokušati stvoriti datoteke na putanji /uploads/.. , ali ni to neće uspjeti. U Dockerfileu linija 11 naznačuje još jedno ograničenje. Da bi se njega shvatilo, treba pogledati .htaccess, slika 8. {{ bazeidatoteke:slika8.png }} U ove tri linije koda je napisano da pokušaj dohvaćanja svih datoteka koje završavaju ekstenzijom ".php" i nalaze se u direktoriju /uploads/, njihov sadržaj neće biti poslan, nego će pristup njima biti zabranjen. NO, treba uočiti da, regularni izraz (regex) koji specificira format i lokaciju zabranjenih datoteka, se ne primjenjuje ako je između direktorija „uploads“ i ekstenzije datoteke ".php" znak „/“. Ovo znači da pravilo neće vrijediti za datoteke koje se nalaze u nekim poddirektorijima direktorija „uploads“, gdje je unutar putanje više od jednog znaka „/“, nego će te datoteke moći biti uspješno dohvaćene. Ovo znači da će na primjer pristup datoteci ‚‚ /uploads/baza.php ‚‚ ovim pravilom biti zabranjen, dok bi datoteci ‚‚ /uploads/user1/baza.php ‚‚ bio dozvoljen, tj. pravilo se ne bi primjenjivalo na nju. Uzevši i ovo ograničenje u obzir, sljedeća ideja može biti stvoriti datoteku u nekom poddirektoriju direktorija „/uploads/“, ali ovdje se javlja problem da ako direktorij u kojemu se datoteka želi postaviti već ne postoji, on neće biti automatski napravljen, nego će korisniku (napadaču) biti javljena pogreška i datoteka neće biti zapisana. Način kako bi se zapisala baza podataka s proizvoljnim imenom na lokaciju u sustavu u kojoj nije izvorno predviđena, je da se zapiše u neki već postojeći poddirektorij putanje „/var/www/html/uploads“. Srećom za napadača, jedna takva putanja je već poznata od ranije. To je putanja u kojoj se uploada postavljena profilna slika, koja je u formatu: /uploads//profile.png Ova putanja zadovoljava sva prethodno navedena ograničenja. Znači da bi se datoteka mogla uspješno zapisati na tu putanju, i s nje bi se mogla i dohvatiti: /uploads//baza.php jer je poznato da ova putanja postoji, jer je u njoj pohranjena slika "profile.png". Sada je poznata tehnika kako stvoriti datoteku s proizvoljnim imenom i ekstenzijom, npr ".php", unutar putanje na serveru s koje se datoteka može vidjeti i dohvatiti. Preostalo je pitanje kako iskoristiti tu datoteku da bi se nešto postiglo. Ako je ekstenzija datoteke „.php“, PHP kod unutar datoteke će biti obrađen i izveden pri postupku dohvaćanja zatražene datoteke prije slanja odgovora na zahtjev. Znači da, ako se stvori datoteka s „.php“ ekstenzijom i PHP kodom u sebi, koja može biti dohvaćena, pri postupku dohvaćanja prije nego što je vraćena, PHP kod će biti izvršen i rezultati izvršavanja će biti zapisani u datoteci. Ostalo je još samo pitanje kako zapisati PHP kod unutar SQLite datoteke s proizvoljnim imenom, na takav način da se PHP kod uspješno izvrši pri dohvaćanju. Unutar baze podataka s proizvoljnim imenom nad kojim imamo kontrolu se zapisuje korisničko ime i password stvorenog korisnika. Ovaj kod se može vidjeti unutar datoteke register.php (slika 9.) {{ bazeidatoteke:slika9.png }} Na username nema ograničenja osim da mora biti duže od 10 znakova i taj username će biti zapisan unutar baze podataka nad čijim imenom i lokacijom imamo kontrolu. (slika 9., slika 10. označeno crveno) {{ bazeidatoteke:slika10.png }} Ovo znači da se može stvoriti baza podataka s „.php“ ekstenzijom i s PHP kodom unutar podataka, koji bi bio u plaintext formatu, pošto se username korisnika zapisuje u plaintextu. Pri dohvaćanju ove baze podataka, što je također moguće odgovarajućim pozicioniranjem baze, PHP kod će se izvršavati, a mi ćemo moći definirati PHP kod koji će se izvršiti. Najjednostavniji kod koji se ovdje može postaviti je: ‚‚ ‚‚ Kako bi se ostvario „web PHP shell“. Ovaj PHP kod mora biti postavljen kao username korisnika pri registraciji. Potpuni postupak napada se sastoji prvo od stvaranja normalnog korisnika, uploada profilne slike s računa tog korisnika i zabilježavanja putanje na kojoj je profilna slika korisnika postavljena, bitan je dio putanje koji je sha256 vrijednost korisničkog imena. Drugi korak je stvaranje novog korisnika, gdje se POST request za registraciju modificira, tako da također sadržava „db“ parametar koji sadrži putanju i ime .PHP datoteke u kojoj će biti web PHP shell. Znači da bi primjer putanje i imena ove datoteke bio: ‚‚ ./uploads//shell.php ‚‚ A korisničko ime koje bi se unijelo pri registraciji bi bilo: ‚‚ ‚‚ Nakon ove prijave, PHP shell bi se mogao koristiti na prethodno definiranoj putanji, a s „cmd“ GET parametrom se mogu definirati shell naredbe. Npr. pokretanje naredbe „ls“. ‚‚ ./uploads//shell.php?cmd=ls ‚‚ Preporučen alat za ostvarivanje ovog postupka je burpsuite. Nakon što je prvi korisnik normalno stvoren i zabilježena je putanja njegove profilne slike kako bi se koristila u daljnjem postupku, može se pokrenuti burpsuite proxy preko kojega će se urediti zahtjev za registraciju. Nakon unosa PHP koda u polje korisničkog imena na registraciji i proizvoljnog/nevažnog passworda, kao što je prikazano na slici 11. {{ bazeidatoteke:slika11.png }} Zahtjev se šalje pritiskom na gumb "Register", dok je istovremeno burp proxy upaljen, kako bi on presreto POST request i preuredio ga tako da mu se doda odgovarajući parametar „db“ kao što je prikazano na slici 12. {{ bazeidatoteke:slika12.png }} Kada je db parametar odgovarajuće definiran, na prethodno opisan način, zahtjev se može proslijediti. Ako je tehnika uspješno izvršena, trebao bi biti vraćen odgovor s porukom o uspješnoj registraciji kao što je prikazano na slici 13. {{ bazeidatoteke:slika13.png }} Nakon ovoga, pristup web shellu je jednostavan, korištenjem putanje koja je bila definirana u „db“ parametru POST requesta registracije. U Dockerfileu se vidi lokacija flaga, tako da je za rješenje zadatka samo potrebno dohvatiti taj flag pristupom spomenutoj putanji s odgovarajućom shell naredbom zadanom u GET parametru: ‚‚ http://chal.platforma.hacknite.hr:13010/uploads/fec11b83d3f57a12506e5........0f678abf4607/shell.php?cmd=cat /opt/flag ‚‚ odnosno u općenitom zapisu formata: ‚‚ http://chal.platforma.hacknite.hr:13010/uploads/ /?cmd= ‚‚ Dohvaćanje flaga ovim načinom prikazano je na slici 14. {{ bazeidatoteke:slika14.png }}