28 Beiträge rss

PHP: Sicherer Login mit MD5

Soll eine Website nicht allen Benutzern offen stehen, muss eine Anmeldung mit Usernamen und Passwort geschaffen werden. Lesen Sie, wie man per PHP einen eigenen Login schafft, der das vom Benutzer eingegebene Kennwort nicht im Klartext über das Netz schickt.

(Erschienen in der "Linux professionell 1/2005")

Eine Zugangskontrolle per Name und Kennwort für ein Internet-Angebot ist schnell eingerichtet. Dazu muss man bei der Verwendung von apache als Webserver nur einen Eintrag in der Kontrolldatei .htaccess anlegen der die so genannte "Basic Authentication" aktiviert und dem System die erlaubten Benutzerkennungen mitteilen. Auf dem Browser erscheint dann der typische Login-Screen, wo der Surfer seine Anmeldedaten eingeben muss, bevor der Zugang freigeschaltet wird.

Diese Authentifizierung ist schnell eingerichtet, lässt aber keinerlei Freiraum für Individualität. Sobald weitere Felder gefordert sind oder die Logik erweitert werden soll, müssen Sie ein eigenes Formular bauen. Über den Inputfeld-Typ "password" lässt sich dabei dann zwar die Benutzereingabe am Bildschirm verschleiern, aber beim Absenden des Formulars wird das Kennwort ungeschützt über die Datenleitung geschickt. Dagegen hilft der Einsatz des Algorithmus MD5.

Mehr als nur Quersummen

Die Methode MD5 bietet eine gute Möglichkeit, Checksummen von beliebigen Eingabedaten zu machen. Man kann ihn aber auch dazu verwenden, einen sicheren Login zu bauen. Der prüft zwar das Passwort, übermittelt es aber nicht im Klartext, was es jedem offenbaren würde, der die Internet-Verbindung abhört.

Das zentrale Konzept dabei ist, nicht das Passwort selbst zu übertragen, sondern lediglich den MD5 davon. Nur bietet diese Methode noch kaum Sicherheit, denn ein Lauscher an der Leitung, der den MD5-Wert mitliest, könnte sich mit einem eigenen System zu einem späteren Zeitpunkt einfach anmelden. Er hätte nicht das Klartext-Passwort, aber mit dem MD5-Wert davon einen nicht minder wertvollen Schatz - nichts wäre so gewonnen.

Sicher wird es, wenn der Login als Eingangsdaten für den MD5 nicht nur das Passwort allein verwendet, sondern dazu noch weitere Daten anfügt, die sich bei jedem Login ändern. Das könnte ein zufälliger String oder ein Zeitstempel sein. Im hier vorgestellten Beispielskript findet die Session-ID Verwendung - ein von PHP automatisch vergebener Wert, wenn man mit Sessions arbeitet. Dieser String aus Hex-Ziffern hat den Vorteil, dass ihn PHP innerhalb einer Sitzung selbständig behält. Würden Sie dagegen einen anderen Wert verwenden, müssten Sie ihn zwischen den beiden separaten Aufrufen der Darstellung des Login-Formulars und seiner Auswertung auf dem Server zwischenspeichern. Die Session-ID dagegen wird je nach den Einstellungen des Servers entweder per Cookie oder in der URL gespeichert.

Das Funktionsprinzip

Die Session-ID wird vom Browser auf der Seite des Anwenders mit dem eingegebenen Passwort verkettet und der MD5-Wert an den Server gesendet. Der errechnet dann den MD5 aus dem bei ihm gespeicherten Kennwortes und des Zufallsstring und verifiziert das Ergebnis mit dem übermittelten Wert.

