Tage
Stunden
Minuten
Sekunden
🎅🎄 Weihnachts-Special 🎅🎄 - 15% Rabatt - nur bis 26.12.2024 ⏰

Einführung in Hashing mit PHP – Login-Skript Tutorial Teil 2

Im vorhergehenden Tutorial haben wir angefangen ein Login-Skript mit PHP zu programmieren (Teil 1), um den Zugang zu deiner Webseite zu schützen. Das war zunächst ganz einfach gelöst, indem Du ein festes Passwort als Geheimnis direkt im Skript gespeichert hast:

<?php
$passwort = "superGeheim";
?>

Dieser Weg ist unsicher und diese Methode solltest Du im Alltag und als angehender Profi nicht benutzen. Das ist heutzutage eine recht kleine Hürde, die durch automatisiertes Raten (sprich: Ausprobieren mit Hilfe des Computers) in kurzer Zeit geknackt werden kann.

Zudem ist das ganze unflexibel, weil jede Änderung des Passworts eine Softwareanpassung bedeutet (Anpassung des aufgerufenen Skripts, welches das eingetippte Passwort überprüft). Jeder, der Zugang zu den Skripten (bzw. deren Quellcode) hat, kann das darin gespeicherte Passwort heraussuchen, sich merken und dieses ändern.

 

Hier in diesem Artikel lernst Du, durch welche Methoden Du einen solchen Zugangsschutz verbessern kannst. Ziel sind dabei immer zwei Dinge:

  1. größere Sicherheit, und
  2. etwas mehr Flexibilität, sprich: wenn das Passwort geändert wird.

Beide Ziele gleichzeitig zu erreichen, ist bei der Entwicklung solcher Mechanismen nicht immer einfach und Du mußt beide Ziele gegeneinander abwägen, sprich: welches davon ist Dir wichtiger oder wie sieht ein guter Kompromiss aus, der praxistauglich ist und den Du auch akzeptieren kannst.

Passwort in einer Datei hinterlegen (Klartext)

Der erste Schritt besteht darin, das bislang im PHP-Skript auswertung.php hinterlegte Passwort in eine externe Datei auszulagern. Hier heißt diese Datei schatztruhe.txt. Damit mußt Du bei einem Wechsel des Passworts dein PHP-Skript nicht mehr ändern und Du kannst die von Dir entwickelten Skripte weitergeben, ohne deine Geheimnisse preiszugeben.

Lege dazu als erstes eine (zunächst noch leere) Textdatei mit dem Namen schatztruhe.txt an. Das PHP-Skript auswertung.php und die gerade erstellte Textdatei müssen sich im gleichen Verzeichnis auf dem Webserver befinden. Öffne nun schatztruhe.txt und füge nur die folgende Zeile hinzu:

superGeheim

Speichere die Datei ab. Als zweiten Schritt änderst Du das PHP-Skript zur Auswertung (auswertung.php). Die Zeile mit dem festen Wert für das Passwort löschst Du und ersetzt diese durch die Angabe der Passwortdatei wie folgt:

<?php
// definiere Passwortdatei
$passwortDatei = "schatztruhe.txt";
?>

Als Drittes definierst Du eine Variable $zugangErlaubt mit dem Wert FALSE. Diese Variable regelt, ob der Zugang zum Inhalt der Webseite freigeschaltet wird. FALSE bedeutet nein, und TRUE bedeutet ja. TRUE und FALSE sind Boolesche Wahrheitswerte, die fest in PHP definiert sind und die Du dir hier zunutzemachst.

<?php
// Zugriff erlaubt?
$zugangErlaubt = FALSE;
?>

Nun liest Du das Passwort aus der Passwortdatei schatztruhe.txt in die lokale Variable $passwort. Die hierbei verwendeten Funktionen zum Lesen der Passwortdatei sind in ausführlich beschrieben.

