Arrays auslesen, Werte zuweisen

  • Hallo,
    ich habe hier ein kleines Problem bei der Passwortverwaltung in einer Datenbank:

    Das für den Nutzer erstellte Passwort wird in der DB als MD-5-Hash aus Passwort+Nutzer abgelegt.
    Es soll aber vermieden werden, dass zwei Nutzer das selbe Passwort haben.

    Das würde ich wie folgt prüfen:

    Ich hole ein Array mit den vorhandenen Nutzernamen ($users) und eines mit den vorhandenen Passwort-Hashes ($pwdhs) aus der Datebank.

    Dann erstelle ich ein weiteres Array, in welchem ich das neu erstellte Passwort mit jedem existierenden Nutzernamen hashe ($hashes2).

    Nun müsste ich $pwdhs mit $hashes2 abgleichen und wenn sich an irgendeiner Stelle eine Übereinstimmung erbigt, muss der Zufallsgenerator nochmal ran, weil es das Passwort dann schon gitb.

    Die erste Frage, die sich mir hier stellt, ist, wie ich alle Werte aus $users in einer Schleife mit dem neuen Passwort hashen kann.

    Dabei geht es erstmal darum, wie man einen Wert in $users adressiert. Da stehen ja jetzt nur die Nutzernamen drin.
    Zweitens muss der entsprechende Wert dann noch $hashes2 zugewiesen werden, was ich hinbekommen würde.

    Ich bräuchte folglich irgenwas wie etwa

    PHP
    md5($users[x].$pwd) = $hashes2[x]


    Das scheint aber so nicht zu funktionieren.

    Der Abgleich könnte dann wohl mit foreach gemacht werden. Aber da blicke ich nocht nicht ganz durch.

    Kann mir da mal jemand einen Anhaltspunkt geben? Danke!

  • Hab jetzt leider nicht die Zeit um deinen Post ausreichend zu entwirren. Nur einige Anmerkungen:

    Hallo,
    Das für den Nutzer erstellte Passwort wird in der DB als MD-5-Hash aus Passwort+Nutzer abgelegt.
    Es soll aber vermieden werden, dass zwei Nutzer das selbe Passwort haben.

    Was soll das fuer einen Sinn machen? Und warum hast du nicht einfach ein Feld fuer den Benutzernamen und ein Feld fuer das Passwort?

    Ich bräuchte folglich irgenwas wie etwa

    PHP
    md5($users[x].$pwd) = $hashes2[x]


    Das scheint aber so nicht zu funktionieren.

    Das funktioniert natuerlich nicht. Auf der linken Seite einer Zuweisung darf ja nur eine Variable stehen.

    Im Uebrigen, aber das wird fuer dich zu komplex sein, gibt es die Funktion array_map(), das nur mal als Hinweis fuer andere Leser.

  • Lieber osiris, ich konnte selbst beim 3784973498. mal Durchlesen nicht verstehen, was du vorhast. Entweder dein Lösungsansatz ist falsch, oder du tust dir einfach nur schwer, dich auszudrücken.

    Üblicherweise trennt man Benutzername und Passwort in der Datenbank. Ist das erst einmal getan, kannst du mit der Funktion in_array arbeiten:

    PHP
    $all_pwds = array(...);
    do {
        $pwd = md5(mt_rand());
    } while(in_array($pwd,$all_pwds));



    Jetzt speichert die Variable $pwd ein neues Passwort-Hash.


  • Was soll das fuer einen Sinn machen? Und warum hast du nicht einfach ein Feld fuer den Benutzernamen und ein Feld fuer das Passwort?

    Natürlich gibt es in meiner Datenbank jeweils ein Feld für die Usernamen und ein Feld für die Passwörter.
    Das Passwort soll aber nicht im Klartext gespeichert werden, sondern als MD5-Hash.
    Als ich mir darüber was durchgelesen habe, bin ich auf folgenden Hinweis gestoßen:

    Man sollte nicht nur das Passwort alleine verschlüsseln, sondern entweder zusammen mit einen zufälligen String oder einfach dem Username, also

    PHP
    md5($passwort.$username)

    Das macht es dann aber eben etwas schwieriger nachzuprüfen, ob ein Passwort bereits existiert. Dazu müsste man wie gesagt:

    1.
    Das Feld mit den Usernamen holen.

    2.
    Das neu erstellte Passwort (wenn sich jemand registriert) jeweils mit jedem bestehenden Nutzernamen hashen und die Resultate in einem Array ($hashes2) ablegen.

    3.
    Anschließend müsste man nachsehen, ob es zwischen $hashes2 und dem Array mit den bestehenden MD5-Hashes ($pwdhs) Übereinstimmungen gibt.
    Wenn ja, dann ist es äußerst wahrscheinlich, dass diese Übereinstimmung an den Stellen $hashes2[user_xy] und $pwdhs[user_xy], also beim selben Nutzer vorkommt.
    Das heißt wiederum, dass das "neue" Passwort, mit dem user_xy gehasht wurde schon besteht - und zwar eben als das Passwort von user_xy.
    Dashalb darf es nicht verwendet werden.

    Zitat von spinball

    Lieber osiris, ich konnte selbst beim 3784973498. mal Durchlesen nicht verstehen, was du vorhast.


    Na ja, trotzdem danke, dass du's dir so oft durchgelesen hast. ;)
    Ich hoffe ich hab's jetzt ein wenig verständlicher formuliert.

  • Das macht es dann aber eben etwas schwieriger nachzuprüfen, ob ein Passwort bereits existiert.


    Warum willst du das machen? Mal angenommen die Anzahl der registrierten Benutzer ist relativ klein und einer erhält beim Ändern seines Passworts die Warnung, dass das Passwort bereits verwendet wurde. Dann muss er doch nur noch alle Benutzernamen mit dem Passwort durchprobieren, weil das Passwort garantiert zu einem passt.

    -- Stefan

  • Also bei mir funktioniert das momentan so:

    Ein Nutzer, der sich registrieren will, gibt lediglich sein Mailadresse ein. Nutzername und Passwort werden automatisch erstellt und per Mail versandt.
    Wenn also ein Passwort schonmal verwendet wurde, bekommt der Nutzer das gar nicht mit.

  • Ein Nutzer, der sich registrieren will, gibt lediglich sein Mailadresse ein. Nutzername und Passwort werden automatisch erstellt und per Mail versandt.
    Wenn also ein Passwort schonmal verwendet wurde, bekommt der Nutzer das gar nicht mit.


    Was bringt die Überprüfung auf doppelte Passwörter dann? Außerdem wird ja der Benutzer die Möglichkeit haben, sein Passwort später zu ändern.

    -- Stefan

  • Der Nutzer hat in diesem Fall nicht die Möglichkeit sein Passwort zu ändern.

    Da aber der Versand des Passwortes per Mail nicht sicher ist, wird nach der ersten Anmeldung für jeden Nutzer noch ein Code erzeugt - sozusagen als zweite Sicherheitsstufe.

    Warum das jetzt so und nicht anders gemacht werden soll, weiß ich nicht. Hab mir das nicht ausgedacht.

    Die Tatsache, dass kein Passwort doppelt verwendet werden darf, macht es einem eventuellen Angreifer schwerer zu einem brauchbaren Ergebnis zu kommen.
    Andererseits: Wenn jetzt tasächlich mal ein identisches Passwort erzeugt werden sollte und sich zwei User mit dem selben Passwort anmelden, wäre das ja auch möglich, weil der MD5-Hash trotzdem unterschiedlich ist.
    Ein Angreifer wüsste also nicht, dass diese User das selbe Passwort haben.

    Aber was ist dann, wenn der eine Nutzer zufällig mal den Usernames des andern eingibt, weil die sich z.B. nur an einer Stelle unterscheiden? Da ist dann schon wieder das Problem.

  • Der Nutzer hat in diesem Fall nicht die Möglichkeit sein Passwort zu ändern.

    Seltsam...

    Die Tatsache, dass kein Passwort doppelt verwendet werden darf, macht es einem eventuellen Angreifer schwerer zu einem brauchbaren Ergebnis zu kommen.

    Dafür gibt es Gegenmaßnahmen, die deutlich brauchbarer sind...

    Andererseits: Wenn jetzt tasächlich mal ein identisches Passwort erzeugt werden sollte und sich zwei User mit dem selben Passwort anmelden, wäre das ja auch möglich, weil der MD5-Hash trotzdem unterschiedlich ist.

    Kapier ich nicht... Warum sollte der MD5-Hash unterschiedlich sein müssen, damit das funktioniert?

    Ein Angreifer wüsste also nicht, dass diese User das selbe Passwort haben.

    Was weiß der Angreifer in deinem Szenario?

    Aber was ist dann, wenn der eine Nutzer zufällig mal den Usernames des andern eingibt, weil die sich z.B. nur an einer Stelle unterscheiden? Da ist dann schon wieder das Problem.


    Du solltest vielleicht mal ausrechnen, wie wahrscheinlich es ist, dass das passiert...


  • Kapier ich nicht... Warum sollte der MD5-Hash unterschiedlich sein müssen, damit das funktioniert?


    Hab ich mich ungut ausgedrückt: Es ging eher darum, dass trotz, dass die beiden Nutzer ein identisches Passwort haben, in der DB zwei unterschiedliche MD5-Hashes stehen.

    Zitat

    Was weiß der Angreifer in deinem Szenario?


    Im schlimmsten Fall wohl das, was in diesem Forum steht.

    Zitat


    Du solltest vielleicht mal ausrechnen, wie wahrscheinlich es ist, dass das passiert...


    Hab ich mir auch schon gedacht. Es gibt immerhin etwa 24000 mögliche Nutzernamen.

    Welche Maßnahmen würdest du denn hier ergreifen anstatt das so umstänlich zu machen?

  • Zitat

    Welche Maßnahmen würdest du denn hier ergreifen anstatt das so umstänlich zu machen?

    • Möglichst keine Einschränkungen für das Passwort (je weniger Einscrhänkungen, desto sicherer kann der Benutzer sein Passwort wählen)
    • freie Passwort-Wahl durch den Benutzer. Nur wenn sich der Benutzer sein Passwort selbst aussuchen kann, wird er sich es auch merken. Ansonsten hat er es wahrscheinlich auf einem PostIt am Monitor kleben...
    • Bruteforce-Attacken möglicherweise mit Sperren entgegenwirken (Aufhebung entweder manuell oder automatisch nach einer bestimmten Zeit, evtl Kombination mit Captcha)
    • Ja nach Zielgruppe evtl die Benutzer daran erinnern, dass sie ihr Passwort wechseln sollen, bzw darauf hinweisen, dass sie ein sicheres Passwort verwenden sollen
  • Ich habe noch nie erlebt, dass sowohl Benutzername als auch Passwort zufällig generiert werden. Das ist sehr unüblich. Nichtsdestotrotz kann man es folgendermaßen realisieren:



    Diese Funktion wurde unter der präpotenten Annahme programmiert, dein Problem verstanden zu haben. Sie liefert ein Array mit zwei Elementen: Benutzername und Passwort-Hash. Dir sollte aber bewusst sein, dass es einen Aufwand von (Anzahl existierender Benutzer) hoch (Anzahl Haare auf meiner Brust) benötigt und nicht empfehlenswert ist.

    PS: Ich bin stark behaart.

  • Es gibt immerhin etwa 24000 mögliche Nutzernamen

    Entweder ich versteh da wieder was nicht, oder das ist irgendwie merkwürdig. 24000 mögliche Nutzernamen?! Also wenn wir mal davon ausgehen dass Benutzer zumindest die 26 Zeichen des Alphabets zur Verfügung haben, und ein Benutzername nur (genau) lächerliche 4 Zeichen lang sein darf, dann ergibt das zumindest mittels meiner bescheidenen mathematischen Kenntnisse 26 hoch 4, also 456976 mögliche Benutzernamen. Das allein wäre schon mehr als 24000. Die Rechnung ist vielleicht völlig falsch, so oder so sind 24000 mögliche Benutzernamen ein Blödsinn, würd ich mal sagen.

    Und noch einmal zu den Passwörtern: Es ist ein viel größeres Sicherheitsrisiko, nicht 2x das gleiche Passwort zu erlauben, als andersrum. Es ist einfach so. Und das mit dem Benutzernamen in den MD5-Hash codieren ist ja auch ein Blödsinn. Wenn ein Angreifer bereits Vollzugriff auf die Datenbank hat, dann kann er ja die Benutzernamen selbst auch sehen. Wenn er keinen Zugriff auf die Datenbank hat und zum Beispiel mittels seinem Webbrowser brute force-Attacken durchführt, dann übernimmt das ja euer eigener Code, daß die Benutzernamen in den Hash codiert werden. Etc... Weiß nicht ob ich meine Meinung jetzt klar rübergebracht hab.


  • Man sollte nicht nur das Passwort alleine verschlüsseln, sondern entweder zusammen mit einen zufälligen String oder einfach dem Username

    Das ist soweit ein überlegter Ansatz. Der Grund dafür ist, dass jemand, der die Hashes in die Hand bekommt, diese nicht so schnell mittels brute-force knacken kann.
    Es geht dabei darum, dass der Angreifer nicht nur die Hashes, sondern auch die Erzeugung der Hashes knacken muss.
    Rainbow-Tables sind für den Angreifer damit faktisch wertlos.
    Wobei ich aber nicht viel davon halte, den Hash mit dem Usernamen zu verknüpfen. Es ist nämlich sehr wahrscheinlich, dass der Angreifer, wenn er an die Hashes gleangt ist, auch an die Usernamen herangekommen ist, was den Angriff kaum verzögert.
    Ausserdem sollte es sich nicht um einen einzigen String für die gesamte Verschlüsselung handeln. Den könnte der Angreifer wieder relativ schnell herausfinden, indem er selbst einen User (zu dem er dann natürlich das PW kennt) anlegt und dann den String knackt. Dieser String sollte also von bestimmten Kriterien abhängen und am besten bei jedem Hash variieren.
    Wenn man es weiter treiben will, dann darf auch ein Angreifer, der sogar an den Quellcode herangekommen ist, nichts nützliches aus diesem herausfinden dürfen.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!