Webtechnologien Sommersemester 2019

Authentifizierung mit PHP

Irgendwann steht jeder mal vor der Aufgabe, Login-Funktionalität o.ä. zu implementieren. Ziel dieser Seite ist deshalb, einen Überblick und Startpunkt zu diesem Thema zu bieten. Schauen wir uns zuerst die Begrifflichkeiten an:

Authentisierung ist auf drei Wegen möglich:

Nachweis Verb Beispiel
Kenntnis einer Information weiß etwas Passwort
Verwendung eines Besitztums hat etwas Schlüssel
Gegenwart des Benutzers selbst ist etwas biometrisches Merkmal

Umgang mit Passwörtern

Hier soll es primär um Kenntnis in Form von Zugangsdaten gehen: Ein Benutzer hat einen öffentlich bekannten Benutzernamen und ein geheimes Passwort. Möchte er sich authentisieren, übergibt er beides an einen Server und dieser erlaubt oder verweigert den Zugang.

Hashing und Brute Force

Eine der grundlegenden Regeln im Umgang mit Zugangsdaten ist, Passwörter niemals als Klartext zu speichern. Aus dem simplen Grund, dass sie gestohlen werden könnten.

Gängige Praxis ist es deshalb, kryptologische Hashfunktionen zu verwenden, um reproduzierbare Abbildungen der Passwörter zu erstellen, die sich nicht zurückrechnen lassen. Es gibt in diesem Bereich viele Algorithmen mit unterschiedlichen Stärken und Schwächen. Weit verbreitet sind beispielsweise MD5 oder SHA1, die sehr performant sind und sich damit auch zum Hashen größerer Dateien eignen.

Aber genau diese Performance wollen wir bei Zugangsdaten nicht. Denn gelangt ein Angreifer an den Hash eines Passworts, ist es mit moderner Hardware in realistischer Zeit möglich, den dazugehörigen Wert per Brute-Force-Angriff zu finden.1

Aufwändiges Hashen

Aus diesem Grund wurden Algorithmen zum Speichern von Passwörtern entwickelt, die absichtlich langsam sind, beispielsweise PBKDF2, bcrypt und scrypt (Nachtrag: mittlerweile wird Argon2 empfohlen). Ihre Langsamkeit fällt in Relation zu anderen Faktoren (Data Sanitization, Datenbankabfragen, Paketumlaufzeit) nicht ins Gewicht – vor allem, da im Normalfall nur eine Berechnung durchgeführt wird. (hash($pw) == $hash). Brute-Force-Angriffe hingegen werden enorm erschwert – auch, da z.B. bcrypt einen einstellbaren Kostenfaktor hat, der sich auch nachträglich noch erhöhen lässt.

Rainbow Tables

Da Zeit – gerade was das Knacken von Passwörtern angeht – häufig wertvoller ist als Speicher (Time-Memory Tradeoff) und um Brute-Force-Attacken zu erleichtern, werden von IT-Forensikern und Crackern sogenannte Rainbow Tables verwendet. Dabei handelt es sich letztlich einfach um eine große Datenbank vorberechneter Hash-Werte. Der vielleicht größte Verwalter dieser Tabellen ist Google. Haben Sie den MD5-Hash eines Passworts gefunden, reicht eine einfache Suche, bspw: google.de/search?q=a2b0ef405bae8278b51270241c4084c5.

Salz und Pfeffer

Um sich dagegen zu wehren, gibt es mehrere Möglichkeiten, z.B. paternalistisch, durch das Erzwingen längerer Passwörter. Oder durch eine technische Lösung wie das Salzen (engl. salt). Dabei wird dem Passwort vor dem Hashen eine nur intern bekannte Zeichenfolge beigefügt und danach beides gespeichert.

Salting

Beim Login wird dann der Salt ausgelesen, zusammen mit dem Passwort gehasht und mit dem Soll-Hash verglichen.