Aus dem gesamten Inhalt der Datei interessiert uns nur die erste Zeile, die sich im 1. Element der Liste $inhaltPasswortdatei befindet (Index 0 der Liste). Danach benutzt Du die PHP-Funktion trim(), um alle eventuell vorkommenden Sonderzeichen aus der eingelesenen Zeile herauszufiltern -- sprich Leerzeichen am Anfang und Ende der Zeile sowie Zeilenumbrüche.

Danach vergleichst Du das Passwort aus der Datei mit dem Wert des Eingabefeldes. Falls beide Werte identisch sind, setzt Du die Variable $zugangErlaubt auf TRUE and schaltest somit den Zugang zur Webseite frei.

<?php
if (file_exists($passwortDatei)) {
    if (is_readable($passwortDatei)) {

    // lese Passwortdatei
    $inhaltPasswortdatei = file($dateiname);

    // die erste Zeile enthält das Passwort
    $passwort = $inhaltPasswortdatei[0];

    // entferne alle Sonderzeichen
    $passwort = trim($passwort);

    // vergleiche beide Werte
        if ($passwort == $eingabefeld) {
            // eingegebenes Passwort ist korrekt
            $zugangErlaubt = TRUE;
        }
    }
}
?>

Mit dieser Änderung hast Du den ersten Schritt zur Verbesserung der Sicherheit erreicht. Knackpunkt ist nun die Passwortdatei, da darin alle Passworte stehen. Stiehlt ein Angreifer diese Datei, ist das Geheimnis verloren. Daher kümmerst Du dich als nächstes um das Passwort und speicherst es verschlüsselt ab.

Kostenloser Crashkurs für Anfänger

Jetzt kostenlosen Crashkurs sichern (Online Programmieren, keine Installation nötig)

Passwort in einer Datei hinterlegen (als Hashwert)

Passworte im Klartext abzuspeichern stellt ein hohes Sicherheitsrisiko dar. Dieses Risiko schaltest Du jetzt aus. In der Praxis wird anstatt des Klartextes der Hashwert des Passworts gespeichert.

Vereinfacht ausgedrückt ist ein Hashwert eine eindeutige Repräsentaton einer Zeichenkette auf der Basis einer Hashfunktion. Das Berechnen des Hashwertes aus der Originalzeichenkette ist einfach, hingegen der umgekehrte Weg -- das Errechnen der Originalzeichenkette aus dem Hashwert -- mit den heutigen technischen Mitteln vergleichsweise kompliziert und daher noch als sicher anzusehen. Was Du hier benutzt, ist die Tatsache, dass zwei Zeichenketten nur mit sehr hoher Wahrscheinlichkeit den gleichen Hashwert liefern, wenn sie identisch sind.

Bisher übliche Verfahren für die Berechnung des Hashwerts sind beispielsweise MD4, MD5, der Secure Hash Algorithm -- kurz: SHA -- und Data Encryption Standard (DES). MD4 und MD5 sind bereits seit längerer Zeit als unsicher einsortiert, sprich: ohne viel Aufwand knackbar.

SHA1 rutscht mittlerweile in die gleiche Kategorie und nur die stärkeren Varianten SHA2 und SHA3 mit größerer Schlüssellänge gelten noch als sicher. PHP bringt neben MD4, MD5 und SHA1 die Unterstützung für die beiden weiteren Verfahren Blowfish und Argon2 mit.

Zudem hat PHP seit längerem Funktionen bereitgestellt, die den Umgang mit diesem Problem vereinfachen. Dazu zählen die beiden Funktionen password_hash() und password_verify(). password_hash() erzeugt den Hashwert auf der Basis eines Passworts und dem gewünschten Verfahren und password_verify() überprüft, ob dieser Hashwert mit dem eines anderen Passworts übereinstimmt. Beide Funktionen kommen hier zum Einsatz.

Mittels password_hash() berechnest Du den Hashwert für das bisherige Passwort "superGeheim" wie folgt:

<?php
$hash = password_hash("superGeheim", PASSWORD_DEFAULT);
?>

