Phil Z.: Wie PWs u. Kontodaten speichern, wie mit Salts umgehen?

Hallo.

Ich möchte bei meinem neuen Loginskript, die Passwörter in einer MySQL Datenbank schreiben.

Wie genau würdet ihr das tun?

Ich würde das so machen:
md5($pw.'dc237üsjü29');

Jedes Pw mit dem gleichen Salt der normal im Quelltext steht.

Aber ist das sicher genug?
Der Salt bei jedem gleich und als Klartext im PHP Quelltext?
Und ist md5 sicher genug?

Ich möchte mit dieser Methode PWs verschlüsseln.

DIe Kontodaten würde ich gerne anders verschlüsseln.

Ich generiere einen zufälligen schlüssel, mit diesem Schlüssel verschlüssel ich wiederum die Daten per Blowfish mit diesem Skript, das heißt also wenn jemand dieses Skript auch hat, und weiß das die Daten Blowfish sind und die Schlüssel aus der anderen Tabelle hat, hat er die Passwörter.

http://php-einfach.de/sonstiges_generator_blowfish.php

Den Schlüssel speicher ich in einer extra Tabelle, allerdings in der selben Datenbank.

Ist dies sicher? Oder sollte ich dort lieber Hash+Salt oder eine andere Verschlüsselungsmethode verwenden?

Liebe Grüße

