Biztonság: SQL Injection és Jelszavak

Egy hacker SQL Injection támadást hajt végre egy bejelentkezési űrlapon

Elérkeztünk a webfejlesztés legkritikusabb pontjához. Ha az eddig tanult módszerekkel (HTML űrlapok + PHP + SQL) összeraksz egy bejelentkezési rendszert, a weboldalad körülbelül 5 perc alatt fogják feltörni a hackerek. A leggyakoribb és legpusztítóbb támadási forma az SQL Injection (SQL Befecskendezés).

Mi az az SQL Injection?

Képzeld el, hogy van egy bejelentkezési űrlapod, ami bekéri a felhasználó email címét, és a PHP kódod így néz ki (SOHA NE ÍRJ ILYET!):

// ÉLETVESZÉLYES KÓD!
$email = $_POST['email'];
$sql = "SELECT * FROM felhasznalok WHERE email = '" . $email . "'";
$kapcsolat->query($sql);

Mi történik, ha a hacker az email címe helyett ezt írja be az űrlapba: ' OR 1=1 -- ?

A PHP vakon behelyettesíti ezt a szöveget az SQL parancsba, ami így fog kinézni:

SELECT * FROM felhasznalok WHERE email = '' OR 1=1 --'

Az adatbázis lefuttatja a parancsot: "Keresd meg azt a felhasználót, akinek üres az email címe, VAGY ahol 1 egyenlő 1-gyel". Mivel az 1 mindig egyenlő 1-gyel, a feltétel minden felhasználóra igaz lesz. A hacker jelszó nélkül, azonnal megkapja az adminisztrátori hozzáférést, és letöltheti a teljes ügyfélbázisodat.

A Megoldás: Prepared Statements (Előkészített lekérdezések)

A PDO zsenialitása, hogy beépített védelmet nyújt ez ellen. Soha nem fűzzük bele a felhasználó adatát közvetlenül az SQL parancsba. Ehelyett "helyőrzőket" (kérdőjeleket vagy neveket) használunk, és a PDO a háttérben ártalmatlanítja (kivédi) a kártékony kódokat.

// A BIZTONSÁGOS MÓDSZER
$email = $_POST['email'];

// 1. Előkészítjük a parancsot egy helyőrzővel (:email)
$sql = "SELECT * FROM felhasznalok WHERE email = :email";
$parancs = $kapcsolat->prepare($sql);

// 2. Biztonságosan hozzákötjük az adatot a helyőrzőhöz, majd lefuttatjuk
$parancs->execute(['email' => $email]);
$felhasznalo = $parancs->fetch();

Jelszavak tárolása: Soha ne mentsd el sima szövegként!

Ha belenézel egy profi adatbázisba, soha nem fogod látni a felhasználók jelszavait (pl. "titkos123"). Ha a szervert feltörik, a hackerek azonnal megkapnák mindenki jelszavát. Ehelyett a jelszavakat titkosítani (Hash-elni) kell mentés előtt.

A PHP erre a password_hash() függvényt biztosítja, ami egy visszafejthetetlen, 60 karakteres karaktersorozatot csinál a jelszóból.

// Regisztrációkor így mentjük el a jelszót:
$titkositott_jelszo = password_hash("titkos123", PASSWORD_DEFAULT);
// Eredmény: $2y$10$Q8... (Ezt mentjük az adatbázisba)

// Bejelentkezéskor így ellenőrizzük:
if (password_verify("titkos123", $titkositott_jelszo)) {
    echo "Sikeres bejelentkezés!";
}
← Előző lecke