PHP password_verify() function funktioniert nicht?

4 Antworten

Okay es funktioniert jetzt. Das Speichervolumen des Passworts war zu kurz für den Hash. Danke für jede Hilfe. Das mit dem mysqli_real_escape_string() habe ich jedoch immer noch nicht ganz verstanden.


Babelfish  08.02.2018, 16:32
Okay es funktioniert jetzt. Das Speichervolumen des Passworts war zu kurz für den Hash.

Diesen möglichen Fehler hatte ich schon angemerkt.

Das mit dem mysqli_real_escape_string() habe ich jedoch immer noch nicht ganz verstanden.

mysqli_real_escape_string ist dafür da, Daten so aufzubereiten, dass man sie gefahrlos in einer Datenbank speichern kann. Es verändert also unter Umständen die Daten.

Da du das Passwort aber nie in die Datenbank schreibst, solltest du das Passwort also auch nicht mit mysqli_real_escape_string behandeln und unverändert hashen.

Du schreibst aber den Passwort-Hash in die Datenbank. Diesen solltest du dann schon mysqli_real_escape_string übergeben.

0

Ganz einfach. Du manipulierst den input ja und schreibst den gefälschten wert in deine $Passwort variable.

Die ungewollte manipulation erfolgt durch deinen funktionsaufruf von mysqli_real_escape_string.

Du hast ein perfektes beispiel gebracht wie man es nicht tun sollte.

Übrigens ist der kommentar falsch. Eine hashfunktion ist immer eine einmalfunktion. Eine rekonstruktion des inputs ist ohne wörterbücher nicht möglich (und kann eigentlich auf den algorithmus bezogen auch nicht als rekonstruktion des inputs bezeichnet werden) und das ist auch so gewollt.


dahlamanada 
Beitragsersteller
 07.02.2018, 21:05

Ich weiß nicht genau was du meinst.

Wie würdest du mein Problem lösen?

0
Kieselsaeure  07.02.2018, 21:48
@dahlamanada

In dem du für password_verify den originalen post wert verwendest.

Warum entwickelst du überhaupt solche sicherheitskritischen bausteine wenn du mit den grundlagen noch garnicht vertraut bist..?

Das wird eines tages alles mal in einer katastrophe enden..

0

Was mir gleich auffällt ist, dass du für dein Passwort kein mysql_real_escape_string nutzen solltest – sowohl beim Speichern, als auch beim Vergleichen. Das Passwort wird ja nicht in der Datenbank gespeichert und da ist das unnötig bzw. kann sogar zu Fehlern führen.

Dagegen solltest du deinen generierten Password-Hash vor dem Speichern in der Datenbank schon mit mysql_real_escape_string behandeln.

Wenn du das gemacht hast und noch mal ein neues Passwort in der Datenbank gespeichert hast und es immer noch nicht klappt, musst du hat mal etwas debuggen. Teste zum Beispiel mal, ob in $row['Password'] auch wirklich der Password-Hash inkl. Salt und verwendetem Algo drin steht.

Woher ich das weiß:Berufserfahrung – Entwickle seit > 20 Jahren Anwendungen mit PHP.

dahlamanada 
Beitragsersteller
 07.02.2018, 21:01

meinst du so?

Zeile 6. $Username = $_POST['Username'];

Zeile 7. $Email = $_POST['Email'];

Zeile 8. $Password = $_POST['Password'];

Zeile 26. $hashedPassword = mysqli_real_escape_string($conn, password_hash($Password, PASSWORD_DEFAULT));

das funktioniert auch nicht

0
Isendrak  07.02.2018, 12:39

Wobei das mit mysql_real_escape_string aufs Passwort angewendet eher weniger ein Problem sein sollte (ausser, wenn seltsame Nebeneffekte zu befürchten sind...), da es sowohl beim Registrieren als auch beim Login durchgeführt wird.

Unnötig ist es aber trotzdem.

0
Babelfish  07.02.2018, 12:52
@Isendrak

Es könnte das Problem auftreten, dass sich bei verschiedenen PHP-Versionen das Verhalten von mysql_real_escape_string ändert und dann stimmt der Vergleich mit den Werten in der DB nicht mehr. Das lässt sich dann nachträglich auch nicht mehr beheben.

Hat zwar nichts mit dem aktuellen Problem zu tun aber besser ist es da kein unnötiges Risiko einzugehen. Wichtig ist es aber, mysql_real_escape_string für den Password-Hash anzuwenden, da je nach verwendeten Algo evtl. problematische Zeichen im Hash enthalten sein könnten.

