pcklick
Goto Top

Über Mysql verschlüsseltes Passwort per PHP abfragen

Hallo, ich habe folgendes Problem.
Ich habe User & Passwörter in einer Mysql Datenbank gespeichert. Diese Einträge wurden damals mit folgendem Befehl angelegt:

 
INSERT INTO `datenbank`.`virtual_users`
(`id`, `domain_id`, `password` , `email`)
VALUES
('1', '1', ENCRYPT('passwort-hier-eingeben', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'user-email');  

Nun möchte ich eine Login-Abfrage erstellen, doch sobald ich diese ausführe erhalte ich nur einen weissen Screen... Keine Fehlermeldung, nichts...

Die Frage: Wie kann ich das Passwort also so umwandeln, dass es dem verschlüsselten Dateneintrag in der Datenbank entspricht?

Exakt mein Problem hatte auch der User, aber mir konnte die Lösung nicht helfen:
http://stackoverflow.com/questions/16704051/how-to-check-a-mysql-encryp ...

Hier noch meine Login-Datei

if(isset($_POST['send']))  
{   
    $email = $_POST['user_email'];  
    $password = $_POST['user_password'];  
    $user_email = trim(htmlspecialchars($_POST['user_email']));  
    $user_password = trim(htmlspecialchars($_POST['user_password']));  

    //Benutzereingaben validieren
    if(filter_var($user_email, FILTER_VALIDATE_EMAIL) && !empty($user_password))
    {

Bis hier her klappte immer alles, nur die folgenden Zeile muss falsch sein:

        $query = $SQL->prepare("SELECT `id` FROM `virtual_users` WHERE `email` = '$email' AND `password` = ENCRYPT('passwort-hier-eingeben', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16)))");  

Und ab hier ging auch wieder alles:
        $query->execute();
        $query->store_result();
        $query->bind_result($user_id);

        //Sind Benutzerdaten vorhanden und korrekt?
        if($query->num_rows == 1)
        {
            $query->fetch();
            header('location: intern.php');  
            exit();
        }
...

Vielen Dank an alle, die mir helfen wollen! :D

Content-ID: 252328

Url: https://administrator.de/contentid/252328

Ausgedruckt am: 26.11.2024 um 05:11 Uhr

Arano
Lösung Arano 18.10.2014, aktualisiert am 24.10.2014 um 15:25:58 Uhr
Goto Top
Hallo pcklick,

wegen der "weißen Fehlerseite":
Die Fehlerausgabe ist scheinbar deaktiviert, versuch doch einmal als erste Zeile die folgenden Settings:
ini_set( 'display_errors', 'On' );  
ini_set( 'error_reporting', E_ALL);  
Die sollte 1. die Fehlerausgabe aktivieren (bitte nur auf Testsystemen verwenden) und 2. die Ausgabe auf alle Meldungen einstellen.
Damit sollte deine "weiße Fehlerseite" einer mit PHP-Fehlermeldungen weichen
Tipp: Denke an eigene Fehlerbehandlung ! Wie in diesem Fall. hättest du nach dem ausführen des Querys den Rückgabewert auf Erfolg geprüft, so hättest du die "weiße Fehlerseite" selber abfangen können und einen entsprechenden Hinweis (z.B. Daten konnten nicht ermittelt werden) ausgeben können.
Zudem macht es vom Programm vermutlich auch keinen Sinn weiterzulaufen wenn dei Datenbankabfrage gar nicht erst geklappt hat. (Dies trifft natürlich auf vieles zu: Keine Verbindung zu DB-Server, DB konnte nicht gewählt werden, Query war fehlerhaft, Query lieferte keine Ergebnisse, ect. pp )


Und zum eigentlichen Problem:
Ja, stimmt schon das es an dem Query liegt ! (verwendest du keinen Editor mit Syntaxhighlight !?)
In deinem Query kommt die Zeichenkette "$6$" vor, da sie in doppelten Anführungszeichen (") steht, wird sie von PHP geparst und PHP versucht alle Variablen durch ihre Werte zu ersetzen -> "$6"
Das siehst du auch an dem Syntaxhighlight hier im Forum. "$6" ist in rot geschrieben weil es für eine Variable gehalten wird (wegen dem $). Da es diese Variabel aber nicht gibt, wird sie durch "nichts" ersetzt und zerstört dir so dein Query. (zusättzlich sollte eine PHP-Notice ausgegeben werden... undefinierte Variable oder so etwas in der Art - sofern die Ausgabe nicht deaktiviert ist face-wink )

Du kannst nun den Query in einfache Anführungszeichen (') setzen damit er nicht mehr durch PHP geparst wird, ODER die Escapst das(beide/alle) Dollarzeichen = "\$6\$" ...die nicht als Variable dienen.


Schönes Wochenede
~Arano
LordGurke
LordGurke 18.10.2014 um 00:55:25 Uhr
Goto Top
Zusatz noch dazu:
Warum um alles in der Welt benutzt du PDO::prepare(), und setzt dann die Eingabevariablen UNGEFILTERT(!!) in den Query ein?!
Anstelle der Variablen solltest du dringend entweder die Platzhalter (":platzhaltername") oder das Fragezeichen verwenden!
wiesi200
wiesi200 18.10.2014 um 07:45:30 Uhr
Goto Top
Hallo,

Ich hätte da noch den Spaß zum beitragen:
http://php.net/manual/de/intro.password.php
pcklick
pcklick 18.10.2014 um 13:35:12 Uhr
Goto Top
Zitat von @Arano:

Hallo pcklick,

wegen der "weißen Fehlerseite":
Die Fehlerausgabe ist scheinbar deaktiviert, versuch doch einmal als erste Zeile die folgenden Settings:
> ini_set( 'display_errors', 'On' );  
> ini_set( 'error_reporting', E_ALL);  
> 
Die sollte 1. die Fehlerausgabe aktivieren (bitte nur auf Testsystemen verwenden) und 2. die Ausgabe auf alle Meldungen
einstellen.
Damit sollte deine "weiße Fehlerseite" einer mit PHP-Fehlermeldungen weichen
Tipp: Denke an eigene Fehlerbehandlung ! Wie in diesem Fall. hättest du nach dem ausführen des Querys den
Rückgabewert auf Erfolg geprüft, so hättest du die "weiße Fehlerseite" selber abfangen können
und einen entsprechenden Hinweis (z.B. Daten konnten nicht ermittelt werden) ausgeben können.
Zudem macht es vom Programm vermutlich auch keinen Sinn weiterzulaufen wenn dei Datenbankabfrage gar nicht erst geklappt hat.
(Dies trifft natürlich auf vieles zu: Keine Verbindung zu DB-Server, DB konnte nicht gewählt werden, Query war
fehlerhaft, Query lieferte keine Ergebnisse, ect. pp )



Und zum eigentlichen Problem:
Ja, stimmt schon das es an dem Query liegt ! (verwendest du keinen Editor mit Syntaxhighlight !?)
In deinem Query kommt die Zeichenkette "$6$" vor, da sie in doppelten Anführungszeichen (") steht, wird sie
von PHP geparst und PHP versucht alle Variablen durch ihre Werte zu ersetzen -> "$6"
Das siehst du auch an dem Syntaxhighlight hier im Forum. "$6" ist in rot geschrieben weil es für eine Variable
gehalten wird (wegen dem $). Da es diese Variabel aber nicht gibt, wird sie durch "nichts" ersetzt und zerstört dir
so dein Query. (zusättzlich sollte eine PHP-Notice ausgegeben werden... undefinierte Variable oder so etwas in der Art -
sofern die Ausgabe nicht deaktiviert ist face-wink )


Du kannst nun den Query in einfache Anführungszeichen (') setzen damit er nicht mehr durch PHP geparst wird, ODER die
Escapst das(beide/alle) Dollarzeichen = "\$6\$" ...die nicht als Variable dienen.


Schönes Wochenede
~Arano

Vielen Dank für diesen Vorschlag! Ich habe ihn angewendet, doch die if-Abfrage ( if($query->num_rows == 1) ) gibt nicht "1" sonder "0" aus. Demnach wurde die Eingabe in der DB nicht gefunden, obwohl im im Skript selbst nun Mail und Passwort direkt angegeben habe...

Ich vermute immernoch, dass an der Passwort Verschlüsselung etwas nicht stimmt...

$query = $SQL->prepare("SELECT `id` FROM `virtual_users` WHERE `email` = meinemail@domain.ch' AND `password` = ENCRYPT('MEINpasswort!123', CONCAT('\$6\$', SUBSTRING(SHA(RAND()), -16)))");  
Liegt es evtl an der RAND() Funktion?
pcklick
pcklick 18.10.2014 um 13:39:50 Uhr
Goto Top
Wenn ich nämlich einen weiteren User erstellen möchte mit dem selben Passwort aber einer anderern Mail, ist das Passwort nicht gleich dem, welches beim ersten User eingetragen wurde:

INSERT INTO `datenbank`.`virtual_users`
(`id`, `domain_id`, `password` , `email`)
VALUES
('10', '1', ENCRYPT('selbepasswort-nochmal', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'anderemail@example.com');

Neues Passwort /= Altes Passwort obwohl beide gleich sind...
LordGurke
LordGurke 18.10.2014 um 14:10:36 Uhr
Goto Top
Klar sind die Passwörter in der DB nicht gleich face-wink
Die sind gesalted: http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html#functi ...

Deshalb muss man die Felder auch beim Abfragen mit DECODE() prüfen:
http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html#functi ...
Den Salt kannst du dir bei der Abfrage schenken, der wird nur bei der Verschlüsselung benutzt.
colinardo
colinardo 18.10.2014 aktualisiert um 18:32:22 Uhr
Goto Top
Hallo zusammen,
Zitat von @LordGurke:
Klar sind die Passwörter in der DB nicht gleich face-wink
Die sind gesalted:
Korrekt, aber bei jedem Passwort wurde hier ein Hash auf einen Random-Wert als Salt verwendet, den man sich irgendwo hätte sichern müssen um das Passwort später wieder mit dem Hash vergleichen zu können.
Deshalb muss man die Felder auch beim Abfragen mit DECODE() prüfen:
Das geht schon mal garnicht Decode kommt nur bei Verwendung von Encode zum Einsatz !
Den Salt kannst du dir bei der Abfrage schenken, der wird nur bei der Verschlüsselung benutzt.
Eben nicht, er benötigt den beim Verschlüsseln verwendeten Salt um bei der Gegenprüfung einen korrekten Hash-Abgleich machen zu können. Da hier wohl ein Random Salt zum Einsatz kam wird er ohne diesen Salt das Passwort nicht mehr vergleichen können.

Also nochmal für den TO: Bei dieser Variante des Salt hättest du für jeden User das Salt zusätzlich in eine DB sichern müssen; hast du das nicht, kannst du die Passwörter nun leider alle gepflegt in die Tonne kloppen...

Normalerweise verwendet man in diesem Fall z.B. Daten des Users anhand dessen man einen Salt erzeugt( wie z.B. die e-Mail-Adresse ändert sich diese muss natürlich daran gedacht werden das Ursprüngliche Passwort erneut mit den neuen Daten zu Salzen). Diesen Algorythmus muss man dann geheim halten, denn mit diesem lässt sich dann ein wiederholbarer Salt generieren mit dem sich ein reproduzierbarer Hash generieren lässt, ohne das man das Salt irgendwo speichern müsste..

Und noch ein Hinweis: Solltest du die Encrypt() unter Windows verwenden wird diese immer NULL zurückgeben, diese ist nur auf Unix Systemen verwendbar.

Hoffe das war einigermaßen verständlich face-smile

Grüße Uwe
LordGurke
LordGurke 18.10.2014 um 17:53:35 Uhr
Goto Top
Sorry, ich hatte irgendwie auch ENCODE im Hinterkopf... Ja... Kaffe... *kram, such*
pcklick
pcklick 18.10.2014 aktualisiert um 18:56:59 Uhr
Goto Top
Zitat von @colinardo:

Hallo zusammen,
> Zitat von @LordGurke:
> Klar sind die Passwörter in der DB nicht gleich face-wink
> Die sind gesalted:
Korrekt, aber bei jedem Passwort wurde hier ein Hash auf einen Random-Wert als Salt verwendet, den man sich irgendwo
hätte sichern müssen um das Passwort später wieder mit dem Hash vergleichen zu können.
> Deshalb muss man die Felder auch beim Abfragen mit DECODE() prüfen:
Das geht schon mal garnicht Decode kommt nur bei Verwendung von Encode zum Einsatz !
> Den Salt kannst du dir bei der Abfrage schenken, der wird nur bei der Verschlüsselung benutzt.
Eben nicht, er benötigt den beim Verschlüsseln verwendeten Salt um bei der Gegenprüfung einen korrekten
Hash-Abgleich machen zu können. Da hier wohl ein Random Salt zum Einsatz kam wird er ohne diesen Salt das Passwort nicht mehr
vergleichen können.

Also nochmal für den TO: Bei dieser Variante des Salt hättest du für jeden User das Salt zusätzlich in eine DB
sichern müssen; hast du das nicht, kannst du die Passwörter nun leider alle gepflegt in die Tonne kloppen...

Normalerweise verwendet man in diesem Fall z.B. Daten des Users anhand dessen man einen Salt erzeugt( wie z.B. die e-Mail-Adresse
ändert sich diese muss natürlich daran gedacht werden das Ursprüngliche Passwort erneut mit den neuen Daten zu
Salzen
). Diesen Algorythmus muss man dann geheim halten, denn mit diesem lässt sich dann ein wiederholbarer Salt generieren
mit dem sich ein reproduzierbarer Hash generieren lässt, ohne das man das Salt irgendwo speichern müsste..

Und noch ein Hinweis: Solltest du die Encrypt() unter Windows verwenden wird diese immer NULL zurückgeben, diese ist
nur auf Unix Systemen verwendbar.

Hoffe das war einigermaßen verständlich face-smile

Grüße Uwe

Danke für Deinen Kommentar!
Wie / Mit welchem Befehl speichere ich diesen Salt dann aber ab?
colinardo
Lösung colinardo 18.10.2014, aktualisiert am 24.10.2014 um 15:25:33 Uhr
Goto Top
Zitat von @pcklick:
Wie / Mit welchem Befehl speichere ich diesen Salt dann aber ab?
Du generierst dir mit PHP einen reproduzierbaren Salt wie oben beschrieben z.B. mit einem SHA2-Hash der E-Mail-Adresse des Users(bitte komplizierter gestallten, sonst wäre das für Hacker ein leichtes), dann musst du diesen eben nicht abspeichern. Nur wenn du etwas nicht reproduzierbares wie einen randomwert bei der Generierung verwendest musst du dein Salt zusammen mit der UserID am besten in einer anderen DB speichern, da ja RAND() bei jedem mal andere Werte produziert!

Für die Umsetzung lese bitte erst mal:
http://www.foxplex.com/sites/php-passwoerter-sicher-verschluesseln/

Aber wie gesagt an deine jetzigen Passwörter wirst du so nicht mehr herankommen.
pcklick
pcklick 18.10.2014 um 19:40:09 Uhr
Goto Top
Das Problem ist nur, dass ich das ganze als SHA512-CRYPT verschlüsseln muss...
Sprich folgendes muss erfüllt sein:

CRYPT_SHA512 - SHA-512 Hash mit einem 16-Zeichen Salt, beginnend mit "$6$"

Mein Frage ist eben, wie ich unter dieser Verschlüsselung, dennoch eine Abfrage des ursprünglichen Passworts per PHP / Mysql machen kann?
wiesi200
wiesi200 18.10.2014 um 19:54:15 Uhr
Goto Top
Du bekommst das ursprüngliche Passwort nicht mehr raus.
Du kannst nur überprüfen ob das eingegeben dem in der Datenbank entspricht und wie man das macht ist ja schon genannt worden
pcklick
pcklick 18.10.2014 aktualisiert um 19:56:37 Uhr
Goto Top
Wie mache ich das aber konkret? Richtig weitergeholfen hat mir das noch nicht so recht ...
colinardo
colinardo 18.10.2014 aktualisiert um 20:13:01 Uhr
Goto Top
Zitat von @pcklick:

Wie mache ich das aber konkret? Richtig weitergeholfen hat mir das noch nicht so recht ...
http://stackoverflow.com/questions/21711890/how-to-implement-sha-512-md ...

ist doch kein Hexenwerk face-smile
...