SQL Injection
Egyik kedvenc hibám, lévén igen sokan elkövetik. De végül is mi is ez? Elég egyszerű!
A weboldalakon általában két fő hibát követnek el, ami ilyen kihasználható biztonsági rést jelenthet:
Nézzük, mit is jelentenek ezek!
Amennyiben közvetlenül a query stringből rakunk adatot egy SQL utasításba, akkor ezek a hibák igen könnyen előfordulhatnak.
Nem szűrt speciális karakterek
Az SQL szintaxisban vannak speciális karakterek, amelyeket ha szűrés nélkül rakunk be a lekérdezés stringjébe, teljesen megváltoztatható annak működése.
Vegyünk egy példát!
Tegyük fel, hogy PHP-ban dolgozunk, és a következő lekérdezésből tudjuk meg, hogy sikerül-e loginolnia a usernek:
$query = "SELECT * FROM USERS WHERE user_name = '".$_POST["user_name"]."' AND password='".md5($_POST["password"])."';";
Csodálatos, kivéve, ha pl. a username mezőbe ezt írjuk be: admin'--
Így a $query erteke: "SELECT * FROM USERS WHERE user_name = 'admin' --' AND password=......"
Itt látható, hogy az aposztróf ('), mint speciális karakter szűrésének hiányaval a jelszóellenőrzést gyakorlatilag megkerültük, ha a -- egy kommentet jelent a DB számára. Persze, lehet meg néhány módon ezzel játszani, de azt hiszem a lényeg érthető: az SQL szintaxisban szereplő speciális karaktereket mindig ki kell escape-elni.
Helytelen típuskezelés
A másik jellemző hiba, hogy - és ismét PHP-s példát hozok - ha a programozási nyelv nem erősen típusos, akkor attól, hogy pl. szám típust várunk egy változóba, még lehet benne egészen más. Egy élő példa erre egy GET string, amit egy webshopban fedeztem fel:
http://........hu/index.php?mod=1&man=1 UNION SELECT user_name,password, user_name, email, email FROM users--
Itt a komment sem escapelődött ki, bár az nem sok mindenen változtat, csak egyszerűbb az élet, mert nem kell figyelni a helyes lezárasra a kedves vizsgálódó kollégának :)
Itt a man paraméter az érdekes. Ez a paraméter számokat várt, de a PHP nem erősen típusos, így simán szövegként értelmeződött, mivel az oldal készitője elmulasztotta a típust ellenőrizni. Ez az oldalrészlet amúgy kilistázott árukat, így a listába sikerült belevenni a felhasználóneveket, e-maileket és jelszavakat is. Innentől kezdve pedig gyakorlatilag az oldal összes felhasználónevét és jelszavát ismerjük (az MD5-ös jelszavak természetesen nem nyújtanak védelmet...).
Mit tehetünk akkor?
Figyeljünk, és teszteljünk! Abban az esetben, ha kézzel állítjuk össze az SQL lekérdezéseket, ez mindig komoly veszélyt jelent. Használjunk valamiféle ORM-et (Object Relational Mapping), ami megkímel minket az SQL utasítások hekkelésétől, esetlegesen automatikusan tudja is validálni a kapott adatokat, így megóv az ilyen jellegű támadásoktól. Persze ha szükség van esetlegesen a közvetlen SQL utasítások sebességére, ott vannak a prepared statement-ek.
Amennyiben mégis a kézi összeállítású SQL utasítások mellett döntünk, mindenképp escapeljük a szöveges adatokat (pl. mysql_real_escape_string), illetve végezzünk típusellenőrzést (pl. intval).
Ez nagy odafigyelést igényel a programozás során, de természetesen erre is vannak kész megoldások. Minek ilyenekkel vacakolni, ha már más megírta helyettünk, nem igaz?