webentwicklung-frage-antwort-db.com.de

Best Practices: Passwörter salzen und würfeln?

Ich stieß auf eine Diskussion, in der ich erfuhr, dass das, was ich getan hatte, Passwörter nicht nur salzte, sondern löste, und seitdem habe ich begonnen, beides mit einer Funktion wie der folgenden zu tun:

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

Ignorieren Sie den gewählten Hash-Algorithmus (ich möchte, dass es sich um eine Diskussion über Salt & Peppers und nicht um bestimmte Algorithmen handelt, aber ich verwende einen sicheren Algorithmus). Ist dies eine sichere Option oder sollte ich etwas anderes tun? Für diejenigen, die mit den Begriffen nicht vertraut sind:

  • Ein salt ist ein zufällig generierter Wert, der normalerweise mit der Zeichenfolge in der Datenbank gespeichert wird, um die Verwendung von Hash-Tabellen zum Knacken von Kennwörtern zu verhindern. Da jedes Passwort ein eigenes Salt hat, müssen sie alle einzeln gezwungen werden, um sie zu knacken. Da das Salt jedoch mit dem Kennwort-Hash in der Datenbank gespeichert wird, bedeutet ein Datenbank-Kompromiss, dass beide verloren gehen.

  • Ein Pfeffer ist ein standortweiter statischer Wert, der separat von der Datenbank gespeichert wird (normalerweise fest im Quellcode der Anwendung codiert) und der geheim sein soll. Es wird verwendet, um zu verhindern, dass bei einer Kompromittierung der Datenbank die Kennworttabelle der gesamten Anwendung brachial erzwungen werden kann.

Fehlt mir etwas und ist das Salting & Pepping meiner Passwörter die beste Option, um die Sicherheit meines Benutzers zu schützen? Gibt es eine potenzielle Sicherheitslücke bei dieser Vorgehensweise?

Hinweis: Nehmen Sie zum Zweck der Erörterung an, dass die Anwendung und die Datenbank auf separaten Computern gespeichert sind, keine Kennwörter gemeinsam nutzen usw., sodass ein Verstoß gegen den Datenbankserver nicht automatisch einen Verstoß gegen das bedeutet Anwendungsserver.

137
Glitch Desire

Okay. Da ich darüber schreiben muss vorbei und vorbei , werde ich nur eine letzte kanonische Antwort auf Pfeffer geben.

Der offensichtliche Vorteil von Paprika

Es liegt auf der Hand, dass Paprika die Sicherheit von Hash-Funktionen erhöhen sollte. Ich meine, wenn der Angreifer nur Ihre Datenbank bekommt, sollten die Passwörter Ihrer Benutzer sicher sein, oder? Scheint logisch, oder?

Deshalb glauben so viele Menschen, dass Paprika eine gute Idee ist. Es macht Sinn".

Die Realität der Paprika

In den Bereichen Sicherheit und Kryptografie reicht "Sinn machen" nicht aus. Etwas muss nachweisbar und sinnvoll sein, damit es als sicher gilt. Außerdem muss es auf wartbare Weise implementiert werden können. Das sicherste System, das nicht gewartet werden kann, wird als unsicher eingestuft (wenn ein Teil dieser Sicherheit ausfällt, fällt das gesamte System auseinander).

Und Paprika passt weder zu den nachweisbaren noch zu den wartbaren Modellen ...

Theoretische Probleme mit Paprika

