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ó

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!