Auf der Seite des Servers ist MD5 schon in den Bordmitteln enthalten, da PHP die Funktion md5() in seinem Standardrepertoire hat. Nur muss der Browser auch eine Möglichkeit haben, das Kennwort, das der User in einem Formular eingegeben hat, mit MD5 zu bearbeiten. Prinzipiell sind solche Aufgaben zum erweitern der Funktionalität eines HTML-Interface die Domäne von Javascript. Das beherrscht zwar von Haus aus kein MD5, lässt sich aber über eine frei erhältliche Javascript-Bibliothek von Paul Andrew Johnston (http://pajhome.org.uk) problemlos nachrüsten. Die davon benötigte Quellcode-Datei md5.js wird im HTML einfach per script-Befehl geladen.

Javascript verschleiert Passwörter

Das Prinzip funktioniert so: Das PHP-Skript login.php hat beim ersten Aufruf fast nichts zu tun. Es beschränkt sich nahezu darauf, das - aus Platzgründen im Listing mit minimalistischem HTML ausgestattete - Formular inklusive des eingebetteten Java Script-Programms darzustellen.

Das Login-Formular enthält die beiden Felder für den Usernamen und das Kennwort Sendet der Anwender das Login-Formular per Klick auf den Button ab, wird durch den im Form-Tag enthaltenen Zusatz

onsubmit="submit_handler()"

die Java Script-Funktion submit_handler aufgerufen, bevor die Formulardaten an den Server abgeschickt werden. Diese Funktion tauscht den Inhalt des Feldes f_pw, das das Klartext-Passwort enthält, gegen seine kodierte Entsprechung aus. Hier findet auch der einzige dynamische Einsatz des PHP-Skript statt, das die Session-ID in direkt ins Java Skript-Programm einbaut:

strSrc = document.loginform.f_pw.value;

strSrc = strSrc+'<?=session_id()?>';

document.loginform.f_pw.value = calcMD5(strSrc);

Beim Beenden liefert submit_handler() ein true zurück und bewirkt dadurch, dass die Übertragung der Formular-Daten durchgeführt wird. Der Empfänger ist dabei das Skript selbst.

Wiedererkennung des Hash-Codes

Beim diesem Aufruf stellt das Skript nun fest, dass Formulardaten vorhanden sind und wertet diese aus. Dazu wird zuerst die Funktion getPassword() aufgerufen. Die soll zum Usernamen das dazugehörige Passwort ausgeben. Der Inhalt von getPassword() wird bei jedem konkreten Einsatz des Skript ein wenig anders aussehen, je Datenbank-Server und Aufbau der Tabelle mit den Benutzerdaten. Darum hat die Funktion im Listing nur beispielhaften Charakter und liefert immer "geheim" als Kennwort zurück. Sie müssen Sie also für eine ernsthafte Anwendung erst noch mit Leben füllen.

Mit dem ermittelten Kennwort führt das PHP-Skript nun dieselbe Operation durch, wie das Java Script zuvor mit dem ins Formular eingegebenen Kennwort: Die aktuelle Session-ID wird angehängt und der MD5 dieser Zeichenkette ermittelt. Sind die beiden MD5-Werte, also der per Formular gelieferte und der in PHP berechnete Wert identisch, hat der Benutzer das richtige Passwort eingegeben. Das PHP-Skript verzweigt in diesem Fall einfach zur imaginären Startseite start.php. In einer richtigen Anwendung würde man zuvor wahrscheinlich noch eine Session-Variable setzte, um etwa den Usernamen festzuhalten. Denn ansonsten wäre beim Aufruf der Folgeseite die Information "ist ein erfolgreich angemeldeter User" ja wieder verloren.

Ansätze zur Verbesserung

Aus der üblichen Sicht, wie man Benutzerschnittstellen baut, sind die im Listing verwendeten verschiedenen Fehlermeldungen für "Username unbekannt" und "Passwort falsch" gut, weil Sie das jeweilige Problem näher beschreiben. Aber leider liefern Sie einem möglichen Angreifer einen wertwollen Hinweis. Denn wenn er nach einigem Herumprobieren statt der ersten Meldung die zweite bekommt, weiß er immerhin schon einmal, dass der verwendete Username existiert und muss "nur noch" das zugehörige Kennwort aufdecken. Darum wäre es besser, in beiden Fällen dieselbe Meldung "User unbekannt oder Kennwort falsch" auszugeben.

Skript zum Download

Auf der rechten Seite finden Sie unter "Dateien" das Symbol

mit dem das hier besprochene PHP-Skript geladen werden kann.


Kann man das auch mit ssl verbinden? das der also über https geht?
[DarkSuyan | 20.11.2007]


Bedingungen für die Kommentareingabe
Hinweis



Ihr Kommentar:


Name: E-Mail:
Name und E-Mail in einem Cookie auf Ihrer Festplatte speichern

Copyright © schraudolph.de 1999-2012   | Tippscout 4.0
Zurück Home