Hinweis noch an dahlamanada: Pass auf, dass dein Passwort-Feld in der Datenbank groß genug ist (VARCHAR(255) sollte ok sein). Der Hash inkl. Salt und Algo wird meist deutlich länger als das Passwort selbst.

3
Kieselsaeure  07.02.2018, 18:45
@Babelfish

Meine empfehlung an der stelle wäre um zukunftsweisend problemen vorzubeugen die hash funktion zu nutzen mit statischer angabe vom algo und auf diesen password_* quatsch zu verzichten.

Warum von password_* abspringen? Du bist unflexibler und (sofern du keine angabe über den algorithmus angibst - den default verwendest) hast die gefahr, dass eines tages der standard algo geändert wird. Liest du die releasenotes nicht durch kannst du schlichtweg nicht alle versionen ohne anpassungen verwenden.

Übrigens ist von solchen sicherheitsrelevanten funktionen (password_*)zu erwarten das unsichere algorithmen mit der zeit entfernt werden. So und viel spass wenn du auch hier nicht wieder in den release notes nachliest. Der algo ist vermutlich wie üblich noch in php vorhanden und steht bereit, aber ist eben aus password_* rausgeflogen (nachvollziehbar, ist ja unsicher).

0

ähm, falls Du wirklich einen Hash generierst, dann ist das eine OneWay-Funktion, man kann einen Hash nicht "dehashen", wie Du schreibst. Die einzige Möglichkeit ist, das eingegebene PW erneut zu hashen und diesen dann gegen den gespeicherten Hashwert zu vergleichen. Da ich auf die Schnelle nicht sehe, was "password_hash" und "password_verify" tatsächlich treiben, kann ich nur vermuten, dass Du das eingegebene Passwort direkt gegen den gespeicherten Hash vergleichst, und das kann nicht TRUE werden.


dahlamanada 
Beitragsersteller
 07.02.2018, 11:56

ein hash ist random. Also ist ein Vergleich mit dem Eingegebenen PW beim Login nicht möglich - da dieser logischerweise anders aussehen würde. Die funktion password_verify() encryptet ("dehashed") das vorher gehashte PW.

0
SabrinaDondic  07.02.2018, 12:13
@dahlamanada

Ein Hash ist nicht random, das ist ja gerade Sinn und Zweck eines Hashes, dass er bei gleicher Eingabe den gleichen Hash erzeugt.

Man speichert nicht das PW im Klartext, sondern Hash(PW). Hash ist eine OneWay- bzw. Trap-Funktion, d.h. die sollte sich hoffentlich nicht umkehren lassen. D.h. es gibt keine "DeHash"-Funktion, mit deren Hilfe sich das PW wieder in den Klartext rekonstruieren lässt à la

PW = DeHash(Hash(PW))

Die Prüfung bei eingegebenem PW kann immer nur Hash(PW) ?= Hash_Stored sein.

1
Isendrak  07.02.2018, 12:14
@dahlamanada
  1. Ein Hash ist nicht "random". Nur der (sofern verwendete) "salt"...
  2. Mit "password_verify" wird da nix "dehashed"... Es wird nur ein entsprechender Hash aus dem Passwort gebildet und dieser mit dem gespeicherten Hash verglichen.

Das ganze sollte in etwa so ablaufen:

<?php
$password = "password1";
$hash = password_hash($password, PASSWORD_DEFAULT);

//TODO: lorem ipsum dolor sit amet...

if(password_verify($password, $hash)){
    echo "password ok.";
}
else{
    echo "password not ok.";
}

Siehe auch: http://php.net/manual/de/function.password-hash.php und http://php.net/manual/de/function.password-verify.php.

1
dahlamanada 
Beitragsersteller
 07.02.2018, 20:57
@Isendrak

Dein Code funktioniert so wie er da steht.

Was ich aber nicht verstehe ist wenn ich den hash von "passwort1" der variable "$hash" übergebe, funktioniert das komischerweise nicht mehr :

<?php

$password = "password1";

$hash = '$2y$10$d5HzrcWYHUsBGo1FenP7neXw.Ehj8tCqkThHK2C3jal';

//TODO: lorem ipsum dolor sit amet...

if(password_verify($password, $hash)){

echo "password ok.";

}

else{

echo "password not ok.";

}

wieso ist das so und ist das vielleicht mein problem?

0