PHP je jedan od najpopularnijih jezika za razvoj dinamičkih web sajtova. Sama skraćenica PHP je rekurzivna i znači “PHP: Hypertext Preprocessor” – Prva reč “PHP” je skraćenica sa značenjem “PHP: Hypertext Preprocessor” i tako u nedogled …
Sledećih nekoliko nedelja ću predstavljati male savete za PHP programiranje. Neke od njih verovatno ste znali, neki će vam, nadam se, pomoći, a svaki je tek početak klupka koje možete da razmotavate dalje i iskoristite da poboljšate svoje PHP programerske veštine.
Prvi Savet: Sanitizacija prosleđenih promenljivih
Jedan od najopasnijih vidova napada na dinamički websajt je pokušaj prosleđivanja malicioznog SQL koda kroz promenljive koje se iz PHP-a prihvataju kroz GET ili POST – SQL injection
Ukratko, SQL injection radi tako što napadač pokušava da prevari vaš PHP kod da u SQL upit koji šaljete bazi podataka ubaci novi maliciozni deo SQL koda.
Najopštiji primer za SQL injection je ubacivanje dela SQL koda koji pokušava da obriše podatke iz baze:
$upit=”SELECT * FROM Zaposleni WHERE ZaposleniID=$IDZaposlenog”;
Ukoliko se u promenljivu $IDZaposlenog prosledi string:
$IDZaposlenog=”1; DELETE * FROM Zaposleni”;
Možete završiti sa ispražnjenom tabelom Zaposleni.
Izvor slike: xkcd
Sanitizacija podataka služi da se prosleđeni podaci iščiste od mogućeg malicioznog koda, a za samu sanitizaciju postoje razne metode i implementacije. Međutim, najsigurniji način da sprečite SQL injection je da koristite prepared statements i parametrizovane upite kroz mysqli ekstenziju koja je dostupna od PHP 5.0 http://php.net/manual/en/book.mysqli.php
Za gornji primer, parametrizovan upit bi izgledao:
$dbConn = new mysqli(“localhost”, “user”, “pass”, “baza”);
$statement = $dbConn->prepare(‘SELECT * FROM Zaposleni WHERE ZaposleniID= ?’);
$statement->bind_param(‘i’, $IDZaposlenog);
$statement->execute();
$result = $statement->get_result();
while ($row = $result->fetch_assoc()) {
// radimo nesto sa $row
}
U ovom primeru se $IDZaposlenog prosleđuje kao integer, ali i u slučaju da se parametar prosleđuje kao string (‘s’) opasnost od SQL injection-a je praktično otklonjena. Razlog za to je što se SQL kod šalje odvojeno od parametara i MySQL server ih po prijemu odvojeno obrađuje i spaja, čime se onemogućuje da se stringovi iz parametara interpretiraju kao SQL komanda.
Prepared statements mogu doneti i uštede u brzini u nekim slučajevima, ali to je druga tema.
Od PHP 5.2 je dostupna i filter ekstenzija koju možete koristiti za širu validaciju i sanitizaciju prosleđenih podataka i time sprečite i druge vidove proturanja malicioznih kodova:
http://www.php.net/manual/en/book.filter.php
Uvek imajte u vidu sanitizaciju podataka koje prihvatate kroz GET ili POST (REQUEST), a najsigurniji način odbrane od SQL injection-a je korišćenje prepared statements i parametrizovanih upita u poslednjem koraku.
Toliko za ovaj petak, nadam se da sam uspeo da vam dam ideje za polazne tačke od kojih možete nastaviti sa unapređenjem svojih PHP znanja i veština, vidimo se uskoro sa novim savetima i preporukama.
Ukoliko imate pitanja ili želite da podelite svoja iskustva i preporuke,
tvitamo se na @LimundoGradnja
Evo potpuno drugacijeg pristupa tom problemu, na jednom drugom blogu:
http://blogs.cisco.com/security/defending-against-sql-injection-attacks-using-cisco-asa-ips-and-ios-firewall-cisco-tac-security-podcast/
Naravno, ima i par finih resenja na slojevima izmedju.
Kako haker može da zna kako se zove moja tabela ?
Neobično koristan tekst za prosečnog Limundo korisnika!
postavite neki konkretan blog za trgovinu , zar ne vidite da nema nikakvod odaziva na ovaj blog ovo je promasena tema za 99 posto limundovaca
Super tekst, ali samo jos da nam objasnis kako da prosledimo promenjivu kao string 🙂
Ne razumem kakve ovo veze ima sa mojom numizmatikom i sa kupi,plati,posalji
@Shurdaa @ s.
Limundo je IT kompanija koja je do sada skupila dosta iskustva u oblasti programiranja i održavanja high performance okruženja.
U Srbiji su ipak retki sistemi veličine i zahtevnosti kakve imaju Limundo i Kupindo, te želimo da bar neka svoja iskustva podelimo sa delom zajednice koja je u IT branši, jer smatramo da će biti zanimljiva tom delu stručne javnosti.
Naravno, svesni smo da je to manji deo ukupne Limundo zajednice, te je stoga i broj IT članaka srazmerno manji u odnosu na članke koji se bave problematikom kupovine i prodaje 🙂
@dare
Cilj ovog članka nije bio da posluži kao uputstvo za hakerske napade, već da uputi na načine zaštite od njih, te stoga ne želim da previše ulazim u problematiku kako iskoristiti SQL injection propust jednom kada ga pronađeš.
Haker koji pronađe način za SQL injection može da dođe do različitih podataka, uključujući i nazive zanimljivih tabela.
Ja sam web programer vise od 10 godina, ali svakako ne vidim razlog da se ovakav blog objavljuje na ovakvom sajtu. Nekako bas zulja… Dobre namere, ali, promasena tema 🙂
Odlicno Miodraze, ja smatram ovo kao jedan pokusaj produhovljena…ja cu Vas pratiti jer me i tema interesuje…ako imate nalog na tviteru ili nam ostavite i mail za poneko pitanje…originalna ideja!
Sve je to lepo, ali kada smo vec pokrenuli ovu temu, nadam se da cemo da vodimo ozbiljan razgovor.I prema tome ja jos nisam dobio odgovor na moje pitanje? Mozda je tekst samo prepisan sa nekog foruma, sajta…cccc
Vrlo zanimljivo. Hvala!
IT crowd, evo od mene malkice plastičnijeg, opipljivijeg i realnijeg primera napada.
Primer uobičajenog upita:
$upit=”SELECT * FROM Zaposleni WHERE ImeZaposlenog=$ImeZaposlenog AND PrezimeZaposlenog=$PrezimeZaposlenog AND Grad=$Grad”;
SQL injection napad i to mnogo REALNIJI (uhvaćen) od prvog navedenog u postu:
$ImeZaposlenog=” xyz ‘ ; UPDATE Zaposleni SET Plata=111222333 ; –” ;
Promenljiva $ImeZaposlenog je napunjena iz Edit-polja i sada sadrži 6 tačaka koje čine jedan solidan napad:
1. prvi apostrof nakon xyz preseca SQL komandu i ne vraća nijedan red aplikaciji (niko se ne zove xyz, bar ne još)
2. potom, tačka-zarez je terminacija započetog upita, SQL kod mora da ostane i dalje korektan inače SQL transakcija ide u ROLLBACK i ništa od napada
3. potom ide maliciozni upit (upiši svim kolegama u firmi PLATA=111222333)
4. maliciozni upit završava sa tačka-zarezom, i dalje nam je konzistentan SQL kod
5. — (dva minusa) na kraju je oznaka zakomentarisanog SQL koda znače doslovce: “IGNORIŠI šta god da dolazi u SQL komandi nakon upotrebe promenljive $ImeZaposlenog ali održi konzistentnost cele SQL konstrukcije da se ne desi ROLLBACK i napad propadne”
Razlog što sam pomenuo ovaj primer je što je to mnogo realniji slučaj napada od navedenog prilično trivijalnog primera.
Lekovi:
1. Eliminišite apostrophe (‘) kao input karakter vašeg edit polja (SQL REPLACE ‘ sa ”).
2. Koristite SQL prepared statemente.
3. Koristite komponente (npr. Edit polja) koje u sebi imaju preventivne kontrole (SQL injection immune)
4. Pazite dobro šta će da vrati vaš sajt kao grešku – tipična ili generička bezvezna poruka o greški može da ukaže hakeru na detalj koji mu je potreban (Error in table Zaposleni: expected parameter is string).
5. Podesite LOGGING (get IP, HostName) i ALERTING da znate kada vas je neko pokušao “pecnuti” sa SQL injection kodom. Bez te dve stvari nećete ni znati da ste napadnuti.
Postoje free alati kojima date adresu websajta i koji će za nekoliko sekundi ili sati besomučno napasti svako Edit polje koje zateknu na stranicama – i to prilično uspešno. IBM ali i drugi vendori imaju komercijalne alate za website penetration ovog tipa. Navodno za white-hat, ali isto to je dostupno i za black-hat…
Najgore od svega je kada ste 100% sigurni u sebe da ste sve rupe začepili, ne smarate se sa logovanjem a kamoli čitanjem alerta i logova.
Ko još ima vremena i za logove?
🙂
Pa sta se desilo, krenula jedna tema petkom i tu smo stali?
Puna podrška za ovakav blog.
Iako sam iskusan web programer, i sve ovo znam, uvek je zanimljivo pročitati i podsetiti se nekih stvari.
Da ne pominjem da bi i ovima što se žale na tematiku bloga (a ko ih tera da čitaju?) bilo korisno da nešto pročitaju i nauče, ko zna, možda jednog dana sakupe dovoljno znanja da mogu da ga prodaju, pa da za novac kupe novčiće, salvetice ili zbog čega već dolaze na Limundo.
Dobijam poruku da ne mogu da pozivam nedefinisanu metodu get_result bla, bla… MySqlnd je ukljucen, sta li moze biti?
@ivan
Premalo je podataka da mogu da dam neki konkretan odgovor. Ali za pocetak proverite ipak da li je instaliran mysqlnd driver, da li je u php.ini ukljucena direktiva extension=php_mysqli_mysqlnd.dll, da li je PHP verzija bar 5.3