Nachdem wir die Bühne bereitet haben, schauen wir uns an, was mit Paprika los ist.

  • Ein Hash in einen anderen zu füttern kann gefährlich sein.

    In Ihrem Beispiel tun Sie hash_function($salt . hash_function($pepper . $password)).

    Wir wissen aus der Vergangenheit, dass das "Einspeisen" eines Hash-Ergebnisses in eine andere Hash-Funktion die Gesamtsicherheit verringern kann. Der Grund ist, dass beide Hash-Funktionen zum Angriffsziel werden können.

    Aus diesem Grund verwenden Algorithmen wie PBKDF2 spezielle Operationen, um sie zu kombinieren (in diesem Fall hmac).

    Der Punkt ist, dass es zwar keine große Sache ist, es aber auch keine triviale Sache ist, einfach herumzuwerfen. Kryptosysteme sind so konzipiert, dass Fälle vermieden werden, die funktionieren sollten, und konzentrieren sich stattdessen auf Fälle, die funktionieren sollten.

    Dies mag zwar rein theoretisch erscheinen, ist es aber in der Tat nicht. Zum Beispiel Bcrypt kann keine willkürlichen Passwörter akzeptieren . Das Übergeben von bcrypt(hash(pw), salt) kann in der Tat zu einem weitaus schwächeren Hash führen als bcrypt(pw, salt), wenn hash() eine Binärzeichenfolge zurückgibt.

  • Gegen Design arbeiten

    Die Art und Weise, wie bcrypt (und andere Passwort-Hashing-Algorithmen) entwickelt wurden, ist die Arbeit mit einem Salt. Das Konzept eines Pfeffers wurde nie eingeführt. Das mag trivial erscheinen, ist es aber nicht. Der Grund ist, dass ein Salz kein Geheimnis ist. Es ist nur ein Wert, der einem Angreifer bekannt sein kann. Ein Pfeffer hingegen ist per definitionem ein kryptografisches Geheimnis.

    Die aktuellen Passwort-Hashing-Algorithmen (bcrypt, pbkdf2 usw.) sind so konzipiert, dass sie nur einen geheimen Wert (das Passwort) enthalten. Das Hinzufügen eines weiteren Geheimnisses zum Algorithmus wurde überhaupt nicht untersucht.

    Das heißt nicht, dass es nicht sicher ist. Das heißt, wir wissen nicht, ob es sicher ist. Und die allgemeine Empfehlung für Sicherheit und Kryptografie lautet: Wenn wir es nicht wissen, ist es das nicht.

    Solange Algorithmen nicht von Kryptographen für die Verwendung mit geheimen Werten (Peppers) entwickelt und überprüft wurden, sollten aktuelle Algorithmen nicht mit ihnen verwendet werden.

  • Komplexität ist der Feind der Sicherheit

    Ob Sie es glauben oder nicht, Komplexität ist der Feind der Sicherheit . Einen Algorithmus so zu gestalten, dass er komplex aussieht, kann sicher sein oder auch nicht. Aber die Chancen sind sehr groß, dass es nicht sicher ist.

