====Blind SQL injection==== Pri općenitom testiranju ranjivosti nekog unosa na SQL injekcije, mogu se prvo pokušati unijeti jednostruki ili dvostruki navodnici i ako je web poslužitelj podešen da prosljeđuje pogreške korisniku, korisniku se može proslijediti i prikazati poruku greška koju je baza poslala, gdje na primjer piše da je neispravno korištenje znakova navodnika. U nekim situacijama sustav je podešen tako da se poruke pogreške iz baze podataka nikad ne prosljeđuju krajnjem korisniku, no sam SQL upit koji se generira s korisničkim unosom nije dobro formatiran i zaštićen. U takvim slučajevima mogu se koristiti takozvane slijepe SQL injekcije. Glavna razlika između slijepih i „običnih“ SQL injekcija, jest da u slijepim SQL injekcijama nema konkretnih podataka koji se dohvaćaju SQL injekcijom iz sustava i vraćaju napadaču, nego napadač na domišljate i kreativne načine nađe način da napravi SQL injekciju i od baze podataka, često indirektno, sazna je li SQL upit konstruiran SQL injekcijom točan ili netočan. Informacija koje se mogu ovim načinom iskorištavanja saznati su, na primjer: - postoji li korisnik "admin" u sustavu? - počinje li lozinka korisnika admin sa slovom "a"? - počinje li lozinka korisnika admin sa slovom "b"? - počinje li lozinka korisnika admin sa slovima abc? Iako su pitanja na koja možemo saznati odgovor samo potvrdna, odnosno jedine informacije koje možemo dobiti su da ili ne / točno ili netočno..., i dalje često možemo postaviti velik broj ovakvih pitanja sustavu i na svako ovo pitanje, pažljivim praćenjem promjena na stranici, možemo zaključiti koji su odgovori na postavljena pitanja. Često je onda idući korak napraviti skriptu ili koristiti već gotov alat, koji će umjesto automatski generirati i postaviti velik broj pitanja koja nas zanimaju i na kraju nam pokazati zabilježene odgovore. __**Primjeri**__ - **Zadatak s Hacknite platforme** - ** Banka ** Sara je razvojna programerka za banku. Napravila je aplikaciju za e-banking, budući da je sigurnost e-banking aplikacija vrlo važna skenirala je aplikaciju raznim sigurnosnim alatima, no nije pronašla nikakve ranjivosti. Također, za dodatnu razinu sigurnosti implementirala je dvofaktorsku autentifikaciju. Ipak, misli da bi bilo dobro da i vi provjerite sigurnost aplikacije prije nego što bude puštena u produkciju. Hint: objavljen je izvorni kod Napomena: Nije potrebno bruteforceati drugi faktor. http://chal.platforma.hacknite.hr:12009 Flag je u formatu CTF2023[brojevi]. Pri prvom pregledu stranice, vidimo da se stranica sastoji od početne stranice, login forme, admin portala i stranice za resetiranje lozinke. Pri isprobavanju login forme i admin portala, za unesene pokušaje korisničkim imena i lozinki dobivamo samo generičan odgovor „Krivo korisničko ime ili lozinka“. Pri pokušaju unošenja različitih imena u formu za resetiranje lozinke dobijemo odgovor „korisničko ime ne postoji“. Možemo pretpostavit da ako ovdje pogodimo barem ime nekog korisnika da ćemo dobit potvrdan odgovor. U tekstu zadatka je napisano da je Sara napravila stranicu, te pokušajem unosa imena „sara“ u formu za resetiranje lozinke dobivamo odgovor „Pozdrav, sara, reset lozinke mailom još nije dostupan. Lozinku možete resetirati u jednoj od naših poslovnica“. {{blind_sql_1.png}} Pokušajem unosa jednostrukih navodnika „ ' „ ne dobivamo nikakvu poruku, niti da korisnik ne postoji, niti poruku pozdrava, što može upućivati na to da je SQL injection moguć ili je unos filtriran, te da smo možda prouzročili SQL grešku pokretanjem slanjem ovog unosa, no poslužitelj ne prosljeđuje poruke greške. {{blind_sql_2.png}} Uz zadatak je dostupan i dio izvornog koda. Analizom djela koda za resetiranje lozinke u datoteci reset.php, vidimo da SQL upit nije formatiran na siguran način, te da bi potencijalno bila moguća SQL injekcija. Također vidimo da se nakon dohvata SQL upita iz baze, ovisno o tome je li dohvaćena neka n-torka iz baze ili ne, vraća ili odgovor da korisničko ime ne postoji, ili poruka pozdrava. {{blind_sql_3.png}} Pokušajem jednostavnog SQL injectiona ' OR 1=1 – , dobivamo poruku pozdrava. {{blind_sql_4.png}} Možemo zaključit da smo ovime uspjeli izvršit SQL injection kojim smo dohvatili barem jednu ili više n-torki iz baze podataka, te da nam je sukladno tome ispisana poruka pozdrava. Ovo nas navodi na zaključak da se u reset formi može koristiti blind SQL injection, pri kojemu po prisutnosti poruke pozdrava ili nedostatku možemo znati postoji li unutar baze barem jedna n-torka koja odgovara SQL upitu koji smo manipulirali uz pomoć SQL injekcije, a ako se ne vrati nikakva poruka, SQL upit konstruiran injekcijom je netočan sintaksom, odnosno uzrokuje error. Analizom koda također možemo zaključiti da postoji tablica //users// s atributima //username// i //password//. Dio koda iz kojeg je to jasno vidljivo je prikazan na slici ispod. {{blind_sql_5.png}} Uz pomoć ovih informacija možemo osmislit formu SQL injekcije kojom ćemo saznati informacije koje nas zanimaju iz baze. Koristi ćemo SQL //LIKE// operator i „wildcard“ simbol //%//, koji znači da jest umjesto njega u stringu prisutan ili nijedan, ili jedan ili više bilo kakvih znakova. Pojednostavljeno, ako pitamo je li password kao (//LIKE//) //%// , ne pitamo efektivno ništa više nego postoji li vrijednost password, koja ima ili nijedan ili jedan ili više znakova, što nam samo po sebi nije korisno, no ako pitamo je li password kao (LIKE) „abc%“, pitamo počinje li password znakovima abc nakon kojih ima ili nijedan ili više znakova. Ovom funkcionalnošću ćemo probati saznati znak po znak passworda. Prvo ćemo konstruirati samo oblik SQL injekcije koju ćemo koristiti, koja ne uzrokuje grešku, a onda ćemo ju naknadno uz pomoć skripte mijenjati i ponavljati veliki broj puta. Oblik naše SQL injekcije će biti sljedeći: sara' AND (SELECT password FROM users) LIKE '%' -- Pokretanjem ovog unosa, dobivamo odgovor, što znači da smo konstruirali SQL injekciju koja ne izaziva grešku, nego se uspješno izvodi i da vraća barem jednu n-torku koja ima vrijednost usernamea „sara“ i ima atribut password. Uspješno izvršavanje ovog unosa prikazano je na slici ispod. {{blind_sql_6.png}} Sada je potrebno napisati skriptu koja će redoslijedom isprobavati sve kombinacije prvog znaka passworda, gdje će redom pokušavati izvršiti prethodnu SQL injekciju s vrijednošću LIKE "a%", pa LIKE "d%", itd. gdje će dobivati odgovor da korisnik ne postoji, sve dok ne pogodi točno prvo slovo, za koje će dobiti poruku pozdrava. Prvim pokretanjem skripte, pri korištenju vrijednosti LIKE "%d", dobiva se odgovor prikazan u slici ispod, što nam daje informaciju da je prvi znak passworda slovo //d//. {{blind_sql_7.png}} Nakon toga skripta će na isti način pokušavati pronaći drugi znak passworda, probavajući redom vrijednost LIKE „da%“, LIKE „db%“, LIKE „dc%“, itd. sve dok ne dobije poruku pozdrava, kojom će znati drugi znak passworda, pa će isto pokušati za treći znak passworda, pa za četvrti, itd. Važno je uzeti u obzir koji se sve znakovi mogu koristiti unutar passworda, pošto je iz koda vidljivo da se koristi hash algoritam SHA256, to znači da password nije u obliku običnog teksta, nego je ta vrijednost zapravo hashirana vrijednost passworda uz pomoć algoritma SHA256. Znakovi koji mogu biti prisutni u hash vrijednosti algoritma SHA256 su heksadekadski zapisi brojeva od 0 do 15, odnosno mala slova „abcdef“ i znamenke od 0 do 9. Izlazna vrijednost SHA256 hash algoritma jest uvijek iste duljine, odnosno fiksna je i sastoji se od 256 bitova, odnosno 32 bajta, odnosno zapis će biti duljine 64 znaka, gdje svaki znat predstavlja pola bajta, odnosno 4 bita. Prethodni algoritam možemo ponavljati za svaki znak passworda, dok ne pronađemo 64 znakova ili dok se ne isprobaju svi mogući znakovi na tom mjestu znaka passworda i za ni jedan se ne vrati poruka pozdrava, onda znamo da smo pronašli cijeli password. Primjer jednog Python programa kojim ostvarujemo prethodno definirani algoritam se može vidjeti u nastavku: import requests import sys #skripta za izvući username i hash iz baze uz pomoć blind sql injectiona URL_PREFIX = "http://chal.platforma.hacknite.hr:12009/reset.php?username=" payload= "sara' AND (SELECT password FROM users) LIKE '" charset_hash="0123456789abcdef" password_hash="" ponoviPetlju=True while ponoviPetlju: ponoviPetlju=False for char in charset_hash: URL = URL_PREFIX+payload+char+"%'--" response = requests.get(URL).text #Ako se rijec poslovnica nalazi u odgovoru, # znaci da smo dobili poruku pozdrava if "poslovnica" in response: password_hash+=char payload+=char ponoviPetlju=True break print(password_hash) Pokretanjem programa dobivamo hash vrijednost Sarine lozinke koja je d4120d4f638a4bdd0f397e975b71b117583f4fdb35c60aeb5416fa922651a465 Koristimo crackstation.net za dobivanje para vrijednosti koja hashiranjem algoritmom SHA256 daje dobiveni hash, te uspješno dobivamo vrijednost monitor123, što je lozinka korisnika Sara. Dobivanje reversa hasha od lozinke s pomoću crackstationa prikazano na slici ispod. {{blind_sql_8.png}} Sada se možemo uspješno ulogirati na formu admin portala s pomoću korisničkog imena //sara// i lozinke //monitor123//, ali nas nakon toga traži drugi faktor 2fa autentifikacije. Analizom koda vidimo da se sjednica uspostavlja odmah nakon uspješne prijave, a ne tek nakon uspješnog prolaska drugog faktora autentifikacije. To znači da možemo ručno promijeniti URL, tako da promijenimo //http://chal.platforma.hacknite.hr:12009/2fa.php// u //http://chal.platforma.hacknite.hr:12009// nakon čega imamo uspješno uspostavljenu sjednicu bez prolaska drugog faktora autentifikacije. Nakon toga možemo samo na izborniku odabrati admin portal, gdje se nalazi flag koji je rješenje zadatka.