Beveiliging login
Ik heb even wat vragen over een inlogsysteem.
1) Ik wil het inlogsysteem zo beveiligen dat er maar 5 keer een foutief wachtwoord/username mag worden gegeven en dat de account dan geblokkeerd wordt voor een aantal minuten of pas gedeblokkeerd kan worden indien er een mail naar de gebruiker gaat.
Ik zat hierbij te denken aan een sessie waarbij het aantal keer inloggen met een username of ip geregistreerd wordt of in een database zetten hoe vaak er foutief ingelogd is. Maar omdat een ip kan veranderen is dat misschien niet zo handig. En als een hacker een username probeert te hacken en hij wordt geblokkeerd, kan hij toch gewoon doorgaan met een andere username? Wat is hiervoor de beste oplossing?
2) Mijn inlogsysteem maakt gebruik van sessions. Zijn deze nou geheel veilig of heb ik dan alsnog te maken met session hijacking? Ik heb een beetje gelezen op internet maar dan hebben ze het ook steeds over cookies en die gebruik ik niet. Een sessie is toch opgeslagen op de server en daar kan toch niemand bij?
Het aantal attempts op een inlogaccount houd je in de database bij met de datum van de laatste attempt. Als deze ouder is dan 5 minuten, dan weer 5 nieuwe attempts geven.
zolang je de gebruikersnaam en wachtwoord of het 'level' van de gebruiker niet in de sessie zet of iets als ingelogd = true; dan zijn sessies veilig, gebruik ze wel in combinatie met je database, en niet alleen maar.
-ip
-username
-timestamp
Bij het inloggen controleer ik of de laatste * minuten meer dan Y foute logins geweest zijn waarbij ip of username gelijk is aan het ingevulde. Is dat zo dan wordt het inloggen geblokkeerd.
Ook controleer ik of er meer dan * aantal foute logins voor een gebruiker zijn zonder een juiste login er tussen. Als dat zo is wordt het wachtwoord gereset en krijgt de gebruiker daar een mail van.
@Victor: Ik zet de username in de sessie omdat ik die dan kan weergeven op elke pagina. Dit is dus niet veilig begrijp ik? Hoe kan ik er dan voor zorgen dat op elke pagina de username staat en dat de sessies veilig zijn?
Kan iemand mij ook een goede uitleg geven wat session hijacking nou precies is, want het is me nog niet helemaal duidelijk.
@Aar en tjvb: Dus als ik het goed begrijp moet ik een nieuwe tabel aanmaken (b.v. login_attemps) en daarin opslaan per foutieve login: ip, username + timestamp. Dan moet ik als iemand in wil loggen de tabel controleren op aantal foute logins.
Is dit dan waterdicht?
Victor - op 13/07/2011 11:38:00:
zolang je de gebruikersnaam en wachtwoord of het 'level' van de gebruiker niet in de sessie zet of iets als ingelogd = true; dan zijn sessies veilig, gebruik ze wel in combinatie met je database, en niet alleen maar.
Dat is niet helemaal waar. Je kan er best inzetten dat de gebruiker ingelogd is of wat zijn username is. Wachtwoord lijkt me een beetje onzinnig. Sessie data staat op de server en kan niet door de gebruiker op wat voor manier dan ook aangepast worden (tenzij je er een GET of POST variabele of andere user input in opslaat natuurlijk). Zie ook http://www.webmasterworld.com/php/3371366.htm .
Het enige wat de gebruiker heeft is een Session ID, die opgeslagen wordt in een cookie. Session hijacking houdt in dat een hacker (bijvoorbeeld via een XSS aanval) de session id van een ander (laten we zeggen de admin) te weten komt. Als de hacker nu naar de website gaat met de Session ID van de admin dan is hij ook ingelogd. Wat je hieraan kan doen is (naast XSS voorkomen) is additionele gegevens van de gebruiker in de sessie bijhouden en controleren of deze nog steeds overeenkomen. Denk bijvoorbeeld aan het IP adres en de user agent. IP adres controle betekent wel dat als iemand bijvoorbeeld op zijn werk inlogt en hij neemt de laptop mee naar huis dat hij dan opnieuw in moet loggen.
Edit: ter aanvulling. Lees eens http://www.sitepoint.com/php-security-blunders/ en http://phpsec.org/projects/guide/4.html door.
Gewijzigd op 13/07/2011 14:10:49 door The Force
if (!preg_match("/^[0-9]{1,2}$/", $month)) die("Bad month, please re-enter.");
Wat is eigenlijk het voordeel (of niet?) van de bovengenoemde manier in plaats van het als volgt te doen:
if (!ctype_digit($month) || $month < 1 || $month > 12) die("Bad month, please re-enter.");
Weet iemand waarom je niet bij elke request een nieuwe SID zou maken dmv session_regenerate_id()?
@Pim: als je dit doet, wordt dan de ID in de cookie gewijzigd en de bestandsnaam van het sessie bestandje? Of wordt er een compleet nieuw sessie bestandje aangemaakt en blijft het oude sessie bestandje bestaan?
Ozzie PHP op 13/07/2011 17:43:43:
@Pim: als je dit doet, wordt dan de ID in de cookie gewijzigd en de bestandsnaam van het sessie bestandje? Of wordt er een compleet nieuw sessie bestandje aangemaakt en blijft het oude sessie bestandje bestaan?
De oude sessie blijft nog bestaan. Zie documentatie.
Dan heeft het wijzigen van de sessie_id niet zo veel zin lijkt me...
Kijk nu eens naar de documentatie. Vanaf PHP 5.1.0 kan je de oude laten weggooien en voor oudere versies van PHP zijn daar ook trucjes voor.
Oké, maar terugkomend op de vraag van Pim... dan denk ik dat je wel bij iedere request een nieuwe sessi_id zou kunnen laten genereren, maar dan moet je wel het oude sessie bestand weggooien. Lijkt me niet dat daar een nadeel aan zit. Het enige wat ik me kan bedenken is dat bij iedere pagina aanroep er dus een nieuw sessie bestand moet worden aangemaakt en het oude bestand moet worden weggegooid. Dit zal nadelig zijn voor de algehele performance van de website.