Erhebliche Probleme mit Paprika

  • Es ist nicht wartbar

    Ihre Implementierung von Paprika schließt die Möglichkeit aus, den Pfefferschlüssel zu drehen. Da der Pfeffer als Eingang für die Einwegfunktion verwendet wird, können Sie den Pfeffer während der gesamten Lebensdauer des Werts nicht ändern. Dies bedeutet, dass Sie sich einige Wonky-Hacks einfallen lassen müssen, um die Schlüsselrotation zu unterstützen.

    Dies ist äußerst wichtig, da es erforderlich ist, wenn Sie kryptografische Geheimnisse speichern. Das Fehlen eines Mechanismus zum Drehen von Schlüsseln (in regelmäßigen Abständen und nach einem Verstoß) ist eine große Sicherheitslücke.

    Und Ihr aktueller Pfefferansatz würde erfordern, dass jeder Benutzer sein Passwort entweder durch eine Rotation vollständig ungültig macht oder bis zu seinem nächsten Login wartet, um zu rotieren (was möglicherweise niemals der Fall ist) ...

    Das macht Ihren Ansatz im Grunde zu einem sofortigen No-Go.

  • Sie müssen Ihre eigene Krypto rollen

    Da kein aktueller Algorithmus das Konzept eines Pfeffers unterstützt, müssen Sie entweder Algorithmen erstellen oder neue erfinden, um einen Pfeffer zu unterstützen. Und wenn Sie nicht sofort sehen können, warum das eine wirklich schlechte Sache ist:

    Jeder, vom ahnungslosesten Amateur bis zum besten Kryptographen, kann einen Algorithmus erstellen, den er selbst nicht brechen kann.

    [~ # ~] niemals [~ # ~] eigene Krypto rollen ...

Der bessere Weg

Von den oben beschriebenen Problemen gibt es also zwei Möglichkeiten, mit der Situation umzugehen.

  • Verwenden Sie einfach die vorhandenen Algorithmen

    Wenn Sie bcrypt oder scrypt korrekt verwenden (mit hohen Kosten), sollten alle bis auf die schwächsten Wörterbuchkennwörter statistisch sicher sein. Der aktuelle Rekord für das Hashing von bcrypt zu Kosten von 5 liegt bei 71.000 Hashes pro Sekunde. Bei dieser Rate würde es Jahre dauern, bis ein 6-stelliges Zufallspasswort geknackt wird. Unter Berücksichtigung meiner empfohlenen Mindestkosten von 10 werden die Hashes pro Sekunde um den Faktor 32 reduziert. Wir sprechen also nur von 2200 Hashes pro Sekunde. Bei dieser Rate können sogar einige Wörterbuchphrasen oder -änderungen sicher sein.

    Außerdem sollten wir an der Tür nach diesen schwachen Klassen von Passwörtern suchen und sie nicht zulassen. Wenn das Knacken von Passwörtern weiter fortgeschritten ist, sollten wir auch die Anforderungen an die Passwortqualität erfüllen. Es ist immer noch ein statistisches Spiel, aber mit einer geeigneten Speichertechnik und sicheren Passwörtern sollte jeder praktisch sehr sicher sein ...

  • Verschlüsseln Sie den Ausgabe-Hash vor dem Speichern

    Im Sicherheitsbereich gibt es einen Algorithmus, der so konzipiert ist, dass er alles verarbeitet, was wir oben gesagt haben. Es ist eine Blockchiffre. Es ist gut, weil es reversibel ist, so dass wir Schlüssel drehen können (yay! Wartbarkeit!). Es ist gut, weil es wie geplant verwendet wird. Es ist gut, weil es dem Benutzer keine Informationen gibt.

    Schauen wir uns diese Zeile noch einmal an. Angenommen, ein Angreifer kennt Ihren Algorithmus (der für die Sicherheit erforderlich ist, andernfalls ist es Sicherheit durch Unbekanntheit). Mit einem herkömmlichen Pfeffer-Ansatz kann der Angreifer ein Sentinel-Passwort erstellen und den Pfeffer brutal erzwingen, da er das Salz und die Ausgabe kennt. Ok, das ist ein langer Schuss, aber es ist möglich. Mit einer Chiffre bekommt der Angreifer nichts. Und da das Salz zufällig ist, hilft ihm ein Sentinel-Passwort nicht einmal. Das Beste, was ihnen bleibt, ist, die verschlüsselte Form anzugreifen. Das bedeutet, dass sie zuerst Ihren verschlüsselten Hash angreifen müssen, um den Verschlüsselungsschlüssel wiederherzustellen, und dann die Hashes angreifen müssen. Aber es gibt eine Menge Nachforschungen über das Angreifen von Chiffren, also wollen wir uns darauf verlassen.

TL/DR

Verwenden Sie keine Paprika. Es gibt eine Vielzahl von Problemen, und es gibt zwei bessere Möglichkeiten: Sie müssen kein serverseitiges Geheimnis verwenden (ja, es ist in Ordnung) und den Ausgabehash vor dem Speichern mit einer Blockverschlüsselung verschlüsseln.

295
ircmaxell

Zunächst sollten wir über den genauen Vorteil eines Pfeffers sprechen :

  • Der Pfeffer kann schwache Passwörter vor einem Wörterbuchangriff schützen, in dem der Angreifer Lesezugriff auf die Datenbank (die die Hashes enthält) hat, aber keinen Zugriff auf den Quellcode mit dem Pfeffer.

Ein typisches Szenario wäre SQL-Injection, weggeworfene Backups, verworfene Server ... Diese Situationen sind nicht so ungewöhnlich, wie es sich anhört, und oft nicht unter Ihrer Kontrolle (Server-Hosting). Wenn du benutzt...

  • Ein eindeutiges Salz pro Passwort
  • Ein langsamer Hashalgorithmus wie BCrypt

... sichere Passwörter sind gut geschützt. Unter diesen Bedingungen ist es nahezu unmöglich, ein sicheres Passwort zu erzwingen, selbst wenn das Salz bekannt ist. Das Problem sind die schwachen Passwörter, die Teil eines Brute-Force-Wörterbuchs sind oder Ableitungen davon. Bei einem Wörterbuchangriff werden diese sehr schnell aufgedeckt, da Sie nur die am häufigsten verwendeten Kennwörter testen.

Die zweite Frage ist wie man den Pfeffer aufträgt ?

Eine häufig empfohlene Methode zum Anwenden eines Pfeffers ist das Kombinieren des Kennworts und des Pfeffers, bevor dieser an die Hash-Funktion übergeben wird:

$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);