Handelt es sich um eine geheime Zeichenfolge, die nicht mit dem Passwort sondern z.B. im Programmcode gespeichert wird, nennt sich der Prozess Pfeffern (engl. pepper). Der Vorteil ist, dass Angreifern der alleinige Zugang zur Datenbank nichts nützt. Beide Methoden lassen sich kombinieren und schützen auch vor Wörterbuch-Angriffen.

Verzögerung

Ein zweiter technischer Weg ist die künstliche Verzögerung des Einloggens. Versucht sich beispielsweise ein Benutzer alle 100ms einzuloggen, stimmt da wahrscheinlich etwas nicht. Eine Art, damit umzugehen, orientiert sich am Exponential-Backoff-Algorithmus, wobei mit jedem Anmeldeversuch eine größer werdende Verzögerung eingebaut wird. Wer also viermal ein falsches Passwort eingegeben hat, kann auch ruhig mal zwei Sekunden warten. Apples iOS nutzt das beispielsweise bei Eingabe zu vieler falscher PINs.

Cookies

Da HTTP zustandslos ist, müssten wir uns mit jeder Anfrage neu authentisieren. Um das komfortabler zu machen, hat Netscape vor langer Zeit das Konzept der Magic Cookies auf das Web übertragen. Bei Cookies handelt es sich um einen Token – ähnlich dem an der Garderobe im Theater – der in Textform an den Client übergeben wird. Der speichert den Cookie und schickt ihn danach bei jeder HTTP-Anfrage mit.

Wer den Token hat, hat den Zugang. Und wie jeder Token, können auch Cookies geklaut werden. Zwei einfache Möglichkeiten, das zu erschweren, sind die Flags secure und HttpOnly. Diese sorgen dafür, dass Cookies nur über HTTPS übertragen werden und nicht per JavaScript gelesen oder verändert werden können.

Des Weiteren ist es ratsam, niemals wichtige Daten im Cookie zu speichern. Stattdessen sollten sie auf dem Server bleiben und durch den Token im Cookie identifiziert werden.

Zugangsverwaltung

Nun kommt es vor, dass Benutzer ihr Passwort vergessen. Da wir es gehasht haben, um zu verhindern, dass es in unbefugte Hände gelangt und es eh nicht über Kanäle versenden würden, deren Sicherheit wir nicht gewährleisten können, können wir es den Nutzer nicht zuschicken.

Gängige Praxis ist es, sich vom Besucher eine E-Mail-Adresse geben zu lassen und wenn es einen Account zu dieser gibt, ihm dahin eine Mail mit einem sogenannten Reset-Link zu schicken. Über diesen kann das aktuelle Passwort durch ein neues ersetzt werden.

Wichtig ist auch, wie damit umgegangen wird, wenn es zu einer Adresse keinen Account gibt oder das eingegebene Passwort nicht stimmt. Denn die Krux bei der Fehlerbehandlung in diesem Bereich ist, dass wir ehrliche Benutzer unterstützen wollen, ohne auch Angreifern einen Vorteil zu verschaffen. Die Meldung “Falsches Passwort” hilft, das fehlerhafte Eingabefeld zu finden, gibt einem Angreifer aber einen Hinweis darauf, dass es überhaupt einen Account zu dieser E-Mail-Adresse gibt. Und das vielleicht bei einer Seite, bei der man für den Besitz eines Accounts in Erklärungsnot geraten könnte.

Diverses

Zu guter Letzt noch ein paar wichtige Stichpunkte:

XKCD 936 – Password Strength

Wer mehr wissen möchte


  1. Es finden sich verschiedene Zahlen, nach denen moderne Grafikkarten 1 – 10 Milliarden MD5-Hash-Berechnungen pro Sekunde erreichen. Letztlich ergibt sich die benötigte Dauer zum Knacken aus Passwortlänge und Zeichenraum. Ein zehnstelliges Passwort aus Kleinbuchstaben ist aber mit Standardhardware an einem Tag zu schaffen.