Authentifizierung in PHP
Ein Mitgliederbereich findet sich auf den meisten Websites. Dieser Artikel gibt euch einige Tipps, wie ihr sowohl einen sicheren als auch benutzerfreundlichen Mitgliederbereich erhaltet und vor unangenehmen Überraschungen geschützt seid. In unserem Artikel Loginscript findet ihr ein einfaches Loginscript, das ihr für eure Webanwendung verwenden könnt.
Dieser Artikel stellt nun nur kurz und übersichtlich die Sicherheits- und Usability-Tipps zu den typischen Funktionen eines Mitgliederbereichs dar. Gerne könnt ihr es auch als Checkliste für euren internen Bereich nutzen.
Inhaltsverzeichnis
Sichere Registrierung
Für eine sichere Registrierung solltet ihr die folgenden Punkte beachten:
- Sicheres Abspeichern des Passworts: Das Passwort sollte niemals als Klartext versendet werden, sondern stets als Hashwert einer sicheren Funktion. Unser Artikel Passwörter sicher speichern hat weitere Informationen zu diesem Thema.
- Benutzername vs. E-Mail: Lange Zeit war es üblich, dass der Benutzer sich einen Benutzernamen ausgesucht hat und sich damit eingeloggt hat. Oder er musste sich mit der zugewiesene Kundennummer einloggen, so wie man es heute noch meistens bei Banken vorfindet. Durch die hohe Anzahl der verschiedenen Seiten bei denen man registriert ist, vergisst man schnell wie denn der Benutzername oder die Kundennummer war. Ich empfehle deswegen, ganz auf Benutzernamen & Co. zu verzichten und der Nutzer kann sich mittels seiner E-Mail-Adresse einloggen.
- Bestätigung der E-Mail-Adresse: Falls ihr für euren Dienst eine gültige E-Mail-Adresse benötigt, so solltet ihr dem Benutzer nach der Registrierung ein Link zum Bestätigen der E-Mail-Adresse zusenden. In diesem Link ist ein zufälliger Code als GET-Parameter enthalten. Nach Aufruf des Links vergleicht ihr den Code mit dem Wert den ihr in der Datenbank für den Nutzer hinterlegt habt und schaltet ihr frei.
- Keine Passwörter per E-Mail übersenden: Nach der Übertragung solltet ihr nicht das Passwort per E-Mail übertragen. Das versenden von E-Mails ist von der Sicherheit zu vergleichen mit dem Versenden von Postkarten und ihr würdet ja auch keine sensiblen Informationen per Postkarte versenden, oder?
- Passwort-Regeln: Viele Seiten erfordern vom Benutzer gewisse Mindestanforderungen an das Passwort, dass dieses beispielsweise mind. 8 Zeichen lang sein muss und Groß- sowie Kleinbuchstaben enthalten muss. Leider halten sich daran nur wenige Benutzer und finden dann meistens ein Weg um das System oder verlassen verärgert eure Seite. Persönlich würde ich keine Kriterien einbauen, man kann aber bei zu kurzen Passwörtern den Benutzer warnen, dass sein Passwort leicht zu knacken ist.
- Schutz vor Spam: Als Schutz gegen Spambots lassen sich sogenannte Captchas wie beispielsweise reCaptcha nutzen. Der Benutzer muss dazu eine schwer zu entziffernde Zahl- und Buchstabenfolge in euer System eingeben. Da die Bots aber immer intelligenter werden bringen diese Systeme kaum noch Schutz und nerven zumeist eure Benutzer. Sofern möglich sollte man also lieber auf Captchas verzichten.
- Geschützte Übertragung mittels HTTPs: Da bei der Registrierung oftmals sensible Daten enthalten sind, beispielsweise das Passwort, sollte der Registrierungsprozess mittels HTTPs ablaufen. Viele Webhoster bieten ein Zertifikat für wenige Euro im Monat an oder bieten eine alternative Adresse für die Übertragung an.
Sicherer Login
Für den sicheren und bequemen Login solltet ihr beachten:
- Login mittels E-Mail: Wie bei der Registrierung geschrieben, sollte der Benutzer sich aus Aspekten der Benutzerfreundlichkeit mittels der E-Mail Adresse einloggen können. Gerne auch weitere Login-Mechanismen wie die von Facebook, Google oder Twitter anbieten.
- Session Hijacking verhindern: Um Session Hijacking zu verhindern, solltet ihr nach der Überprüfung der E-Mail-Adresse und des Passworts die Funktion session_regenerate_id() aufrufen um so eine neue, frische Session ID zu erzwingen.
- Übertragung des Logins per HTTPs: Um neugierige Ohren abzuwehren sollte der Login mittels HTTPs sicher verschlüsselt übertragen werden. Immer mehr User sind mobil auf ihrem Smartphone unterwegs, dort ist die Absicherung der Übertragung meistens besonders schlecht.
- Anzahl der Login-Versuche überprüfen: Um Brute-Force-Attacken auf eure Mitgliederkonten zu vermeiden sollten fehlgeschlagene Logins protokolliert werden. Treten zu häufig fehlerhafte Logins auf, bietet es sich an die IP oder gar den Benutzer zu sperren. Aber Achtung, damit kann man auch schnell legitime Nutzer verprellen die ihr Passwort vergessen haben und verschiedene Kombinationen ausprobieren.
Sichere Passwort-Vergessen-Funktion
Sollte der Benutzer sein Passwort vergessen haben, empfiehlt sich der folgende Ablauf. Wie schon bei der Registrierung solltet ihr niemals einfach per E-Mail ein Passwort versenden.
- E-Mail mit zufälligem Code versenden: Hat der Benutzer sein Passwort vergessen, so gibt er bei euch seine E-Mail Adresse ein. Daraufhin generiert ihr einen zufälligen Code der nur eine begrenzte Zeit gültig ist, z.B. für 6 Stunden. Den Code und das Ablaufdatum schreibt ihr in die Datenbank, beispielsweise in die Nutzertabelle. Anschließend sendet ihr eine E-Mail an den Benutzer mit einem Link, der seine User-ID und diesen Code enthält und fordert ihn auf, diese Seite zu besuchen. Ihr solltet wenn jemand sein Passwort vergessen hat diesen Benutzer nicht sperren oder ihm direkt ein neues Passwort vergeben. Dies würde Spaßvögel einladen unschuldige Benutzer aus eurem System auszuschließen.
- Aufruf der Website: Nachdem der Benutzer seine E-Mail erhalten hat ruft dieser den Link auf und kommt auf eine spezielle Website. Dort kann er sein neues Passwort eingeben und danach direkt euer System nutzen.
- Optional: Geändertes Passwort bestätigen: Nachdem er das neue Passwort gesetzt habt, könnt ihr ihm nochmal eine E-Mail senden, dass sein Passwort geändert wurde. Aber wie schon bei der Registrierung solltet ihr das neue Passwort von ihm nicht per E-Mail versenden.
Für die Passwort-vergessen-Funktion solltet ihr tunlichst Abstand nehmen von den 'Passwort-vergessen-Fragen' o.ä. Diese sind ziemlich unsicher und lassen sich meistens leicht beantworten wenn man den Nutzer kennt.
Passwort und E-Mail Adresse ändern
Sofern ihr in eurem internen Bereich ein Möglichkeit anbietet das Passwort oder die E-Mail Adresse zu ändern, so solltet dies euer Benutzer nur nach erneuter Eingabe des Passworts machen können. Gerne vergisst man sich bei einem öffentlichen Rechner auszuloggen, der nächste Nutzer des PCs könnte dann das Passwort oder die E-Mail Adresse ändern und so dauerhaften Zugang erlangen. Dieser Rat gilt übrigens auch für alle weiteren sehr kritischen Aktionen die ein Benutzer durchführen könnte, beispielsweise um sein Konto zu löschen etc.
Nach der Änderung des Passworts bzw. der E-Mail Adresse solltet ihr noch eine entsprechende Benachrichtigungsemail an die alte und neue E-Mail-Adresse versenden.
Angemeldet bleiben-Funktion
Eine 'Angemeldet bleiben'-Funktion erhöht die Usability eurer Webanwendung, senkt aber auch die Sicherheit. Für besonders kritische Anwendungen solltet ihr deswegen auf diese verzichten.
Um diese möglichst sicher zu implementieren führt folgende Schritte aus (Implementierung für die Angemeldet bleiben Funktion:
- Bietet beim Login die Checkbox 'Angemeldet bleiben' an. Hat der Benutzer diese ausgewählt wird ein zusätzlicher Login-Cookie bei ihm abgespeichert.
- Erzeugt zwei sichere Codes, idealerweise mittels openssl_random_pseudo_bytes() , zur Not sonst mit uniqid() . Der erste Code ist der Identifier, der zweite der Securitytoken.
- Speichert in einer Tabelle die User-ID, den Identifier sowie den SHA-1 Wert des Securitytokens. Ihr könnt ebenfalls weitere Infos abspeichern wie beispielsweise das Erstellungsdatum o.ä.
- Beim Benutzer selbst wird der Identifier und der Securitytoken (als Klartext) als Cookie abgespeichert.
- Besucht der Nutzer eure Website erneut und ist noch nicht eingeloggt, so lest ihr aus dem Cookie den Identifier und den Securitytoken aus.
- Sollte der Identifier und Securitytoken zu den Daten in der Datenbank stimmen, so loggt ihr den Benutzer ein und erzeugt einen erneuten Securitytoken (den Identifier könnt ihr wiederverwenden). Der neue Securitytoken wird im Cookie und in der Datenbank aktualisiert.
- Passt der Securitytoken nicht zu dem Token in der Datenbank, so hat jemand höchst wahrscheinlich die Cookies beim Benutzer gestohlen. In diesem Fall könnt ihr euren Nutzer per E-Mail über den potentiellen Diebstahl warnen.
- Ist kein Identifier in den Cookies vorhanden oder passt zu keinem in der Datenbank, dann könnt ihr den Wert ignorieren.
Es kann nützlich sein, eine Möglichkeit dem Nutzer anzubieten alle Angemeldet-Bleiben-Cookies zu löschen. Löscht dazu die entsprechenden Einträge in der Tabelle. Manche Dienste löschen auch alle Einträge wenn der Benutzer sich bewusst für einen Logout entscheidet.
Administrationsbereich
Besonders kritisch ist oft der Administrationsbereich eurer Webanwendung. Hierfür solltet ihr zusätzliche Sicherheitsmaßnahmen vornehmen.
- Sicheres Passwort von Administratoren verlangen: Es gab bereits Fälle bei bekannten deutschen Firmen, dass ein Administrator das selbe Passwort bei allen Websites genutzt hatte. Ein Angreifer konnte von einer fremden Website das Passwort des Admins stehlen und loggte sich dann als Administrator ein und richtet großen Schaden für die Firma an (stahl u.A. alle Kundendaten). Deswegen solltet ihr verlangen, dass eure Administratoren ein sicheres Passwort (mind. 9 Zeichen) nutzen und es nirgendwo anders verwenden.
- Erneute Authentifizierung verlangen: Besitzt ihr einen User- und einen Administratorenbereich, wie das beispielsweise in Foren der Fall ist, sollte der Administrator das Passwort erneut eingeben müssen bevor er in den Admin-Bereich wechseln kann. Dies verhindert dass z.B. der Admin sich vergisst auszuloggen aus dem Benutzerbereich und eine fremde Person dann seine Session weiternutzt um Aktionen im Adminbereich durchzuführen.