Phil

  1. Hallo,

    Ich möchte bei meinem neuen Loginskript, die Passwörter in einer MySQL Datenbank schreiben.

    Wie genau würdet ihr das tun?

    Ich würde das so machen:
    md5($pw.'dc237üsjü29');

    Jedes Pw mit dem gleichen Salt der normal im Quelltext steht

    Dies wäre eine HMAC und kein Hash mit Salt mehr.
    Dies erhöht die Sicherheit erheblich, da ein Angreifer nun den Quelltext und die Db braucht.
    Hat man nur eine SQL Injection, wie es diese dutzenfach im phpBB2 gab, und kann nur die User-Hashs auslesen, ist eine HMAC sehr effektiv.
    Besser wäre eine salted HMAC, also sowas:
    $salt.md5($pw.'dc237üsjü29'.$salt);

    Den Schlüssel speicher ich in einer extra Tabelle, allerdings in der selben Datenbank.

    Dies hilft nicht viel. Schafft ein Angreifer per SQL Injection an die DB zu gelangen, kann er die Kontodaten + das Passwort aus der extra Tabelle auslesen.

    Du könntest die Tabellen für Blowfish berechnen und als PHP Code abspeichern und dann die Daten so abspeichern.

    Alternativ könntest du noch das Userpasswort als Passwort verwenden, d.h. die Kontodaten sind mit dem Userpasswort abgespeichert.
    Dafür musst du, wenn sich der User einlogt, sein PW in einer Session abspeichern um damit seine Daten entsprechend zu verschlüsseln/entschlüsseln..

    Probleme hierbei:
    _Du_ kommst nicht an die Kontodaten des Users. Für den aktiven Zahlungsverkehr müssten die Daten dann in einer anderen Table in Klartext (oder mit der obigen Methode) hinterlegt sein.

    Wenn du dich dafür entscheiden solltest, solltest du aber nicht Blowfish wählen, sondern einen anderen schlanken Algo.
    Auf der Seite wird auch XTEA angeboten, welcher sich gut eignen würde.

    Ist dies sicher? Oder sollte ich dort lieber Hash+Salt oder eine andere Verschlüsselungsmethode verwenden?

    Also auf der Seite wird auch ein Improved Hash Algorithm angeboten.
    Dies ist eigentlich einer der besten Möglichkeiten. Du hast eine salt sowie eine Key strengthening Methode und scheinbar kann man auch eine HMAC verwenden.

    Für die Kontodaten musst du abwegen. Optimal vom Schutz wäre wenn man das Userpasswort als Verschlüsselungskey verwendet, komfortabler wäre wenn du die berechneten P- und S-Boxen von Blowfish hardcoded als PHP Code hinterlegst.

    MFG

    1. Hallo.

      Besser wäre eine salted HMAC, also sowas:
      $salt.md5($pw.'dc237üsjü29'.$salt);

      Okay und $salt? woher kommt der? Auch aus dem QUelltext oder in einer Tabelle gespeichert oder in einem .txt Doc.?

      Probleme hierbei:
      _Du_ kommst nicht an die Kontodaten des Users. Für den aktiven Zahlungsverkehr müssten die Daten dann in einer anderen Table in Klartext (oder mit der obigen Methode) hinterlegt sein.

      Leider muss ich das aber...

      Wenn du dich dafür entscheiden solltest, solltest du aber nicht Blowfish wählen, sondern einen anderen schlanken Algo.
      Auf der Seite wird auch XTEA angeboten, welcher sich gut eignen würde.

      Danke, gut zu wissen.

      Ist dies sicher? Oder sollte ich dort lieber Hash+Salt oder eine andere Verschlüsselungsmethode verwenden?
      Also auf der Seite wird auch ein Improved Hash Algorithm angeboten.

      Klingt sehr gut. Danke.

      Für die Kontodaten musst du abwegen. Optimal vom Schutz wäre wenn man das Userpasswort als Verschlüsselungskey verwendet, komfortabler wäre wenn du die berechneten P- und S-Boxen von Blowfish hardcoded als PHP Code hinterlegst.

      Ich habe leider keine Ahnung wie ich das bewerkstelligen soll.

      lg, danke

      Phil

      1. Hallo Phil,

        Besser wäre eine salted HMAC, also sowas:
        $salt.md5($pw.'dc237üsjü29'.$salt);
        Okay und $salt? woher kommt der? Auch aus dem QUelltext oder in einer Tabelle gespeichert oder in einem .txt Doc.?

        Das Salt erstellst du für jeden Hash mehr oder weniger zufällig und speicherst das dann auch zusammen mit dem Hash. Das sorgt einfach nur dafür, dass das Passwort künstlich (und zufällig) verlängert wird, was das Benutzen von Rainbow-tables unmöglich macht. Bei einem "festen Salt", Klaus nennt das anscheinend "HMAC", könnte man im einzelfall ne neue Rainbow Table mit speziell diesem "Salt" erstellen, wenn du ein zufälliges Salt nimmst, ist das nicht möglich.

        Es ist in dem Fall auch egal, wenn der Hacker das Salt auslesen kann, das Tailstück hilft ja nicht bei der suche nach dem ganzen passenden Klartext.

        Jonathan

        1. Hi.

          Danke, jetzt muss ich aber noch wissen wie ich das mit den Kontodaten am besten handhabe!

        2. Hallo,

          Bei einem "festen Salt", Klaus nennt das anscheinend "HMAC", könnte man im einzelfall ne neue Rainbow Table mit speziell diesem "Salt" erstellen, wenn du ein zufälliges Salt nimmst, ist das nicht möglich.

          Das nenn nicht nur ich so, sondern ist ein etablierter Begriff:
          HMAC

          Die Sicherheit von HMAC basiert einfach darauf, dass man diese 'feste Salt' benötigt um zu testen ob ein Hash zu einem Passwort gehört oder nicht.
          Ist die 'feste Salt' ausreichend sicher, sprich lang genug, ist es einem Angreifer praktisch unmöglich irgendwelche Passwörter zu knacken. Er müsste zuerst diese feste Salt herrausfinden.

          Wenn er aber nur die Datenbank hat, z.B. über SQL Injections oder über menschliche Fehler, wie es beim Woltlab Board war, kann er mit den Hashs nichts anfangen.

          MFG

      2. Hallo,

        Probleme hierbei:
        _Du_ kommst nicht an die Kontodaten des Users. Für den aktiven Zahlungsverkehr müssten die Daten dann in einer anderen Table in Klartext (oder mit der obigen Methode) hinterlegt sein.

        Leider muss ich das aber...

        Gut, dann besser ein hardcoded Blowfish/XTEA o.ä., ist leichter in der Handhabung, das stimmt.

        Für die Kontodaten musst du abwegen. Optimal vom Schutz wäre wenn man das Userpasswort als Verschlüsselungskey verwendet, komfortabler wäre wenn du die berechneten P- und S-Boxen von Blowfish hardcoded als PHP Code hinterlegst.

        Ich habe leider keine Ahnung wie ich das bewerkstelligen soll.

        Das Key Setup von Blowfish sieht ja so aus, dass alle Einträge aus der P-Box und den S-Boxen ersetzt werden und nur diese Boxen sind entscheidend für die Verschlüsselung.
        Man könnte sie also normal generieren und dann per PHP die einzelnen Einträge der Boxen ausgeben, am besten so, dass die Ausgabe ein gültiger PHP Code ist für die P- und S-Boxen.

        Alternativ kann man auch XTEA verwenden. Dort hast du ja kein aufwendiges Key-Setup, deswegen reicht es, wenn du das Passwort für XTEA fest im Code hinterlegt hast.

        Also in etwa so:
        $key = "bHnk4....";

        Natürlich hängt die Sicherheit hier davon ab, dass es einem Angreifer unmöglich sein sollte, deinen Source Code zu bekommen.
        Über SQL Injections oder über Datenbank-Dumps (wie bei Woltlab) würde man also nicht an die Daten kommen, bekommt man aber einen FTP Zugang, kann man natürlich auch das hardcoded Passwort/Key auslesen und alles bequem entschlüsseln.

        MFG

    2. Moin!

      Also auf der Seite wird auch ein Improved Hash Algorithm angeboten.
      Dies ist eigentlich einer der besten Möglichkeiten. Du hast eine salt sowie eine Key strengthening Methode und scheinbar kann man auch eine HMAC verwenden.

      Ich bin mir bei der Idee, einfach MD5 auf das Ergebnis von MD5 anzuwenden, einfach nicht sicher, ob das nicht doch irgendwelche noch nicht entdeckten Ärgerlichkeiten birgt.

      Schließlich bildet man damit eine bekannte Menge (nämlich alle 160-Bit-Zahlen in hexadezimaler Darstellung) wieder auf eine bekannte Menge (ebenfalls 160-Bit-Zahlen in Hex-Darstellung) - das halte ich qualitativ für etwas anderes, als wenn man beliebige Strings abbildet. Es würde sich da fast schon lohnen, dafür eine Rainbow-Tabelle auszurechnen, denn mit der kann man dann vermutlich jede beliebige Anzahl von Runden zurückrechnen, ohne den geringsten Mehraufwand.

      Und sollte das tatsächlich mal jemand machen, kämen für ihn vielleicht interessante Muster zum Vorschein, die evtl. noch ganz andere Angriffsmethoden denkbar machen. :)

      - Sven Rautenberg

      --
      "Love your nation - respect the others."
      1. Hallo,

        Es würde sich da fast schon lohnen, dafür eine Rainbow-Tabelle auszurechnen, denn mit der kann man dann vermutlich jede beliebige Anzahl von Runden zurückrechnen, ohne den geringsten Mehraufwand.

        Dies ist nicht ganz richtig, Rainbowtables müssen auch berechnet werden, wenn man also md5 vom md5 Hash bildet, würde der Aufwand für die Generierung der Tables sich in etwa verdoppeln.
        Allerdings gegen Rainbow Tables ist das auch gar nicht gedacht und würde es auch nicht effektiv verhindern.

        Gegen Rainbow Tables verwendet man normalerweise zufällige salts, dieser md5(md5()) schützt dann gegen Brute Force.

        Und sollte das tatsächlich mal jemand machen, kämen für ihn vielleicht interessante Muster zum Vorschein, die evtl. noch ganz andere Angriffsmethoden denkbar machen. :)

        Naja ganz unbekannt ist die Methode gerade nicht:
        Hash based key strengthening oder für eine bessere Analyse von solch einer Methode:
        Secure Applications of Low-Entropy Keys - Section 4 (Seite 5)

        MFG

  2. Moin!

    Ich würde das so machen:
    md5($pw.'dc237üsjü29');

    Jedes Pw mit dem gleichen Salt der normal im Quelltext steht.

    Aber ist das sicher genug?
    Der Salt bei jedem gleich und als Klartext im PHP Quelltext?
    Und ist md5 sicher genug?

    Erstmal zu MD5: Wenn du nichts besseres hast, ist MD5 immer noch sicher genug. Aber eigentlich überall, wo MD5 existiert, existiert auch SHA-1. Das macht längere Hashes und deshalb mehr Aufwand.

    Längere Hashes sind immer besser. SHA256, SHA384 oder SHA512 stehen dir in PHP zur Verfügung, wenn die Erweiterung "Hash" integriert ist.

    Zum Salt: Man muß davon ausgehen, dass ein Angreifer in jedem Fall den Salzwert in Erfahrung bringen kann. Ein konstanter Wert bietet ihm den Vorteil, dass er nicht für jedes Passwort komplett neu suchen muß, sondern die gesamte Passworttabelle in einem Abwasch durchchecken kann. Er prüft dann alle generierten Passworte mit 1, 2, 3, ... X Zeichen (oder Wörterbuchtabellen) plus dem Salt (egal ob es vorn oder hinten angehängt wird) - der dadurch generierte Hashwert wird dann mit allen verfügbaren Passworthashes verglichen, anstatt nur mit genau einem.

    Sofern sich in der Datenbank überhaupt irgendein brute-force-knackbares Passwort befindet (dem kannst du durch eine geeignete Prüfung entgegenwirken: Mindestlänge und z.B. müssen auch Ziffern enthalten sein), ist ein konstantes Salt natürlich nicht so schön.

    Da du das Salt aber ja nicht mehr aus dem Hashwert zurückrechnen kannst, mußt du auch ein pro Passwort zufällig generiertes Salt irgendwo im Klartext abspeichern - das würde also dem Angreifer ebenfalls in die Hände fallen, wenn er den Passworthash abgreifen kann. Und es vergrößert seinen Aufwand nur marginal: Statt z.B. alle 50 Accounts mit einmal Rechnen zu checken, muß er jeden Account einzeln checken - also wird er vermutlich 50 Rechner benutzen. Böse Angreifer haben sowas, oder können es sich beschaffen.

    DIe Kontodaten würde ich gerne anders verschlüsseln.

    Ich generiere einen zufälligen schlüssel, mit diesem Schlüssel verschlüssel ich wiederum die Daten per Blowfish mit diesem Skript, das heißt also wenn jemand dieses Skript auch hat, und weiß das die Daten Blowfish sind und die Schlüssel aus der anderen Tabelle hat, hat er die Passwörter.

    http://php-einfach.de/sonstiges_generator_blowfish.php

    Den Schlüssel speicher ich in einer extra Tabelle, allerdings in der selben Datenbank.

    Ist dies sicher? Oder sollte ich dort lieber Hash+Salt oder eine andere Verschlüsselungsmethode verwenden?

    Bei reversibler symmetrischer Verschlüsselung hast du das grundsätzliche Problem, dass du auf dem System, was die Verschlüsselung herstellt, alle Zutaten vorliegen haben mußt, mit dem man auch wieder Entschlüsseln kann. Im Falle eines Eindringens von Unbefugten sind also im Prinzip alle Daten als kompromittiert anzusehen.

    Die einzige Lösung dagegen wäre ein asymmetrisches Verfahren wie PGP bzw. GnuPG. Hier gibt es einen öffentlichen Schlüssel, mit dem man verschlüsselt, und einen ganz anderen, privaten Schlüssel, mit dem man den Inhalt wieder entschlüsseln kann. Sofern du also nicht darauf angewiesen bist, an die Kontodaten auch vom Server her wieder heranzukommen, könnte sich diese Methode anbieten.

    Andererseits: Wenn du serverseitig nicht an die Kontodaten ran mußt, dann müssen die auch nicht auf dem Server liegen. Was wiederum eher dagegenspricht, dass du serverseitig nicht ran mußt.

    Andererseits: Kontodaten sind nicht unbedingt als supergeheim anzusehen, sie sind durch den alltäglichen Zahlungsverkehr eigentlich weiträumig bekannt - wenngleich nicht der gesamten Welt, so aber doch einer ausreichenden Zahl von Menschen. Das Abgreifen dieser Daten wäre also zwar extrem ärgerlich, aber von weitaus geringerem Übel als der Verlust des Passwortes.

    Nichtsdestotrotz solltest du den Aufwand gerne so hoch wie möglich treiben.

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. Hallo,
      »»Das macht längere Hashes und deshalb mehr Aufwand.

      Längere Hashes sind immer besser. SHA256, SHA384 oder SHA512 stehen dir in PHP zur Verfügung, wenn die Erweiterung "Hash" integriert ist.

      Das ist so nicht richtig.

      Man kann eine Hash-Funktion haben, die evt. 4096 Bit output hat, dennoch deutlich weniger Aufwand macht als MD5 mit 128 Bit.
      Denn der Aufwand für die Berechnung der Prüfsumme hängt nicht von der Ausgabe ab, sondern von der Komplexilität des Algorithmus.
      SHA1 ist im Vergleich zu MD5 nur wenig (Zeit)aufwendiger in der Berechnung, trotz des mehr an Outputs.

      Auf SHA-512 umzusatteln, weil dieser aufwendiger in der Berechnung ist, ist der falsche Ansatz.
      Besser ist Key strengthening

      PS:
      Der Vorteil von längeren Hash-Algos. ist i.d.R. dass diese besser gegen Kollisionen resistent sind, dies ist aber bei der Wahl ob MD5, SHA1 oder SHA-256 momentan absolut egal.

      MFG