Authentifizierung die kein Vertrauen weckt

Authentifizierung richtig gemacht

Bildnachweis: (c) Annie Spratt

Das Thema Authentifizierung und Session-Management hat viele Aspekte, und es gibt viele potentielle Fehler, die gemacht werden können. Ich möchte mich hier deshalb zunächst nur auf die Authentifizierung beschränken.

1. Passworte sind nicht sicher gespeichert

Leider sehen wir das immer wieder: In einer Datenbanktabelle existiert ein Feld “password”, mit lesbarem Inhalt. Das darf natürlich gar nicht sein. Häufiger sehen wir Passworte, die mit md5 oder sha1 gehashed wurden. Das ist auch nicht sehr sicher. Denn oft reicht eine Google-Suche nach einem Hash, und am Ende findet man in irgendeiner Rainbowtable das gesuchte Passwort.

Maßnahmen

Ein Salt muss her. Vor PHP 5.5 haben wir dazu oft eine zweite Spalte “salt” gehabt, die pro User ein neuer Zufallswert ist. Dieser Salt wird an das Klartext-Passwort drangehängt und mitgehashed.

Mit PHP 5.5 gibt es eine schöne und einfache Password API. Sie soll laufend um neue Algorithmen erweitert werden, wenn bestehende sich als unsicher erweisen. Die API sorgt für größtmögliche Sicherheit.

$hash = password_hash("passwort", PASSWORD_DEFAULT);

Dieser Hash beinhaltet Informationen zum Algorithmus und zum Salt. Daher kann es einfach in ein Datenbankfeld geschrieben werden. PHP empfiehl das Feld 255 Zeichen groß zu machen.

Um ein Passwort zu überprüfen, reicht dann folgendes:

if (password_verify("passwort", $hash)) {
    echo "eingelogged";
} else {
    echo "falsches passwort!";
}

Auch, wenn diese Funktion nicht genutzt wird, würde ich empfehlen die Passwortprüfung nicht mit einem SQL in der Datenbank vorzunehmen, da hier durch SQL-Injection ein weiterer Angriffsvektor besteht.

Ich würde außerdem empfehlen nach jedem Login zu checken, ob der eingesetzte Hash noch sicher ist, und ob das Passwort neu gehashed werden sollte. Nach dem Login ist deswegen sinnvoll, weil wir das Klartext-Passwort vom User eben erhalten haben. Beispiel:

$hashInDb = "$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq";

if (password_verify($_POST['password'], $hashInDb)) {
    // Passwort stimmt!
    if (password_needs_rehash($hashInDb, PASSWORD_DEFAULT)) {
        $newHash = password_hash($_POST['password'], PASSWORD_DEFAULT);
        // in DB speichern
    }
} else {
    // ....
}

2. Passwörter können erraten werden

Die besten kryptographischen Ansätze bringen einem nichts, wenn einfache Passworte erlaubt werden. Verlangen Sie unbedingt starke Passworte.

Was ist stark? Darüber lässt sich streiten. Ich denke aber, eine Regel sollte mindestens so aussehen:

Mindestens 8 Zeichen, davon mindestens ein Groß- und ein Kleinbuchstabe, eine Ziffer und ein Sonderzeichen (z.B. _-.*()!§$%&#+).

Viele Frameworks bieten Funktionen zum Komplexitätscheck an, aber auch Google-Suchen nach “PHP password complexity check” liefern viele Ergebnisse.

Nicht zu viel preisgeben

Noch ein Gedanke: Das wissen über die Existenz eines Users eröffnet schon viele Möglichkeiten (z.B. Brute-Force-Attaken). Bei Loginformularen sollte bei Eingabe eines falschen Usernamens die selbe Fehlermeldung ausgegeben werden, wie bei der falschen Eingabe eines Passworts. Ebenso bei Passwort-Vergessen-Formularen: Dort immer eine Erfolgsmeldung ausgeben. So weiß keiner, welche User existieren.

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.