SQL Injection

28
Univerzitet u Beogradu Fakultet Organizacionih Nauka Seminarski rad iz predmeta Zaštita računarskih sistema Naziv teme: SQL injection i zaštita od SQL injection-a

Transcript of SQL Injection

Page 1: SQL Injection

Univerzitet u Beogradu

Fakultet Organizacionih Nauka

Seminarski rad iz predmeta

Zaštita računarskih sistema

Naziv teme:

SQL injection i zaštita od SQL injection-a

Profesor: Dr Dejan Simić

Student: Panić Nenad, 137/05

Mart, 2012

Page 2: SQL Injection

Sadržaj

1. SQL injection..........................................................................................................................3

2. Vrste napada..........................................................................................................................4

2.1 Zaobilaženje autorizacije.................................................................................................4

2.2 Korišćenje SELECT naredbe..............................................................................................5

2.3 Korišćenje INSERT naredbe..............................................................................................7

2.4 Korišćenje SQL Server uskladištenih pocedura................................................................8

2.5 Napadi drugog reda.........................................................................................................9

3. Zaštita od SQL injection-a......................................................................................................10

3.1 Proveravati ulaz...............................................................................................................10

3.2 Zabraniti navodnike i escape znakove u ulazu.................................................................11

3.3 Koristiti ograničene paramete..........................................................................................13

3.4 Zaključavanje sistema.......................................................................................................14

3.5 Koristiti uskladištene procedure za pristup bazi podataka...............................................15

3.6 Izolovati web server..........................................................................................................17

3.7 Podesiti prijavljivanje grešaka...........................................................................................18

3.8 Enkripcija podataka...........................................................................................................20

4. Zaključak..................................................................................................................................20

5. Literatura.................................................................................................................................21

2

Page 3: SQL Injection

1. SQL Injection

SQL injekcija (engl. SQL injection) je tehnika koja eksploatiše sigurnosnu ranjivost koja se događa u sloju baze podataka aplikacije. Najčešće se eksploatišu web aplikacije koje u svojim SQL upitima koriste podatke koje je isporučio korisnik, ali bez prethodnog ispitivanja da li ti isti korisnički podaci sadrže neke potenijalno štetne znakove poput navodnika, tačke-zarez i sl.

SQL injekcija je tehnika koja se sastoji od upisivanja odgovarajućeg teksta u polja obrasca koja aplikacija koristi u svojim SQL upitima, tako da upiti iz baze vrate podatke koje inače ne bi. Ova metoda, kao i većina hakerskih postupaka, počiva na metodi pokušaja i grešaka i temelji se na pogađanju strukture SQL upita i imena atributa i tablica.

1.1 SQL injection

3

Page 4: SQL Injection

1.2 Web ranjivost za prvi i drugi kvartal 2009 godine

1. Vrste napada

2.1 Zaobilaženje autorizacije

Najjednostavnija tehnika SQL injekcije je zaobilaženje prijave (engl. logon form). Pogledajmo sledeći programski kod:

SQLQuery = "SELECT Username FROM Users                WHERE Username = ‘" & strUsername & "‘                AND Password = ‘" & strPassword & "‘" strAuthCheck = GetQueryResult(SQLQuery) If strAuthCheck = ""    Then boolAuthenticated = False 

4

Page 5: SQL Injection

   Else boolAuthenticated = True End If

Nakon što korisnik preda korisničko ime i lozinku ispituje se tabela Users da bi se saznalo da li postoji red sa tim korisničkim imenom i lozinkom. Ako je takav red pronađen, tada se korisničko ime upisuje u varijablu strAuthCheck, koja označava da je korisnik pravilno autentifikovan. Ako ne postoji red koji sadrži zadate korisničke podatke, strAuthCheck će biti prazan i korisnik se neće autentifikovati.

Ako strUsername i strPassword nemaju ograničenja, tj. mogu sadržati bilo kakve znakove, tada se može modifikovati struktura aktuelnog SQL upita tako da ''prođe'' autentifikaciju iako validno korisničko ime i lozinka nisu poznati. Primer:

Primer 1: Ukoliko korisnik ispuni polje korisničkog imena i lozinke obrasca sa podacima:

Login: ‘ OR ‘‘=‘ Password: ‘ OR ‘‘=‘

Gore naveden SQL upit će poprimiti sledeći oblik:

SELECT Username FROM Users WHERE Username = ‘‘ OR ‘‘=‘‘ AND Password = ‘‘ OR ‘‘=‘‘

