A tartalomkezelő rendszerek, web alapú alkalmazások megbízhatósága szempontjából kulcsfontosságú kérdés a felhasználó biztonságos azonosítása. Azonosításra nem csak a bejelentkezéskor van szükség, hanem a védett környezetben való tartózkodás alatt folyamatosan, egészen addig, míg a felhasználó kijelentkezik és elhagyja az oldalt.
Cikkemben a biztonság szempontjából legfontosabb teendőket, támadási lehetőségeket próbáltam meg összeszedni. Ha a védekezés nem megfelelő szintű, akkor a weboldal nem képes a kívülről jövő támadásokat elhárítani vagyis feltörik, vírus fertőzés, adatszivárgás áldozata lesz.
Tartalomjegyzék
- Biztonságos jelszó
- Bejelentkezés captcha megoldások
- Bejelentkezés brute force támadás elleni védelem
- Beviteli mezők szűrése
- SQL injection elleni védelem
- Cross-Site Scripting (XSS) elleni védelem
- Jelszavak tárolása az adatbázisban
- MD5 kódolás problémák
- SESSION hijacking elleni védelem
- SESSION fixation elleni védelem
- Cross-Site Request Forgeries (CSRF) elleni védelem
- Include állományok
- Nem biztonságos PHP függvények
- Biztonságos kapcsolat
- Biztonságos átirányítások
- További olvasnivaló a weboldalak elleni támadások okairól
Biztonságos jelszó
A legtöbb felhasználó általában valamilyen könnyen megjegyezhető de nem biztonságos jelszót választ. Ezeket a jelszavakat az úgy nevezett "dictionary attack" vagy "brute force attack" eljárással könnyen ki lehet találni. Éppen ezért ha lehetőség van rá, a rendszer maga generáljon biztonságos jelszót a felhasználó részére és ne engedjük meg, hogy ezt kevésbé biztonságosra tudja változtatni.
Bejelentkezés captcha megoldások
A "brute force" támadások elleni védelem érdekében az első három bejelentkezési kísérlet után a rendszer egy captcha megoldással szűrje az automatizált támadási kísérleteket.
Bejelentkezés brute force támadás elleni védelem
Ugyanazzal a felhasználó névvel történő 3-5 db sikertelen próbálkozás után meghatározott időre tiltsuk le a bejelentkezést, naplózzuk a sikertelen kisérleteket.
A bejelentkezési folyamat lassítására iktassunk be 3-5 másodperces várakozást a login script-be. Ezzel csökkenthetjük az adott idő alatt lebonyolítható próbálkozások számát.
Beviteli mezők szűrése
Nem csak a login form-ban hanem az alkalmazásban mindenhol törekedni kell arra, hogy a beviteli mezőket hosszúság és adattípus szempontjából lekorlátozzuk. Ahol lehet használjunk legördülő listákat, a szöveges mezők esetén már HTML-ből korlátozzuk a karakterek számát.
SQL injection elleni védelem
Az SQL injection a leggyakoribb támadási mód. Ahol az SQL lekérdezésekbe közvetlenül változókat illesztünk be, ott ezeknek a változók tartalmának felülírásával a támadó információkat olvashat ki az adatbázisból, adatokat változtathat meg vagy törölhet.
Az SQL injection támadás ellen az input mezők tisztításával és a változók aposztrófok közé helyezésével védekezhetünk.
Íme egy példa az input mezők tisztítására:
function clean($str) {
$str = @trim($str);
if(get_magic_quotes_gpc()) { $str = stripslashes($str); }
return mysql_real_escape_string($str);
}
$username = clean($_POST['username']);
$password = clean($_POST['password']);
$check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = '".$username."' and Password = '".$password."'");
Cross-Site Scripting (XSS) elleni védelem
Az SQL injection-el ellentétben a támadó itt a bevitt adatok megjelenítés előtti hibás kezelésére apellál.
Például ha a felhasználó név beviteli mezőbe a támadó egy külső javascript állományra való HTML hivatkozást helyez és bármikor később a felhasználó nevet megjelenítjük az oldalon, azonnal lefut a korábban beillesztett támadó script. A nem megfelelően kezelt beviteli mezők segítségével HTML vagy Javascript kódot lehet futtatni az oldalon, amellyel login információkhoz, jelszavakhoz vagy szinte bármilyen egyéb információhoz hozzáférhetnek.
A megoldás a beviteli mezők tisztításában rejlik. A PHP-nek több beépített funkciója van erre a feladatra amelyeket nyugodtan használhatunk. Az egyik ilyen függvény a htmlspecialchars(), konkrét használata a következőképpen néz ki:
echo htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
Bővebben az XSS-ről: https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet
Jelszavak tárolása az adatbázisban
Az adatbázisban jelszavakat csak kódolt formában szabad tárolni!
Salt alkalmazásával javítható a jelszó biztonsága. A salt egy olyan karakter sorozat, amelyet a jelszó elejéhez vagy végéhez adva növeli annak biztonságát. A salt segítségével két azonos jelszónak a kódolt formája is eltérő lesz.
Bővebben: http://blackbe.lt/php-secure-sessions/
MD5 kódolás problémák
Az MD5 (és sha-1, sha-2) kódolás nem teljesen biztonságos, javasolt helyette az erősebb sha-256, sha-512-t használni.
SESSION hijacking elleni védelem
A Session Hijacking támadási mód ellen nem könnyű védekezni. Lényege, hogy a támadó különböző módszerek segítségével (pl. a kommunikációs csatorna lehallgatásával) megszerzi a session azonosítót. A Session ID birtokában már hozzá tud férni a bizalmas információkhoz.
Többfajta védekezi mód is létezik, az egyik legelterjedtebb a felhasználó IP címének és User Agent információjának a tárolása a session-ben természetesen kódolt és salt-al megtoldott formában. Ezen két információ folyamatos ellenőrzése megnehezíti az session id eltulajdonítását.
Bizonyos hálózatok és internet hozzáférések esetén problémát jelenthet a teljes IP cím eltárolása, ezért csak annak első három részét javasolt felhasználni:
$ip = '192.168.1.100'; // Minta IP cím
// Az eredeti IP címet vágja és ebben a formában adja vissza: XXX.XXX.XXX.0
function trimIP($ip) {
$pos = strrpos($ip, '.');
if ($pos !== false) { $ip = substr($ip, 0, $pos+1); }
return $ip . '.0';
}
$ip = trimIP($ip);
SESSION fixation elleni védelem
A Session Fixation esetén a gyanútlan felhasználó a támadó által választott session azonosítóval jelentkezik be. A bejelentkezés után a támadó a már jóváhagyott érvényes session ID-t használva úgy lép be a rendszerbe, mint maga a felhasználó.
A Session Fixation támadáshoz elégséges, ha a felhasználó egy alábbihoz hasonló linkre kattint: http://www.example.com/?PHPSESSID=1234
Védekezés: a session_regenerate_id() függvény minden kritikus művelet meghívása előtt egy új session azonosítóra cseréli a régit, így a támadó már nem fog tudni visszaélni az általa adott ID-vel.
Cross-Site Request Forgeries (CSRF) elleni védelem
A CSRF egy gyakori és veszélyes támadási módszer amelynek során a felhasználó észrevétlenül egy olyan kártékony script-et futtat, amely eltulajdonítja a bejelentkezési információkat.
A támadás általában úgy zajlik, hogy miután a felhasználó bejelentkezett egy weboldalra, egy ártatlannak tűnő linkre kattint, amely egy olyan weboldalra irányítja, ahol visszaélnek az adataival.
A CSRF támadásokat általában GET és POST hívásokkal hajtják végre. Védekezni többféleképpen lehet ellenük:
A GET eljárások helyett használjuk a biztonságosabb POST-ot.
Az űrlapok megjelenítése előtt javasolt egy random string-et (token) generálni, elmenteni a session-be, majd ugyanezt a string-et a form egy rejtett mezőjébe is beilleszteni. A form elküldése után a session-ban lévő token-t összehasonlítva a rejtett mező tartalmával azonosíthatjuk biztonságosan az oldalt.
Include állományok
Az include állományokat javasolt minden esetben a web-root mappán kívülre, egy nem hagyományos nevű könyvtárba rakni.
Az include állományoknak semmiképpen se legyen .inc a kiterjesztésük, hanem .inc.php, hogy php fájlként fussanak le, ne pedig txt fájlként, mert utóbbi esetben azonnal megjelenik a bennük tárolt információ!
Javasolt minden include mappába egy üres index.html fájlt rakni, hogy ez fusson le, ha mégis valaki böngészné az adott útvonalat.
A szerveren a directory listing (.htaccess vagy httpd.conf-ban) legyen minden esetben kikapcsolva!
Nem biztonságos PHP függvények
Kerüld a biztonság szempontjából kockázatos PHP függvények használatát, ezek közül kiemelten a következőket:
eval()
ini_set()
exec()
fopen()
popen()
passthru()
readfile()
file()
shell_exec()
system()
Biztonságos kapcsolat
A webes alkalmazás és a benne tárolt felhasználó adatok biztonsága szempontjából megfontolandó az SSL protokoll használata, amely egy titkosított kommunikációs csatornát biztosít a felhasználó számítógépe és a szerver között.
Biztonságos átirányítások
Az alábbi példa egy biztonságos átirányítást valósít meg. A die() nélkül a php kód további része is lefut annak ellenére, hogy a böngészőben nem jelenik meg. A hacker-ek ennek ellenére látni fogják.
header("location: index.php");
die();
További olvasnivaló a weboldalak elleni támadások okairól
A weboldalak illetve tartalomkezelő rendszerek elleni támadási okokról, típusokról és elhárításukról született egy részletes cikkem, javaslom elolvasni!