Professional Documents
Culture Documents
Sta Je Injection Baze
Sta Je Injection Baze
i komunikacione tehnologije
SQL injection
ali će se kao rezultat pojaviti sva vozila iz baze, jer taj upit uvek vraća
TRUE vrednost.
http://www.primer.com/proizvodi.php?kategorija=1&?proizvod=14
Kada vidite ovakav link, prilično lako je uočiti parametre koji se prosleđuju, a
to su u ovom primeru kategorija i proizvod.
Dovoljno je samo izmeniti vrednosti ovih parametara i pratiti šta se dešava.
Ukoliko dobijemo bilo kakvu grešku generisanu od strane baze podataka,
postoji velika verovatnoća da je to polje ranjivo na SQL injection.
Login napad
Napadi – primer 1
Neka je data forma za logovanje
Za prikazanu formu traži se unos
korektnih podataka, kako bi se pristupilo
nekom resursu za koji su potrebne
određene privilegije.
U ovom slučaju, potrebno je da imate korisničko ime i lozinku u sistemu.
Napadi – primer 1
<?php
//ucitavanje neophodnih podataka za komunikaciju sa bazom
include('connect.php');
//izvrsavanje upita
$rezultat = mysql_query($upit);
//$broj_redova oznacava broj redova vracenih od strane baze podataka za upit koji smo
// izvrsili ukoliko je upit uspesno izvrsen, rezultat nece biti 0
$broj_redova = mysql_num_rows($rezultat);
//provera uspesnosti
if ($broj_redova != 0){ echo 'Uspesno ste logovani!';}
else { echo 'Niste uneli ispravnu kombinaciju!';}
?>
Napadi – primer 1
Nakon unosa podataka u formu, dobijamo sledeći upit za bazu podataka
Napad
Problem kod ove skripte za login je to što se podaci uopšte ne proveravaju pre
prosleđivanja bazi podataka i korisnik može bez problema da unese dodatni SQL kod, kako
bi postigao željeni rezultat - tj. da se uloguje na sistem bez korektne kombinacije
korisničkog imena i lozinke.
Kod ovog slučaja ne moramo ništa upisati u prvo polje, a možemo i upisati bilo koji tekst,
a u polje za lozinku ćemo napisati ' OR '1'='1 i time potpuno premostiti login sistem.
Verovatno se pitate zbog čega smo uneli baš taj tekst, a objašnjenje je sledeće - Prilikom
unosa ' OR '1'='1 u polje za lozinku, formirao se sledeći upit
Pretraga-filtriranje napad
Napadi – primer 2
Neka je data forma za filtriranje
Unosom određene godine dobijamo
željene podatke o knjigama koje su izdate
posle godine koja je uneta.
-- html kod --
<?php
//provera da li je uneta godina izdanja. Ukoliko je uneta, taj broj se prosledjuje funkciji
za ucitavanje
if($_POST['godina'] != null) { UcitajKnjige($godina); }
else { UcitajKnjige(0); }
function UcitajKnjige($godina) {
include('connect.php');
$upit = "SELECT * FROM sql_injection.knjige WHERE godina_izdanja > $godina";
$rezultat = mysql_query($upit);
while($red = mysql_fetch_array($rezultat)) {
echo "<tr><td>" . $red['id'] . "</td> <td>" . $red['naziv'] . "</td> <td>" . $red['autor'] .
"</td> <td>" . $red['godina_izdanja’] . "</td></tr>\n"; }
}
?>
-- html kod --
Napad
Na ovom primeru će se objasniti jedna od najčešće korišćenih mogućnosti SQL
injection-a - UNION SELECT.
UNION SELECT predstavlja mogućnost SQL jezika da podatke koje smo već
dobili preko nekog upita sastavimo sa podacima iz novog upita.
Preduslov da UNION SELECT funkcioniše je to da drugi upit mora imati isti broj
kolona kao i prvi, a tipovi podataka drugog upita moraju se poklapati sa tipovima
podataka prvog.
Eksploatisanjem ove mogućnosti, maliciozni korisnik može da izvlači mnogo
podataka koji su običnom korisniku inače nedostupni.
"1999" predstavlja godinu za koju želimo podatke, a "UNION SELECT 1" pokušaj
pronalaska broja kolona. Ukoliko rezultuje greškom, znači da broj kolona nije 1.
1999 UNION SELECT 1, 2
Ukoliko i ovo rezultuje greškom, znači da broj kolona nije ni 2. Ovo
ponavljamo sve do trenutka kada se ne pojavi greška. U ovom primeru,
greška se nije pojavila kada je uneto:
Time smo dobili podatke svih korisnika, koje sada bez problema možemo koristiti
za logovanje.
Nakon unosa ovog teksta, u tabelu za izlistavanje knjiga bi se učitale sve knjige
koje su izdate nakon 1995. godine, a iz tabele korisnici bi se izbrisali svi podaci.
Napadi kroz primere
Prva stvar koja obično zanima napadača je korisničko ime, koje se može
izvući na jedan od sledećih načina:
SELECT user();
SELECT current_user;
SELECT file_priv FROM mysql.user WHERE user = 'username' --- MySQL 4/5
SELECT grantee,is_grantable FROM information_schema.user_privileges
WHERE privilege_type = 'file' AND grantee = 'username'
PHP ima dovoljan broj framework-a koje možete koristiti za pristup bazi
podataka. Tri najčešće korišćena su: mysqli, PEAR::MDB2 i PHP Data
Objects (PDO) i svaki ima mogućnost parametrizacije upita.
Parametrizovani SQL upiti
Primer za mysqli
Paket mysqli, dostupan sa PHP verzijom 5.x i omogućen za komunikaciju sa
MySQL 4.1 i novijim, je jedan od najčešće korišćenih interfejsa za bazu
podataka i omogućava parametrizovane upite upotrebom znaka pitanja za
ostavljanje mesta za dinamičku vrednost.
Validacija podataka
Validacija podataka
U prethodnoj celini je bilo reči o parametrizovanim upitima i njihovom uticaju
na smanjenje ranjivosti na SQL injection, ali nije samo to dovoljno kako bismo
bili sigurni da ranjivosti neće biti.
Jedna od najmoćnijih kontrola koju možete koristiti je validacija unetih
podataka.
'|%|--|;|/\*|\\\*|_|\[|@|xp_
U PHP-u možete koristiti mnoge funkcije za validaciju unetih podataka, uključujući sledeće:
Primer korišćenja preg_match funkcije za validaciju polja forme bi mogao biti sledeći:
$username = $_POST['username'];
if (!preg_match("/^[a-zA-Z]{8,12}$/D", $username)
{
// ovde ide kod koji se odnosi na loše unete podatke
}
Kodiranje podataka
Kao dodatak validaciji unetih podataka, često je neophodno da se kodira ono
što se prosleđuje između različitih modula ili delova aplikacije.
Čak i ako koristimo whitelist validaciju unosnih podataka, postoje slučajevi
kada je ' (apostrof) validan karakter za unos, a to može napraviti probleme pri
komunikaciji sa bazom.
U tim slučajevima se koriste funkcije za zamenu potencijalno opasnih
karaktera.
Apostrof treba zameniti sa dva apostrofa - '' ili sa \’.
PHP pruža funkciju mysql_real_escape_string($string) koja menja opasne
karaktere sa bezopasnim, kao što je navedeno.
Recimo da imamo sajt sa statistikom NBA igrača i da želimo da unesemo
podatke Shaquille O'Neal-a. To može izazvati problem, jer se u njegovom
prezimenu nalazi karakter ' koji je potpuno validan. Ova funkcija će njegovo
prezime zameniti u O\'Neal i to neće praviti nikakav problem pri komunikaciji
sa bazom.
Stvar na koju treba obratiti pažnju je dekodiranje vraćenih podataka, jer
korisniku sajta ne želimo da prikažemu prezime sa \ karakterom.
Dobre prakse pri razvoju aplikacije
Za svaku konekciju sa bazom koristite korisnika sa što manjim nivoom
pristupa koji je dovoljan da se izvrši upit - tj. ukoliko morate samo nešto da
pročitate iz baze, dozvolite samo READ privilegije tom korisniku.
Kada god je to moguće, koristite parametrizovane SQL upite ili stored
procedure.
Onemogućite prikazivanje grešaka putem baze podataka, jer to malicioznom
korisniku dosta govori.
Ne koristite očigledne nazive za imena tabela i kolona, kako biste što više
otežali upad slepim SQL injection-om.
Nikada nemojte čuvati šifre u bazi, već njihove hash-ovane vrednosti,
koristeći hash algoritam sa dobrom enkripcijom (poput SHA256).
Visoka škola strukovnih studija za informacione
i komunikacione tehnologije
SQL injection