Zum Inhalt springen

Unsichere Speicherung von Passwörtern

CWE-916CWE-759CWE-257OWASP A02:2021Aktualisiert 4. September 20265 Min. Lesezeit

Passwörter gehören mit einer Hashfunktion gespeichert, die bewusst langsam ist und je Nutzer ein eigenes Salt verwendet: Argon2id, scrypt oder bcrypt. Schnelle Hashverfahren wie MD5 und SHA-256 lassen sich mit heutiger Hardware massenhaft zurückrechnen, und Verschlüsselung ist ungeeignet, weil der Schlüssel immer irgendwo erreichbar ist.

Von allen Daten in Ihrer Datenbank gibt es eine Kategorie, die Sie selbst nie lesen können müssen: Passwörter. Sie müssen lediglich feststellen können, ob jemand das richtige eingegeben hat. Dieser Unterschied, prüfen statt zurückholen, bestimmt, wie die Speicherung aussehen muss. In diesem Artikel lesen Sie, warum das so oft schiefgeht und wie Sie es beheben, ohne Ihre Nutzer damit zu behelligen.

Was ist unsichere Passwortspeicherung?

Unsichere Speicherung von Passwörtern bedeutet, dass die gespeicherte Form das ursprüngliche Passwort in dem Moment unzureichend schützt, in dem ein Angreifer die Datenbank in die Hände bekommt. Das ist die Annahme, von der Sie ausgehen müssen: nicht ob die Datenbank je ausläuft, sondern was dann geschieht.

In der Praxis kommen drei Varianten vor. Die schwerwiegendste ist die Speicherung in lesbarer Form, bei der das Passwort buchstäblich in einer Spalte steht. Danach folgt die Verschlüsselung, die besser wirkt, als sie ist: Verschlüsselung ist umkehrbar, es existiert also irgendwo ein Schlüssel, und der liegt in der Praxis auf demselben Server oder in derselben Konfiguration. Und schließlich die häufigste: das Hashen mit einem dafür ungeeigneten Verfahren wie MD5, SHA-1 oder SHA-256, mit oder ohne Salt.

Letzteres bedarf einer Erläuterung, denn diese Funktionen sind nicht “kaputt”. Sie sind auf Geschwindigkeit ausgelegt, und für die Prüfung der Unversehrtheit von Dateien ist das eine Tugend. Für Passwörter ist es ein Mangel: Ein Angreifer mit einer gestohlenen Tabelle kann mit einer gewöhnlichen Grafikkarte Milliarden Kandidaten hindurchjagen. Ein Passwort-Hash muss langsam sein, langsam genug, um bei einer einzelnen Anmeldung kaum bemerkbar zu sein, und lähmend bei Milliarden.

Wie wird unsichere Passwortspeicherung ausgenutzt?

Verwundbar:

// Schnelles Hashverfahren, festes oder fehlendes Salt
const crypto = require('node:crypto');

function speicherePasswort(nutzerId, passwort) {
  const hash = crypto.createHash('sha256').update(passwort).digest('hex');
  return db.query('UPDATE nutzer SET hash = ? WHERE id = ?', [hash, nutzerId]);
}

Zwei Probleme zugleich. SHA-256 ist zu schnell, und es gibt kein Salt, wodurch gleiche Passwörter gleiche Hashwerte erhalten. Letzteres bedeutet, dass ein Angreifer auf einen Blick sieht, welche Nutzer dasselbe Passwort haben, und dass fertige Tabellen mit vorab berechneten Hashwerten unmittelbar nutzbar sind. Eine Liste von zehn Millionen häufig verwendeten Passwörtern lässt sich auf diese Weise binnen Sekunden gegen die gesamte Datenbank abgleichen.

Sicher:

const argon2 = require('argon2');

// Parameter auf Ihre Hardware abstimmen: Ziel etwa 0,5 Sekunden je Hash
const OPTIONEN = {
  type: argon2.argon2id,
  memoryCost: 19456,   // 19 MiB
  timeCost: 2,
  parallelism: 1,
};