Umesto da upoređujemo podatke koje je predao korisnik sa onima u tableli Users, upit upoređuje istinitost relacije ‘‘=‘‘, rezultat čega će naravno uvek biti istina. S obzirom da su svi uslovi, u WHERE delu SQL upita, zadovoljeni, aplikacija će odabrati korisničko ime iz prvog reda tabele koja se pretražuje (u ovom slučaju to je tabela Users). Izabrano korisničko ime će se pridružiti varijabli strAuthCheck koja će osigurati autentifikaciju.

2.2 Korišćenje SELECT naredbe

U nekim situacijama, treba na temelju povratne poruke koja opisuje grešku da primenimo obrnuti inžinjering na SQL upite koji su ranjivi. Da bi to učinili, moramo znati kako da protumačimo poruku koja opisuje grešku i kako u skladu s tim promeniti injection string.

Prva greška koja se obično sreće je sintaksna greška (engl. sintax error). Sintaksna greška označava da upit ne odgovara strukturi ispravnog SQL upita. Prva stvar koju moramo utvrditi je, da li je moguća injekcija bez izbegavanja navodnika, ako jeste radi se o direktnoj injekciji.

5

Page 6: SQL Injection

U slučaju direktne injekcije, koji god argument predamo koristiće se u SQL upitu bez ikakve izmene. Direktne vrednosti mogu biti numeričke vrednosti koje se koriste u WHERE delu upita ili argumenti SQL naredbe poput naziva tabele ili atributa tabele u bazi podataka. U svim ostalim slučajevima u injection string-u potrebno je koristiti navodnike.

SELECT naredba se koristi za uzimanje informacija iz baze podataka. Da bi naterali server da uzme druge zapise, osim onih koji su nameravani, potrebno je da se izmeni WHERE deo SQL upita tako da mu dodamo naredbu UNION SELECT koja će omogućiti da rezultat bude unija izvornog i novog SQL upita. Pretpostavimo da je zadata skripta sa sledećim programskim kodom:

SQLString = "SELECT Ime, Prezime FROM Zaposleni WHERE Grad = ‘" & strCity & "‘"

Ako koristimo injection string oblika:

‘ UNION ALL SELECT DrugiAtribut FROM DrugaTablela WHERE ‘‘=‘

Serveru baze podataka će biti poslat ovaj SQL upit:

SELECT Ime, Prezime FROM Zaposleni WHERE Grad = ‘‘ UNION ALL SELECT DrugiAtribut FROM DrugaTablela WHERE ‘‘=‘‘

Mehanizam baze podataka će pregledati tablelu Zaposleni tražeći red gde je atribut Grad postavljen na ''ništa''. Budući da ga neće pronaći, neće vratiti nikakve informacije. Jedine informacije koje će upit vratiti biće iz drugog, injektiranog SQL upita. U ovom primeru smo pretpostavili da ne postoji zaposleni koji nema vrednost atributa Grad. U nekim slučajevima ''ništa'' neće funkcionisati jer postoje zapisi u bazi koji koriste ''ništa'' u odgovarajućem atributu. U tom slučaju potrebno je samo upisati vrednost koja se ne pojavljuje u tabeli.

Neki serveri baze podataka vraćaju deo upita koji sadrži sintaksnu grešku. Zavisno od strukture upita, pojedini injektirani niz će uzeti korisne informacije, dok drugi neće.

Moguće je manipulisati injektirani upit tako da polako, ali sigurno, vrati željenu informaciju. To se postiže dodavanjem dodatnih uslova u WHERE deo upita koji će sprečiti odabir određenih redova tabele. Pretpostavimo da je početni injection string izgledao ovako:

‘ UNION ALL SELECT PrviAtribut, DrugiAtribut, TreciAtribut FROM Tabela WHERE ‘‘=‘

6

Page 7: SQL Injection

Neka je rezultat ovog upita 'prvi', 'drugi' i 'treci'. Sledeći injection string bi izgledao ovako:

‘ UNION ALL SELECT PrviAtribut, DrugiAtribut, TreciAtribut FROM Tabela WHERE PrviAtribut NOT IN (‘prvi’) AND DrugiAtribut NOT IN (‘drugi’) AND TreciAtribut NOT IN (‘treci’) AND ‘‘=‘

Deo NOT IN() osigurava da povratna informacija budu podaci koje još ne znamo (u ovom slučaju drugi red tabele Tabela).

2.3 Korišćenje INSERT naredbe

Naredba INSERT se koristi za dodavanje n-torki u bazu podataka. U Web aplikacijama se obično koristi za registraciju korisnika, dodavanje proizvoda u ''kolica'' pri online-kupovini i sl. Proveravanje ranjivosti sa INSERT naredbom je slično onom sa WHERE. Korišćenje ove naredbe nije preporučljivo ukoliko se želi izbeći detekcija napada.

Pretpostavimo da web stranica sadrži neku vrstu obrasca za registraciju, u kojoj je potrebno upisati ime, adresu, broj telefona itd. Nakon predaje obrasca, preusmeravamo se na stranicu koja prikazuje prosleđene podatke uz opciju izmene tih podataka ili nešto slično. Ovo je vrlo važno, jer da bi mogli iskoristiti INSERT ranjivost moramo videti prosleđene podatke. Nije važno u kom obliku.

Naredba INSERT ima ovakvu strukturu:

INSERT INTO Tabela VALUES (‘jedan’, ‘dva’, ‘tri’)

Ukoliko se želi manipulisati podacima koji su prosleđeni kao argumenti u VALUES delu naredbe, kako bi se dohvatili neki drugi podaci, potrebno je koristiti podupite. Primer:

SQLString = "INSERT INTO ImeTabele VALUES (‘" & strJedan & "‘, ‘" & strDva & "‘, ‘" & strTri & "‘)"

Ako ispunimo obrazac na sledeći način:

Name:‘+(SELECT TOP 1 ImeAtributa FROM ImeTabele)+‘

Email: [email protected] 

7

Page 8: SQL Injection

Broj_telefona: 333-333-3333

Dobićemo naredbu:

INSERT INTO ImeTabele VALUES (‘‘ + (SELECT TOP 1 ImeAtributa FROM ImeTabele) + ‘‘, ‘[email protected]’, ‘333-333-3333’)

Na stranici gde možemo videti prosleđene podatke, umesto imena pisaće vrednost atributa strJedan. Da nismo koristili TOP 1 u injection string-u, dobili bi poruku da je došlo do greške jer je podupit vratio previše redova. Da bi dohvatili ostale redove koristimo NOT IN().

2.4 Korišćenje SQL Server uskladištenih pocedura

Microsoft SQL Server instalacija ima više od 1000 uskladištenih procedura. Ukoliko napadač pokušava da upotrebi napad SQL injekcijom na Web aplikaciju koja koristi SQL Server, uskladištene procedure mogu se pokazati izuzetno korisnim. Zavisno od dozvola pristupa korisnika u bazi podataka koje koristi web aplikacija, neke, sve ili čak nijedna od tih pocedura se može koristi.

Injekcija pomoću uskladištenih procedura izgleda otprilike ovako:

simplequoted.asp?city=seattle’;

EXEC master.dbo.xp_cmdshell ‘cmd.exe dir c:

Na početku je dat validan argument, nakon njega sledi jednostruki navodnik i ;. Poslednji argument uskladištene procedure nema završni navodnik. Ovakav ulaz će zadovoljiti potrebe sintakse. Postoji mogućnost da će u ulazu biti potrebne zagrade ili dodatni WHERE uslovi i sl. ali nije potrebno brinuti o usklađenosti atributa ili tipova podataka.

master.dbo.xp_cmdshell je jedna od najznačajnijih uskladištenih procedura. Uzima samo jedan argument koji je naredba koju želimo da izvršimo na korisničkom nivou SQL Servera.

xp_cmdshell {‘command_string’} [, no_output]

Korisnik web aplikacije, međutim, gotovo nikad neće imati dozvolu za izvođenje ove uskladištene procedure.

Još jedna vrlo korisna procedura je master.dbo.sp_makewebtask:

8

Page 9: SQL Injection

sp_makewebtask[@outputfile=]‘outputfile’,[@query=] ‘query’

Argumenti ove procedure su izlazna datoteka i SQL upit. sp_makewebtask uzima zadati upit i kao rezultat daje web stranicu koja sadrži rezultat upita.

2.5 Napadi drugog reda

Napadi drugog reda - su oni napadi u kome podaci leže skriveni u bazi podataka sve dok se ne desi neki budući događaj. Često se dešava da kada su podaci u bazi podataka , oni se smatraju da su čisti i ne proveravaju se ponovo . Međutim, ti podaci se često koriste u upitima gde još uvek mogu da prouzrokuju štetu.