Die Angabe PASSWORD_DEFAULT im Funktionsaufruf wählt als kryptographisches Verfahren Blowfish aus. Die Angabe ist erforderlich, wenn Du bspw. mit einer PHP-Version kleiner als 7.0 programmierst. In späteren PHP-Versionen ist der zweite Parameter nicht mehr zwingend erforderlich. Das Ergebnis des Aufrufs der Funktion password_hash() ist diese Zeichenkette:


$2y$10$vztf9mlzBEFLnfCtpDm6e.ILogNTvJiAnDQug7Mm/OFfkd6l1qYPS

Diesen Wert speicherst Du nun in der Datei "schatztruhe.txt" als Geheimnis ab. Ersetze dazu den Inhalt der ersten Zeile vollständig durch den Hashwert.

Als nächstes änderst Du im Skript "auswertung.php" den Vergleich des hinterlegten Hashwertes aus der Passwortdatei "schatztruhe.txt" mit dem Eingabefeld. Zum Einsatz kommt die Funktion password_verify() wie folgt:

<?php
if (password_verify($eingabefeld, $passwortHash)) {
    // eingegebenes Passwort ist korrekt
    $zugangErlaubt = TRUE;
}
?>

Rufst Du nun dein Skript mit der Anmeldung auf, wird der Hashwert für den Text im Eingabefeld berechnet und mit dem gespeicherten Hashwert in der Passwortdatei verglichen.

Mit dieser Vorgehensweise hast Du gleichzeitig dafür gesorgt, dass nirgendwo das verwendete Passwort im Klartext auftaucht. Stiehlt jemand die Passwort-Datei schatztruhe.txt, hat er nur die Hashwerte, aus denen sich nur mit sehr viel Aufwand das Originalpasswort berechnen läßt.

Weitere Techniken zur Absicherung von Passwörtern

Bisher hast Du lediglich ein Passwort verwendet, um den Zugang zu sichern. Damit hat nur ein einziger Benutzer Zugang bzw. alle Benutzer müssen das gleiche Passwort verwenden und sich somit das Geheimnis teilen. Das ist eher ungünstig.

In der Praxis kommen daher weitere Methoden zum Einsatz, um den Zugang noch stärker zu sichern. Dazu zählen das Ergänzen eines Benutzernamens -- sprich das Speichern einer Kombination aus Benutzername und Passwort, das Schützen der Inhalte durch eine Datei namens .htaccess und das Ergänzen der Authentifizierung um einen weiteren Faktor (genannt Zwei-Faktor-Authentifizierung) -- einen Fingerabdruck oder eine Rechenaufgabe (bekannt als Capture). Diese Techniken sind aufwendiger und verdienen einen eigenen Artikel.

Um noch mehr über den Umgang mit Passworten und PHP zu erlernen, ist ein Blick in die entsprechende PHP-Dokumentation nützlich. Darin stehen Aufrufbeispiele und Erklärungen, wie Du andere Hashing-Verfahren in deinen Projekten einsetzen kannst.

Links und Referenzen

  • htaccess erstellen & konfigurieren – Eine Anleitung, https://www.was-mit-internet.de/htaccess-konfiguration/
  • Apache HTTP Server Tutorial: .htaccess files, https://httpd.apache.org/docs/2.4/howto/htaccess.html
  • Secure Hash Algorithms, Wikipedia, https://en.wikipedia.org/wiki/Secure_Hash_Algorithms
  • Blowfish, Wikipedia, https://de.wikipedia.org/wiki/Blowfish
  • Argon2, Wikipedia, https://de.wikipedia.org/wiki/Argon2
  • Zwei-Faktor-Authentifizierung, Wikipedia, https://de.wikipedia.org/wiki/Zwei-Faktor-Authentisierung
  • Data Encryption Standard (DES), Wikipedia, https://de.wikipedia.org/wiki/Data_Encryption_Standard
  • PHP Manual: Password Hashing, https://www.php.net/manual/de/book.password.php
Programmierer-Crashkurs für Anfänger...kostenlos!
Baue echte Apps, ohne Vorwissen, ohne Installation!
toolbox 1
Email eintragen und sofort loslegen: