[SOLVED] PHP/MySQL, Userauthentifizierung und Passwörter

    • Offizieller Beitrag

    Ich hab versucht eine simple Useranmeldung zu programmieren. Da ich mich mit der ganzen Password-Security aber nie beschäftigt hab, hab ich folgende Anleitung/Guideline benutzt:
    http://alias.io/2010/01/store-…afely-with-php-and-mysql/


    Passwörter verschlüsseln geht einwandfrei. Nur das Anmelden haut jetzt nicht so hin, wie ichs gern hätte :)
    Folgender Code aus der Guide scheint mir fehlerbehaftet, aber ich weiß nicht wo ich ansetzen soll, weil ich noch nie mit objektorientierten Abfragen in MySQL gearbeitet hab :-/


    Erstmal glaub ich, dass hinter LIMIT 1' noch eine Klammer geschlossen gehört!
    So .. da es jetzt also schonmal einen Typo in diesem Codeabschnitt gibt, bin ich schonmal verunsichert :-/
    Geh ich richtig in folgender Annahme (hier verändert mit meinem eigenen Code):


    Ich krieg immer ein "Fatal error: Call to a member function bindParam() on a non-object in". Und bei Überpüfung der Variablen $sth kommt raus, dass sie bool(false) ist. Somit kein Objekt, ok. Aber WARUM ist sie false?


    Jemand ne Idee?

    • Offizieller Beitrag

    Ok. hier jetzt also meine Lösung:


    Ich erstelle das Passwort wie im obigen Link angegeben, und speichere $hash und $salt in meiner MySQL-Datenbank.


    Bei der Anmeldung übergeben ich $username und $password und mache dann folgendes:


    Auf diese Art funktionierts. Aber: Ist das auch sicher? Ich hol mir erst das Salt des entsprechenden Users aus der Datenbank, und mach dann den selben Schritt mit "crypt($hash, $salt)" wie in der Generierung des Passwort-Hashes. Den gleiche ich dann mit dem in der Datenbank gespeicherten hash ab.


    Noch eins: ist es normal, dass der Passwort-hash bei gleichen Passwörtern auch ident ist? Ich hab mehrere User testweise mit dem selben Passwort erstellt, und der hash war immer gleich! Das salt ist jedoch immer anders (logisch, das wird ja randomisiert).
    Eigentlich sollte "crypt($hash, $salt)" doch einen hash auf basis des salts erstellen, und somit immer anders aussehen, selbst bei gleichem eingegebenen Passwort!
    Was mach ich falsch?

    • Offizieller Beitrag

    Noch was getestet: das salt eines users funktioniert bei jedem anderen user auch! grad per phpMyAdmin in der Datenbank die salts rumgetauscht, und das anmelden geht noch immer ..
    Das kann doch nicht so richtig sein, oder?? Das salt sollte doch einzigartig zur Entschlüsselung des Userpasswortes dienen, oder hab ich da was falsch verstanden??

  • Das Problem an dieser "Verschlüsselungsmethode" ist, dass du sowohl die Credentials als auch den Ergebnis-Hash mit in die DB schreibst. :) Sollte jemand die DB kompromittieren, hat er alle Teile, die er braucht, um die Verschlüsselung zu umgehen. Wenn er de facto nur den Hash braucht zum Einloggen, und der auch mit in der DB steht, ist der Salt ja eh nutzlos, von daher würde ich es eher folgendermaßen angehen:


    1.) Der Salt kann ruhig einheitlich sein für alle Nutzer. Wichtig ist nur, dass der irgendwo weggeschrieben wird außerhalb der DB, z.B. als Konstante in einer PHP-Datei, die beim Start gebootstrapped wird:

    PHP
    define('MARTIN_SALT', 'mysecretstring');


    Der Salt muss nicht für jeden Nutzer unterschiedlich sein; dafür ist das eigentliche Passwort da. Das Salt ist im Grunde nur wichtig, wenn du auf Twitter und FB das Passwort "testpwd" nutzt, wäre es auch verschlüsselt auf beiden Seiten identisch. Mit deinem Salt allerdings ist der Hash auf deiner Seite anders, obwohl der Nutzer das gleiche Passwort genutzt hat. So kann ein Hacker die erbeuteten Daten einer anderen Seite nicht auf deiner Seite nutzen, da du das Pwd wie gesagt "salzt" mit einem dem Hacker unbekannten String. Ich weiß, der in dem Artikel empfiehlt das, aber sobald der Hash bzw. das Salt in der selben DB wie die Nutzer stehen, hat ein Hacker alles was er braucht, um es zu umgehen.


    2.) Statt den Salt mit in die DB zu schreiben, bildest du den Hash einfach real-time bei jeder Abfrage, was du ja schon machst, nur halt jetzt nimmst du die Konstante und schreibst den Hash nirgends weg, sodass er nur während der Laufzeit PHP bekannt ist.



    Bzgl. gleicher Passwort-Hash bei gleichen Passwörter: Wie bildest du denn das Salt pro Nutzer? Aus dem Pwd? Oder ein Random String? Falls Ersterem, wäre es klar: Wenn das Pwd. gleich ist und daraus der Salt gebildet wird, sind sowohl das Pwd und Salt pro Nutzer gleich, die das selbe Pwd haben. Wie du das Salt bildest, sieht man leider in deinem Code-Auszug nicht.



    Hier gibt es bei StackOverflow übrigens einen Ansatz (siehe akzeptierte Antwort): http://stackoverflow.com/quest…class-login-logout-signup Eine Alternative wäre OpenID mit Google, falls dein Script Zugriff nach außen hat: http://stackoverflow.com/quest…in-system/4460342#4460342

    • Offizieller Beitrag

    Danke für den Input!


    Also das salt sollte eigentlich randomized sein. Ich generiere es wie in der Guide auf alias.io beschrieben mit:


    Desshalb schreib ichs dann in die Datenbank, weil ich ohne das spezielle salt ja sonst das zugehörige Passwort nicht mehr entschlüsseln kann (dachte ich jedenfalls).


    Komischerweise sind aber die Passwort-hashes trotz unterschiedlicher salts bei gleichem Passwort auch ident! (also z.B. Passwort "hugo123" ergibt IMMER den hash "$2jC86XdlRvzV", obwohl das salt unterschiedlich ist!)
    Wenn ich dann per phpMyAdmin mit den Salts herumjongliere (also das salt eines Users durch das salt eines anderen Users ersetze) kann ich mich TROTZDEM anmelden, als ob das salt für die encryption des hashes eigentlich irrelevant wäre! Ersetze ich das salt bei einem User aber durch einen beliebigen string (z.b. "abcdefgh") geht das anmelden nicht mehr. Also IRGENDWAS steckt da drin, nur blick ich nicht durch, was :-))


    Dein Vorschlag mit einem zentralen salt gefällt mir aber sehr gut. Mir ists eh lieber, das steht nicht in der Datenbank. Werde ich also mal machen.