Zamislite aplikaciju koja dozvoljava korisnicima da podese neke omiljene kriterijume pretrage. Kada korisnik definiše parametre za pretragu , aplikacija poništava sve apostrofe , tako da se prvi napad ne može desiti kada se podaci za omiljenu pretragu ubacuju u bazu podataka . Međutim, kada korisnik dolazi da izvrši pretragu, podaci se preuzimaju iz baze podataka i koriste se da formiraju drugi upit koji zatim vrši stvarnu pretragu . Pa je ovaj drugi upit koji je žrtva napada.

Na primer. Ukoliko korisnik upiše sledeće kao kriterijum za pretragu:

'; DELETE Orders;--

Aplikacija uzima ovaj ulaz i poništava apostrofe , tako da konačna SQL naredba može izgledati ovako:

INSERT Favourites (UserID, FriendlyName, Criteria)

VALUES(123, 'My Attack', ''';DELETE Orders;--')

koji je ušao u bazu bez problema. Međutim, kada korisnik izabere svoju omiljenu pretragu, podaci se vraćaju aplikaciji, koja formira novu SQL komandu i izvršava je. Na primer, C# kod može izgledati ovako:

// Uzmi validno korisničko i prijateljsko ime omiljenog kriterijuma pretrage

int uid = this.GetUserID();

string friendlyName = this.GetFriendlyName();

9

Page 10: SQL Injection

// Napravi SQL upit za vraćanje kriterijuma za pretragu

string sql = string.Format("SELECT Criteria FROM Favourites" + "WHERE UserID={0} AND FriendlyName='{1}'",

uid, friendlyName);

SqlCommand cmd = new SqlCommand(sql, this.Connection);

string criteria = cmd.ExecuteScalar();

// Izvrši pretragu

sql = string.Format("SELECT * FROM Products WHERE ProductName = '{0}'", criteria);

SqlDataAdapter da = new SqlDataAdapter(sql, this.Connection);

da.Fill(this.productDataSet);

Drugi upit u bazu podataka , kada se potpuno proširi, izgleda ovako:

SELECT * FROM Products WHERE ProductName = ''; DELETE Orders;--

Neće vratiti očekivane rezultate upita, ali je kompanija upravo izgubila sve svoje porudžbine.

3. Zaštita od SQL injection-a

Ne postoji neki siguran način koji bi sprečio SQL injekciju, ali postoje načini da se smanji verovatnost njenog događanja. U nastavku su dati neki od tih načina.

3.1 Proveravati ulaz:

10

Page 11: SQL Injection

Vrlo je važno proveravati ulazne podatke koje je predao korisnik kako bi se osiguralo da ne sadrže opasne kôdove, bez obzira radi li se o SQL-u ili HTML-u. Umesto brisanja ''loših delova'', jer je verovatnost da ćemo se setiti svega što može da ugrozi sigurnost vrlo mala, preporučuje se brisanje svega osim ''dobrih delova''.

Koliko god je moguće izbegavati ulaz koji sadrži sledeće karaktere:

1) [ ; ] Graničnik upita2) [ ’ ] Graničnik karaktera data string-a3) [ -- ] Razdvajanje komentara4) [ /*...*/ ] Razdvajanje komentara. Tekst između /* i */ nije ocenjen od strane servera5) [ xp_ ] Koristi se na početku imena kataloški proširene uskladištene procedure, kao što

je xp_cmdshell

3.2 Zabraniti navodnike i escape znakove u ulazu:

Usprkos činjenici da lako možemo proveriti email ili telefonski broj, nije preporučljivo izbaciti navodnike iz polja imena zbog postojanja prezimena poput O'Reilly. Postoje alati koji vrše proveru da li su navodnici ''dobro napisani'' i koji povećavaju sigurnost, ali ne sprečavaju u potpunosti napad.

Jedan od tih alata se koristi u mysql-u:

$mysql = mysql_query ("SELECT * FROM `table` WHERE USER = ". mysql_real_escape($_POST['username']);

Metoda mysql_real_escape_string() se koristi za uklanjanje zlih znakova kod mysql-a.

Ali u nekim serverima ima jedna stvar koja može naškoditi korišćenju funkcije, a to je MagicQuotes. To je automatsko escape ugrađeno u PHP, ali je nesigurno i neefikasno. Zato je, na nekim serverima, potebno isključiti ovu opciju , ili koristiti sledeću funkciju:

function safe($value) {   if (get_magic_quotes_gpc()) //da li je magic quotes ukljucen      $value = stripslashes($value); //ako je, ponisti sta je napravio   if (!is_numeric($value)) //da li nije numericka vrjednost (dali je string?)     $value = "'" . mysql_real_escape_string($value) . "'"; //ako

11

Page 12: SQL Injection

je string, uradi escape   return $value;}

$mysql = mysql_query ("SELECT * FROM `table` WHERE USER = ". safe($_POST['username']);

Funkcija proverava da li je MagicQuotes uključen, ako jeste, poništava ga. Zatim proverava da li je string, ako jeste, onda može da se pozove metoda mysql_real_escape_string().

Primer u NET.Framework-u:

string surname= this.surnameTb.Text.Replace("'", "''");

string sql = "Update Users SET Surname='"+surname+"' "+

"WHERE id="+userID;

Prosta metoda zamene navodnika koja bi sprečila sve do sada navedene injekcione napade.

Međutim, u mnogim aplikacijama potrebno je da korisnik unese brojeve i onda nema potebe za prethodnom metodom. Ako aplikacija omogućava korisnicima da pregledaju svoje porudžbine po godinama, aplikacija može da izvrši neku SQL komandu ovako:

SELECT * FROM Orders WHERE DATEPART(YEAR, OrderDate) = 1996

Da bi aplikacija izvršila prethodnu komandu, C# kod za izgradnju SQL komande bi izgledao ovako:

string sql = "SELECT * FROM Orders WHERE DATEPART(YEAR, OrderDate) = " + this.orderYearTb.Text);

Onda postaje lako za ubrizgavanje koda u bazu. Sve što napadači treba da urade u ovom slučaju je da počnu svoj napad sa jednim brojem, onda ubacuju kod koji želite da pokrenu. Nešto otprilike ovako:

0; DELETE FROM Orders WHERE ID = 'competitor';--

Zato je imperativ da se ulaz od strane korisnika proverava da bi se utvrdilo da li je zaista broj , i da li je u važećem opsegu . Na primer :

string stringValue = orderYearTb.Text;

12

Page 13: SQL Injection

Regex re = new Regex(@"\D");

Match m = re.Match(someTextBox.Text);

if (m.Success)

{

// Ovo nije broj, uradi procesiranje greške.

}

else

{

int intValue = int.Parse(stringValue);

if ((intValue < 1990) || (intValue > DateTime.Now.Year))

{

// Ovo je izvan opsega, uradi procesiranje greške.

}

}

3.3 Koristiti ograničene parametre:

U slučaju ove metode zaštite SQL upiti sadrže prazna mesta koja su označena upitnikom i upit se prevodi u interni obrazac.

Parametri u SQL serveru omogućavaju proveru tipa i validaciju dužine promenljive. Ako koristimo parametre, ulaz se tretira kao doslovna vrednost, a ne kao izvršni kod. Dodatna pogodnost korišćenja parametara je da je moguće na silu sprovesti proveru tipa i dužine promenljive. Vrednosti izvan opsega će pokrenuti izuzetak. Sledeći deo koda pokazuje upotrebu parametara u ASP.NET-u:

SqlDataAdapter myCommand = new SqlDataAdapter("AuthorLogin", conn);

myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;

13

Page 14: SQL Injection

SqlParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);

parm.Value = Login.Text;

U ovom primeru, @au_id parametar se tretira kao doslovna vrednost umesto kao izvršni kod. Ova vrednost se proverava za tip i veličinu. Ako se vrednost @au_id ne pridržava navedenog ograničenja navedenog tipa i dužine, baca se izuzetak.

Dok se mnogi napadi drugog reda mogu sprečiti korišćenjem parametara, oni se mogu koristiti samo na mestima gde je dozvoljeno koristiti parametre u SQL izjavi. Aplikacija može da vrati rezultat promenljive veličine na osnovu preferencija korisnika. SQL izraz može uključiti TOP ključnu reč da bi se ograničio skup rezultata , međutim, u SQL Server 2000 , TOP može prihvatiti samo doslovne vrednosti tako da bi aplikacija morala da ubaci tu vrednost u SQL komandu da bi dobila tu funkcionalnost . Na primer:

string sql = string.Format("SELECT TOP {0} * FROM Products", numResults);

3.4 Zaključavanje sistema

Bezbednost je nešto što treba rešavati na mnogim nivoima , jer je lanac jak onoliko koliko je jaka njegova najslabija karika. Kada je korisnik u interakciji sa delom softvera , postoje mnoge karike u lancu , a ako je korisnik zlonameran , može pokušati da napadne ove veze da bi pronašao slabu tačku i pokušati da obori sistem. Imajući ovo u vidu , važno je da programer ne postane samouveren u vezi sigurnosti sistema, jer se lako može desiti da previdi značajne sigurnosne propuste koje mogu ugroziti ceo sistem.

Intranet sajt koji koristi Windows autentifikaciju i koji je smešten unutar korporativne mreže i nedostupan korisnicima Interneta može dati utisak da samo autorizovani korisnici pristupaju intranet web aplikaciji . Međutim , moguće je da ovlašćeni korisnik dobije neovlašćen pristup , ako se koristi samo ovaj vid bezbednosti . Neke statistike podržavaju predlog da većina narušavanja sigurnosti su insider poslovi, pre nego korisnici koji napadaju sistem spolja .

Imajući ovo u vidu , važno je da čak i ako aplikacija dozvoljava samo validne podatke, koje su pažljivo proverene i očišćene , da se upotrebe i ostale mere bezbednosti sistema. Ovo je posebno važno izmedju slojeva aplikacije u kojima možda postoji povećana šansa za pokušaje otimanja zahteva ili rezultata .

14

Page 15: SQL Injection

Na primer , ako web aplikacija zahteva da korisnik izabere datum , onda bi bilo normalno da su vrednosti za datum proverene u nekoj JavaScript funkciji na web stranici pre nego što bilo koji podatak bude prosleđen serveru . Ovo poboljšava korisničko iskustvo smanjujući čekanje između zahteva server. Međutim, vrednost treba da bude ponovo proverena na serveru, pošto je moguće poslati zahtev sa namerno napravljenim nevažećim datumom.

3.5 Koristiti uskladištene procedure za pristup bazi podataka

Uskladištene procedure dodaju dodatni sloj apstrakcije u projektu softverskog sistema . To znači da , dokle god interfejs na uskladištenoj proceduri ostaje isti, osnovna struktura tabele se može promeniti bez primetne posledice na aplikaciju koja koristi bazu podataka . Ovaj sloj apstrakcije takođe pomaže da bi se postavila dodatna prepreka potencijalnim napadačima . Ako je pristup podacima u SQL Serveru jedino dostupan preko uskladištenih procedura, onda nije potrebno eksplicitno postavljati odobrenje na bilo koje od tabela. Dakle , nijedna od tabela ne bi trebalo da ikada bude direktno izložena spoljnim aplikacijama. Da bi spoljašnja aplikacija mogla da čita ili modifikuje bazu podataka, mora proći kroz uskladištene procedure . Iako neke uskladištene procedure, ako se koriste nepravilno, potencijalno mogu da oštete bazu podataka, bilo šta što može da smanji površinu napada je korisno.

Uskladištene procedure mogu biti napisane da validuju bilo koji ulaz koji je poslat ka njima da bi se obezbedio integritet podataka izvan jednostavnog ograničenja koje imaju tabele. Parametri se mogu proveriti za validne opsege. Informacije se mogu unakrsno proveriti sa podacima u drugim tabelama .

Na primer, zamislite bazu podataka koja sadrži korisničke podatke za web sajt, to uključuje korisničko ime i lozinku . Važno je da napadač nije u mogućnosti da dobije listu lozinki ili čak jednu lozinku. Uskladištene procedure su tako dizajnirane da lozinka može biti ubačena , ali da nikada neće postaviti lozinku u bilo koji skup rezultata. Uskladištene procedure za registraciju i autentifikaciju korisnika za sajt mogu biti:

RegisterUser VerifyCredentials ChangePassword

RegisterUser preuzima korisničko ime i lozinku kao parametar ( eventualno zajedno sa ostalim informacijama koji su neophodni za registraciju na sajtu) i daje UserID.

VerifiCredentials se koristiti za logovanje na sajt prihvatanjem korisničkog imena i lozinke . Ako postoji podudaranje vraća se UserID, ako ne onda se vraća NULL vrednost.

15

Page 16: SQL Injection

ChangePassvord bi se koristio da uzme UserID, staru lozinku i novu lozinku . Ako se UserID i lozinka slažu, lozinka se može promeniti . Vrednost koja ukazuje na uspeh ili neuspeh se vraća.

Problemi sa uskladištenim procedurama:

Dok uskladištene procedure izgledaju kao odličan lek protiv injekcionih napada , to ne mora uvek biti slučaj . Kao što je pomenuto gore , važno je da validovati podatke i proveravati da li su ispravni. Međutim, izuzetno je važno da se provere podaci ako će uskladištena procedura da koristiti EXEC( neki_string ) gde je neki_string izgrađen na osnovu podataka i string literala koji formiraju novu komandu.

Na primer, ako uskladištene procedure treba da promene model podataka u bazi podataka , kao što je kreiranje tabele, kod može biti napisan ovako:

CREATE PROCEDURE dbo.CreateUserTable

@userName sysname

AS

EXEC('CREATE TABLE ' + @userName +

' (column1 varchar(100), column2 varchar(100))');

GO

Očigledno je da bez obzira šta @userName sadrži dodaće se CREATE izrazu. Napadač može ubrizgati u aplikaciju neki kod koji postavlja korisničko ime na:

a(c1 int); SHUTDOWN WITH NOWAIT;--

koja će odmah zaustavi SQL Server , bez čekanja na izvršavanje drugih zahteva.

Važno je da potvrdite unos kako bi se osiguralo da nema ilegalnih karaktera. Aplikacija se može podesiti da se osigura da razmaci nisu dozvoljeni kao deo korisničkog imena i ovo bi moglo da bude odbijeno pre nego što dođe do kreiranja CREATE izraza.

Ako će uskladištene procedure izgraditi SQL komandu baziranu na nekom postojećem objektu, kao što je tabela ili pogled, onda treba proveriti da li takav objekat postoji. Na primer:

CREATE PROCEDURE dbo.AlterUserTable

@userName sysname

AS

16

Page 17: SQL Injection

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES

WHERE TABLE_SCHEMA = 'dbo'

AND TABLE_TYPE = 'BASE TABLE'

AND TABLE_NAME = @userName)

BEGIN

// Tabela postoji

// Konstruiši odgovarajuće komande

END

GO

3.6 Izolovati web server

Potrebno je projektovati infrastrukturu mreže sa pretpostavkom da će napadač na neki način uspeti da dobije sve dozvole pristupa serveru, te je potrebno ograničiti načine da se to iskoristi da bi se iskompromitovalo nešto drugo.

Ako pokrećemo aplikaciju koja se povezuje sa bazom podataka koristeći administratorski nalog, napadač tada ima potencijal da obavi skoro neograničen broj komandi nad bazom podataka. Sve što administrator može da uradi , može da uradi i napadač.

Sledeći primer prikazuje kako napadač može doći do informacija koje se nalaze na hard disku servera:

Prva komanda se koristi da stvori privremenu tabelu u bazi podataka koja se puni sa nekim podacima. Sledeći injektovani kod će kreirati tabelu sa istom strukturom kao rezultat proširene uskladištene procedure koja će biti pozvana. Onda popunjava tabelu sa rezultatima proširene uskladištene procedure.

'; CREATE TABLE haxor(name varchar(255), mb_free int);

INSERT INTO haxor EXEC master..xp_fixeddrives;--

Drugi injekcioni napad služi da se dobiju podaci ponovo.

17

Page 18: SQL Injection

' UNION SELECT name, cast((mb_free) as varchar(10)), 1.0 FROM haxor;--

Ovo vraća ime diskova sa raspoloživim kapacitetima u megabajtima . Sada kada su poznata slova hard diskova, novi injekcioni napad se može dogoditi da bi saznali šta je na tim diskovima.

'; DROP TABLE haxor;CREATE TABLE haxor(line varchar(255) null);

INSERT INTO haxor EXEC master..xp_cmdshell 'dir /s c:\';--

I ponovo, drugi injekcioni napad se koristi da vrati podatke .

' UNION SELECT line, '', 1.0 FROM haxor;--

xp_cmdshell , po defaultu, je izvršna samo od strane korisnika sa sysadmin privilegijama , kao što su SA i CREATE TABLE je dostupna samo sysadmin , db_dbovner ili db_dlladmin korisnicima. Stoga je važno pokrenuti aplikaciju sa najmanje privilegija koje su neophodne kako bi se izvršile neophodne funkcije u aplikaciji.

Kada se instanca SQL Servera instalira na kompjuter, ona stvara servis koji radi u pozadini i obrađuje komande od aplikacija koje su povezane sa njim. Po podrazumevanoj vrednosti , ovaj servis je instaliran da koristiti Local System account . Ovo je najmoćniji nalog na Windows mašini , snažniji nego administratorski nalog.

Ukoliko napadač ima priliku da probije granice samog SQL Servera , kao na primer kroz duži postupak xp_cmdshell , onda su mogli da dobiju neograničen pristup mašini na kojoj je SQL Server.

Microsoft preporučuje da tokom instalacije SQL Servera, da se servisu da domen nalog koji ima dozvole da podesi samo neophodne resurse. Na taj način, napadač je ograničen dozvolama koja su potrebna da biste pokrenuli SQL Server.

3.7 Podesiti prijavljivanje grešaka

Standardne postavke prijave grešaka u nekim radnim okruženjima uključuju informacije o traženju grešaka u programu (engl. debugging).

Poruke o greškama su korisne za napadača , jer one daju dodatne informacije o bazi podataka koja ne mogu drugačije biti na raspolaganju . Često se misli da je korisno da se vrati poruka o

18

Page 19: SQL Injection

grešci korisniku ako nešto krene naopako , tako da ako problem postoji imaju neke korisne informacije da kažu tehničkom timu za podršku. Prijave će često imaju neki kod koji izgleda ovako:

try

{

// Neke operacije nad bazom podataka

}

catch(Exception e)

{ errorLabel.Text = string.Concat("Sorry, your request failed. If the problem persists please report the following message to technical support", Environment.Newline, e.Message);

}

Bolje rešenje koje ne ugrožava bezbednost bi bilo da se prikazuje generička poruka o grešci koja jednostavno navodi da je došlo do greške sa jedinstvenim ID-om . Jedinstveni ID nema nikakvo značenje za korisnika , ali će biti upisan u log fajl zajedno sa dijagnostifikovanom greškom na server, kome tim tehničke podrške ima pristup. Umesto gornjeg koda tebalo bi upisati nešto ovako:

try

{

// Neke operacije nad bazom podataka

}

catch(Exception e)

{

int id = ErrorLogger.LogException(e);

errorLabel.Text = string.Format("Sorry, your request Failed. "+

19

Page 20: SQL Injection

"If the problem persists please report error code {0} to the technical support team.", id);

}

3.8 Enkripcija podataka

Polazeći od stava da je napadač nekako uspeo da se probije kroz sve ostale odbrane, pitanje je: koje informacije su toliko osetljive da moraju da ostanu tajna? Kandidati za enkripciju uključuju User LogIn informacije ili finansijske informacije , kao što su detalji kreditnih kartica .

Za stavke kao što su lozinke , korisnikova lozinka može da se skladišti kao " salted hash " . Kada korisnik kreira lozinku, nasumično generisana " salt " vrednost se kreira od strane aplikacije i dodaje na lozinku , i onda generisana lozinka-salt vrednost se zatim provuče kroz jednu šifrovanu rutinu , kao što je HashPasswordForStoringInConfigFile method, metoda koja se nalazi u .NET Framework-u u pomoćnoj FormsAuthentication klasi. Rezultat je salted hash koji se čuva u bazi podataka , zajedno sa čistim salt stringom.

Vrednost salted hash je takva da dictionary attack neće raditi pošto bi svaki rečnik morao da bude obnovljen dodavanjem raznih salt vrednosti i recomputing hash vrednosti za svaku stavku. Iako je još uvek moguće odrediti lozinku brute force attack-om, upotreba salt ( iako je poznata ) u velikoj meri usporava proces . Druga prednost salt je da maskira svaku situaciju u kojoj dva nezavisna korisnika koriste istu lozinku, pošto će salted hash vrednost za svakog korisnika biti drugačija ako se daju različite salt vrednosti.

4. Zaključak

Šifrovanje osetljivih podataka Pristupiti bazi podataka koristeći nalog sa najmanjim privilegijama Instalirati bazu podataka koristeći nalog sa najmanjim privilegijama Uveriti se da su podaci validni Pregledati kod zbog mogućnosti napada drugog reda Koristiti parametre kod kreiranja upita Koristiti uskladištene procedure

20

Page 21: SQL Injection

Ponovo potvrditi podatke u uskladištenim procedurama Uveriti se da poruke o grešci ne daju nikakve informacije o unutrašnjo strukturi

aplikacije ili baze podataka

5. Literatura

1. http://www.spidynamics.com/papers/SQLInjectionWhitePaper.pdf

2. http://www.unixwiz.net/techtips/sql-injection.html

3. http://en.wikipedia.org/wiki/SQL_injection

4. http://php.net/manual/en/security.database.sql-injection.php

5. http://msdn.microsoft.com/en-us/library/ms161953.aspx

6. http://php.net/manual/en/function.mysql-real-escape-string.php

7. http://www.codeproject.com/Articles/9378/SQL-Injection-Attacks-and-Some-Tips-on-How-to-Prev

21