Es gibt jedoch noch einen anderen, noch besseren Weg:

$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);

Dies ermöglicht nicht nur das Hinzufügen eines serverseitigen Geheimnisses, sondern auch das Austauschen des $ serverSideKey, falls dies erforderlich sein sollte. Diese Methode erfordert etwas mehr Arbeit, aber wenn der Code einmal existiert (Bibliothek), gibt es keinen Grund, ihn nicht zu verwenden.

23
martinstoeckli

Der Sinn von Salz und Pfeffer besteht darin, die Kosten für eine vorberechnete Kennwortsuche, die als Rainbow-Tabelle bezeichnet wird, zu erhöhen.

Im Allgemeinen ist es schwierig, eine Kollision für einen einzelnen Hash zu finden (vorausgesetzt, der Hash ist sicher). Bei kurzen Hashes ist es jedoch möglich, mit dem Computer alle möglichen Hashes für eine Suche auf einer Festplatte zu generieren. Dies nennt man einen Regenbogentisch. Wenn Sie eine Rainbow-Tabelle erstellen, können Sie in die Welt hinausgehen und schnell plausible Passwörter für (ungesalzene, nicht gepfefferte) Hashes finden.

Der Sinn eines Pfeffers ist es, die Rainbow-Tabelle so zu gestalten, dass sie Ihre Passwortliste eindeutig macht. Verschwenden Sie also mehr Zeit für den Angreifer, um die Rainbow-Tabelle zu erstellen.

Das Ziel des Salzes ist es jedoch, die Rainbow-Tabelle für jeden Benutzer eindeutig zu machen, was die Komplexität des Angriffs weiter erhöht.

Wirklich ist der Punkt der Computersicherheit fast nie, es (mathematisch) unmöglich zu machen, nur mathematisch und physikalisch unpraktisch (zum Beispiel in sicheren Systemen würde es die gesamte Entropie im Universum (und mehr) erfordern, um das Passwort eines einzelnen Benutzers zu berechnen).

2
Aron

Das Speichern eines fest codierten Werts in Ihrem Quellcode hat keine Sicherheitsrelevanz. Es ist Sicherheit durch Dunkelheit.

Wenn ein Hacker Ihre Datenbank erwirbt, kann er Ihre Benutzerkennwörter brutal erzwingen. Es wird nicht lange dauern, bis dieser Hacker Ihren Pfeffer identifiziert, wenn er es schafft, ein paar Passwörter zu knacken.

1
Sven