async function speicherePasswort(nutzerId, passwort) {
  const hash = await argon2.hash(passwort, OPTIONEN);   // Salt steckt in der Ausgabe
  await db.query('UPDATE nutzer SET hash = ? WHERE id = ?', [hash, nutzerId]);
}

async function pruefe(nutzer, passwort) {
  if (!await argon2.verify(nutzer.hash, passwort)) return false;

  // Gelegenheit gleich nutzen, um zu migrieren oder zu verstärken
  if (argon2.needsRehash(nutzer.hash, OPTIONEN)) {
    await speicherePasswort(nutzer.id, passwort);
  }
  return true;
}

Argon2id ist bewusst langsam und speicherintensiv, was Angriffe mit Grafikkarten erheblich verteuert. Das Salt wird automatisch erzeugt und in die Ausgabezeichenkette aufgenommen, Sie brauchen dafür also keine eigene Spalte. Die Prüfung mit needsRehash ist das Detail, das Migrationen schmerzlos macht: Bei jeder erfolgreichen Anmeldung wird geprüft, ob der gespeicherte Hashwert noch den aktuellen Parametern entspricht, und falls nicht, wird er stillschweigend ersetzt.

Ist Argon2id nicht verfügbar, sind scrypt und bcrypt gute Alternativen. Bei bcrypt gilt ein Hinweis: Eingaben über 72 Byte werden abgeschnitten, hashen Sie lange Passwortsätze daher zuerst mit SHA-256, bevor Sie sie bcrypt übergeben.

Speichern Sie Passwörter in lesbarer oder verschlüsselter Form, gehen Sie davon aus, dass jedes Passwort in der Datenbank kompromittiert ist, sobald diese ausläuft. Da Menschen Passwörter wiederverwenden, trifft ein solches Leck auch Konten Ihrer Nutzer bei anderen Diensten. Damit wird es meldepflichtig und bringt Ihre Organisation in die Lage, Dritten Schaden zugefügt zu haben.

Welche Auswirkungen hat unsichere Passwortspeicherung?

Der Schweregrad ist hoch bis kritisch, und das unterscheidet diesen Befund von den meisten anderen dieser Kategorie. Der Grund liegt darin, dass die Folge sich erst bei einem anderen Vorfall zeigt, dann jedoch vollständig ist.

Läuft die Datenbank aus, über SQL-Injection, eine falsch eingerichtete Sicherung, einen gestohlenen Laptop oder einen Mitarbeiter mit zu weit reichenden Rechten, entscheidet allein die Speicherform darüber, was ein Angreifer damit anfangen kann. Bei Argon2id mit sinnvollen Parametern kostet das Knacken eines einzigen starken Passworts unbezahlbar viel Rechenzeit. Bei MD5 ohne Salt ist die gesamte Tabelle binnen eines Tages in lesbare Passwörter umgewandelt.

Der Schaden bleibt zudem nicht bei Ihnen. Da die Wiederverwendung von Passwörtern weit verbreitet ist, verschaffen geknackte Passwörter Zugang zu E-Mail-Konten, Onlineshops und Geschäftssystemen derselben Nutzer. Ein Leck bei Ihrer Organisation wird damit zum Problem Dritter, mit entsprechender Meldepflicht nach der DSGVO und einem Reputationsschaden, der über den Vorfall hinausreicht. Anders als bei vielen Schwachstellen lässt sich im Nachhinein zudem wenig ausrichten: Einen offengelegten Hashwert können Sie nicht zurücknehmen.

Wie spürt man unsichere Passwortspeicherung auf?

Dies ist ein Befund, der von außen selten sichtbar ist; er kommt bei einer Quellcodeprüfung, einer Konfigurationsbeurteilung oder einem Gespräch mit dem Entwicklungsteam ans Licht. Die Frage nach dem verwendeten Verfahren gehört deshalb standardmäßig in den Umfang einer Sicherheitsuntersuchung.

Es gibt allerdings indirekte Anzeichen. Eine Anwendung, die eine Höchstlänge von etwa sechzehn Zeichen vorgibt oder Sonderzeichen ablehnt, verarbeitet das Passwort vermutlich nicht als undurchsichtige Eingabe. Eine Funktion zur Passwortwiederherstellung, die das alte Passwort per E-Mail zuschickt, beweist, dass es rücklesbar gespeichert ist, ein unmittelbar nachweisbarer Befund. Auch eine auffällig schnelle Antwort auf einen Anmeldeversuch kann darauf hindeuten, dass keine aufwendige Hashfunktion ausgeführt wird.

Bei einer Prüfung werden zusätzlich die Parameter betrachtet: Ein bcrypt mit zu niedrigem Kostenfaktor oder ein Argon2 mit minimalen Speichereinstellungen bietet deutlich weniger, als es scheint. Ebenso wird geprüft, ob der Vergleich zeitsicher erfolgt und ob ein Migrationspfad zu stärkeren Parametern besteht. AssistSec berücksichtigt diese Punkte bei einer Code-Prüfung oder Konfigurationsbeurteilung, denn ein Penetrationstest von außen hat hier naturgemäß nur begrenzte Sicht.

Wie verhindert man unsichere Passwortspeicherung?

  • Verwenden Sie Argon2id zum Hashen von Passwörtern, mit scrypt oder bcrypt als Alternativen.
  • Stimmen Sie die Parameter auf Ihre Hardware ab; zielen Sie auf etwa eine halbe Sekunde Rechenzeit je Hash.
  • Verwenden Sie je Passwort ein eindeutiges, zufälliges Salt; moderne Verfahren regeln das selbst.
  • Speichern Sie Passwörter nie lesbar oder verschlüsselt, auch nicht “vorübergehend” oder in Protokolldateien.
  • Hashen Sie lange Eingaben bei Verwendung von bcrypt zuerst mit SHA-256, wegen der Grenze von 72 Byte.
  • Berechnen Sie den Hashwert bei jeder erfolgreichen Anmeldung neu, sobald Parameter oder Verfahren verstärkt wurden.
  • Erwägen Sie einen Pepper in einem Schlüsseltresor als zusätzliche Schicht über dem Hashwert.
  • Versenden Sie nie ein bestehendes Passwort per E-Mail; arbeiten Sie ausschließlich mit einem kurzlebigen Wiederherstellungslink.
  • Vergleichen Sie Hashwerte mit einer zeitsicheren Funktion und protokollieren Sie bei einem Fehlversuch nie den eingegebenen Wert.

Quellen

Häufige Fragen

Warum ist ein schnelles Verfahren wie SHA-256 ungeeignet?

Gerade weil es schnell ist. Moderne Grafikkarten berechnen Milliarden pro Sekunde, wodurch ein Angreifer mit einer gestohlenen Datenbank enorme Mengen an Kandidaten durchprobieren kann. Ein Passwort-Hash sollte bewusst langsam und speicherintensiv sein, damit jeder Versuch messbar kostet.

Muss ich das Salt geheim halten?

Nein, ein Salt muss nicht geheim sein; es muss je Passwort eindeutig sein. Sein Zweck ist zu verhindern, dass gleiche Passwörter gleiche Hashwerte erhalten und dass vorab berechnete Tabellen nutzbar sind. Moderne Verfahren wie bcrypt und Argon2id nehmen das Salt einfach in die Ausgabezeichenkette auf.

Wie migriere ich von einem veralteten Verfahren?

Ohne Aufwand für die Nutzer: Berechnen Sie bei der nächsten erfolgreichen Anmeldung einen neuen Hashwert mit dem modernen Verfahren und ersetzen Sie den alten. Für Konten, die nicht zurückkehren, können Sie den alten Hashwert nach einer Frist ungültig machen und eine Passwortwiederherstellung erzwingen.

Was ist ein Pepper und brauche ich einen?

Ein Pepper ist ein geheimer Wert, den Sie dem Passwort vor dem Hashen hinzufügen und der nicht in der Datenbank, sondern in einem Schlüsseltresor oder einer Umgebungsvariablen liegt. Bei einem Leck ausschließlich der Datenbank sind die Hashwerte damit unbrauchbar. Es ist eine nützliche zusätzliche Schicht, kein Ersatz für eine gute Hashfunktion.

Verwandte Artikel

Zum Suchen / drücken · Esc