Client-Side Hashing


cwriter

Erfahrenes Mitglied
Hallo Welt

Beim Implementieren eines kleinen REST-Services bin ich mal wieder etwas ins Grübeln gekommen.
Warum ist Client-Side Hashing nicht Standard?

Bei Websites ist der heutige Prozess des Logins ja so:
  1. Client schickt Nutzername und Passwort über HTTPS an den Server
  2. Der Server prüft den bereits gespeicherten Hash für diesen Nutzernamen per hash(password + salt) und wenn die Hashes übereinstimmen, gilt das Passwort als korrekt.
Angriffspunkte:
  1. Client (und Nutzer). Immer verwundbar.
  2. Server (offline - z.B. Datenbankauszug). Durch Hashes und Salts (wenn gut gewählt) kaum ein Problem bei Rainbowtable-Angriffen.
  3. Server (online - z.B. böser Admin). Verwundbar, da Passwörter im Klartext. Wenn jemand ein Passwort an mehreren Orten verwendet -> Erwischt.

Bei Client-Side Hashing könnte man es - als Beispiel - so gestalten:
  1. Client schickt Nutzername über HTTPS an den Server
  2. Der Server schickt den gespeicherten Salt an den Client
    1. N.B.: Damit die Existenz eines Nutzers nicht geleakt wird, müsste jeder angefragte Nutzer einen eindeutigen, niemals wechselnden Salt bekommen. Idealerweise müssten also Dummy-Nutzer gespeichert werden (die man natürlich überschreiben könnte, wenn man den Salt gleich hält).
  3. Der Client schickt (Nutzername, Hash(Passwort + Salt)) an den Server
  4. Der Server prüft den bereits gespeicherten Hash für diesen Nutzernamen direkt mit einem erneuten Hash (gespeichert= Hash(Hash(Password + SaltClient) + SaltServer)) und wenn die Hashes übereinstimmen, gilt das Passwort als korrekt.
Angriffspunkte:
  1. Client (und Nutzer). Immer verwundbar.
  2. Server (offline - z.B. Datenbankauszug). Durch Hashes und Salts (wenn gut gewählt) kaum ein Problem bei Rainbowtable-Angriffen.
  3. Server (online - z.B. böser Admin). Kein Problem mehr, da ein böser Admin ohnehin Zugriff auf die Daten des Dienstes hat. Die Daten an anderen Orten sind aber sicher, solange die Hashes sicher sind.

Das Internet schlägt fast immer in die gleiche Kerbe: "Es ist nur wenig bis gar nicht sicherer als pures HTTPS"

Die vorgeschlagenen Alternativen:
  • Passwortmanager. Wissen wir alle, benutzt fast niemand. Sind schlecht für die Usability
  • 2FA: Löst das Problem nicht. Es braucht nur 1 Seite ohne 2FA, die dasselbe Passwort hat, um wieder ein Problem zu sein
  • HTTPS: Ist keine Lösung für böse Endpoints.
"Nützt ja nichts, da ein kompromittierter Server auch anderes JS ausliefern kann": Völlig korrekt. Allerdings erklärt das nicht, warum es keine Browser-API gibt, die - ähnlich dem Certificate Pinning - solche Änderungen am Code verbietet.

Gegenargument "Weniger Entropie": Trifft nur bei Passwörtern < 32 Bytes auf. Ich denke, das ist vernachlässigbar.

2 Fragen / Diskussionspunkte dazu:
1) Warum wird das nicht von Entwicklern umgesetzt? Klar, es ist ein bisschen mehr Arbeit, aber jetzt auch nicht die Welt.
2) Warum wird es nicht von den "Grossen" gepusht? Will man den Passwort-Reuse-Leuten nicht helfen? Oder kann man sich nicht vorstellen, dass ein Server übernommen wird?

Ich freue mich auf jeden Input :)

Gruss
cwriter
 
Zuletzt bearbeitet:

zerix

Hausmeister
Moderator
Hallo,

ich habe erstmal keine Meinung, weil keine Gedanken gemacht, aber zu zwei Aussagen wollte ich was sagen.

"Nützt ja nichts, da ein kompromittierter Server auch anderes JS ausliefern kann": Völlig korrekt. Allerdings erklärt das nicht, warum es keine Browser-API gibt, die - ähnlich dem Certificate Pinning - solche Änderungen am Code verbietet.
Certificate Pinning macht schon Probleme und das "einzige" was dazu tun ist, ist sicherzustellen, dass das Zertifikat sich nicht geändert hat. Da der Browser sich eine Zeit lang die Zertifikatsinfos speichert, hat der Webseiten-Betreiber das Problem, wenn sich das Zertifikat aus irgendeinem Grund vorher ändert. Aus dem Grund soll CertPinning wieder abgeschafft werden, zumindest was die Browser angeht.
Wie soll das bei Code aussehen? Um sicher zu stellen, dass der Code nicht geändert wurde, müsste dieser signiert sein. Was macht man, wenn man hier den Key zum signieren verliert? Da hat man hier das gleiche Problem. Weiterhin ändert sich Code öfter als Zertifikate. Was ist ein geeigneter Zeitraum?
Die Änderung des Codes so zu verhindert ist wesentlich schwerer.

Gegenargument "Weniger Entropie": Trifft nur bei Passwörtern < 32 Bytes auf. Ich denke, das ist vernachlässigbar.
Ich kann bezüglich der Entropie gerade nicht folgen, da ich das Argument nicht kenne, aber dir ist klar, dass Passwörter < 32 Byte Passwörter mit weniger als 32 Zeichen sind? Wieviele Passwörter haben mindestens 32 Zeichen?

Viele Grüße
Sascha
 

cwriter

Erfahrenes Mitglied
Da der Browser sich eine Zeit lang die Zertifikatsinfos speichert, hat der Webseiten-Betreiber das Problem, wenn sich das Zertifikat aus irgendeinem Grund vorher ändert.
Danke für die Info, ich wusste bisher nur, dass es kaum verbreitet war. Allerdings war Cert Pinning auch vor allem für Google selbst gedacht, um Vorfälle wie den von Türktrust (Fatale Panne bei Zertifikatsherausgeber Türktrust) zu vermeiden - dort ist es auch nicht allzu schlimm, dass man die Zertifikate kaum ändern kann. Soweit ich weiss, sind die Google-Certs mittlerweile einfach hardcoded im Chrome drin.

Weiterhin ändert sich Code öfter als Zertifikate. Was ist ein geeigneter Zeitraum?
Die Änderung des Codes so zu verhindert ist wesentlich schwerer.
Alleine schon eine Warnung, dass sich die Anmeldung von Client-Side Hashes auf Passwort geändert hat, wäre ja schon genug. Klar kann ein Browsers das schlecht herausfinden, wenn es in JS selbstgebastelt ist - daher auch die Frage, warum es keinen Standard dafür gibt. Es wäre ja ein Leichtes, ein
HTML:
<input type="password-hash" salt="mysalt">
in den Standard zu packen (jaja, Standardisierung ist nicht ganz so leicht :) ).

Ich kann bezüglich der Entropie gerade nicht folgen, da ich das Argument nicht kenne, aber dir ist klar, dass Passwörter < 32 Byte Passwörter mit weniger als 32 Zeichen sind? Wieviele Passwörter haben mindestens 32 Zeichen?
Das Gegenargument gegen Hashes ist die oft kurze Länge - Bei BCrypt sind es oft 23 Bytes, soweit ich weiss - in einen SHA256 gefüttert dann 32 Bytes. Längere Passwörter (wie man sie mit einem Passwortmanager nutzen kann) werden dann gekürzt. Noch etwas schlimmer: Man müsste bei Brute-Force nur eine fixe Länge abfragen, statt durch alle Passwortlängen durchzugehen.
Tatsächlich sind die wenigsten Passwörter länger als 10 Zeichen:

Daher finde ich das Argument, Hashes würden die Sicherheit im schlimmsten Fall durch ihre Länge verschlechtern, ungültig. Selbst dann ist die Entropie des Passworts wahrscheinlich tiefer als die eines Hashes.

Gruss
cwriter
 

Technipion

Erfahrenes Mitglied
1) Warum wird das nicht von Entwicklern umgesetzt? Klar, es ist ein bisschen mehr Arbeit, aber jetzt auch nicht die Welt.
Die Frage stelle ich mir auch oft. Leider komme ich dann immer zu einem Schluss, der mir auch nicht gefällt: In der Software-Branche arbeiten leider (sehr) viele faule Menschen. Damit meine ich nicht, dass sie nicht pünktlich zur Arbeit gehen oder lässigen Code schreiben. Sondern dass nur wenige sich die Mühe machen, wirklich über ihr System nachzudenken und selbst "übliche" Ansätze in Frage zu stellen. Einfach mal die Finger von der Tastatur lassen, sich ein Blatt Papier schnappen, und ordentlich grübeln. Genau das was du da gemacht hast cwriter. Aber leider sind die meisten Leute zu denkfaul dafür. Ich ertappe mich ja selbst auch immer wieder dabei.
Und wenn die Mehrheit eben gar nicht darüber nachdenkt bleibt halt alles beim alten. Auch wenn andere Ansätze besser geeignet wären. Aber wer kümmert sich heute überhaupt noch selbst um sein Hashing. Machen doch eh alles fertige Bibs.

Ich meine das alles ja nicht beleidigend. Aber es ist meine Beobachtung und eigentlich müsste man was dagegen tun.
2) Warum wird es nicht von den "Grossen" gepusht? Will man den Passwort-Reuse-Leuten nicht helfen? Oder kann man sich nicht vorstellen, dass ein Server übernommen wird?
Programmierer sind eine Ware. Für Konzerne ist alles nur eine Ware. Der Code auch.
Wenn du verstehen willst warum Firmen oft einen feuchten Furz auch Sicherheit geben, musst du anfangen in Geld zu denken, so wie die.
Eine nicht völlig hirntote Krankenkasse würde nie Patientendaten in eine Drittanbieter-Cloud auslagern. Man gibt die "Datenhoheit" völlig auf und gibt offen zu, dass man keine Ahnung von Privatsphäre hat. Wird aber trotzdem gemacht, weil es scheinbar billiger ist. In Wahrheit wird der Preisvorteil natürlich dadurch erkauft, dass unter'm Strich ein Haufen an den falschen Ecken gespart wird.

Sorry für den Rant, aber das musste mal raus. Ich schaue jetzt schon Jahre dabei zu wie - teilweise große - IT-Systeme zerf**** werden. Das müsste alles nicht sein.

Gruß Technipion

PS: Weil ich oben natürlich alle Programmierer als faul betitelt habe: Es ist natürlich in vielen Unternehmen auch gar nicht gewollt, dass die Leute Zeit nehmen und eigene Gedanken zu den Systemen machen.
 

cwriter

Erfahrenes Mitglied
Die Frage stelle ich mir auch oft. Leider komme ich dann immer zu einem Schluss, der mir auch nicht gefällt: In der Software-Branche arbeiten leider (sehr) viele faule Menschen.
Damit könnte ich noch knapp leben. Die grössere Frage für mich ist, warum sich so viele in Phrasen retten:
  • Crypto sollte man eh nicht selber machen
  • Der Standard ist gut genug
  • Nützt nichts, da dann der Hash das Passwort ist
Nichts davon ist wirklich falsch, aber halt nicht unüberlegt.
Daher frage ich mich auch, ob es ein technisches Problem bei Client-Side Hashing gibt oder ob wirklich nur Faulheit dagegen spricht.


Wenn du verstehen willst warum Firmen oft einen feuchten Furz auch Sicherheit geben, musst du anfangen in Geld zu denken, so wie die.
Aber sollte nicht gerade die DSGVO dafür sorgen, dass Sicherheit = Geld ist?
Ich bin ja auch kein Fan der Juristerei, aber best-effort wäre ja trotzdem möglich. Ich mache mir bei jedem Code, den ich schreibe, Gedanken darüber, welche Daten der Server sehen muss und welche nicht. Idealerweise ist der Server ja nur ein Lager für verschlüsselte Daten, und bearbeitet werden die Daten nur auf dem Client.
Nun gibt es natürlich Grenzen, z.B. kann ein Server auch für Data Processing verwendet werden, da ist Verschlüsselung (mit einem Schlüssel, welchen nur der Nutzer hat) etwas unpraktisch ;). Generell ist Usability ja auch erwünscht, da gibt es halt manchmal Trade-Offs.
Aber gerade bei Nutzer-spezifischen (bzw. -identifizierenden) Daten will ich die Daten gar nicht sehen.
Ich habe keine Lust auf grosse Leaks, die gemeldet werden müssen, keine Lust auf Gerichtsbeschlüsse, nach denen die Daten einzelner Nutzer offengelegt werden müssen (geht in beide Wege: Ich will auch nicht überprüfen können/müssen, welche Daten die Nutzer auf meine Dienste packen) und ganz persönlich wäre ich ziemlich unglücklich, wenn ich mir anvertraute Daten verlieren würde bzw. an Unberechtigte weitergebe, gewollt oder ungewollt.

Zu ungewollt: Twitter ruft nach Sicherheitspanne zum Passwortwechsel auf Wäre z.B. mit Client-Side Hashing kein oder nur ein sehr kleines Problem gewesen.

Ich weiss, ich weiss, Idealismus muss man sich leisten können. Aber gibt es denn keinen Berufsstolz (oder vielleicht eher Selbstachtung) mehr, dass man seine Arbeit nur noch "genügend" machen will, statt "nach bestem Wissen und Gewissen"?

Gruss
cwriter
 

Technipion

Erfahrenes Mitglied
Ich weiss, ich weiss, Idealismus muss man sich leisten können. Aber gibt es denn keinen Berufsstolz (oder vielleicht eher Selbstachtung) mehr, dass man seine Arbeit nur noch "genügend" machen will, statt "nach bestem Wissen und Gewissen"?
Deshalb bin ich ja mehrfach etwas zurückgerudert. Ich möchte ja nicht die ganze Branche in den Dreck ziehen. Natürlich gibt es viele gute Programmierer, die echt was von ihrem Handwerk verstehen und denen die Sicherheit der Nutzerdaten am Herzen liegt. Ich habe hier nur gegen den allgemeinen Trend in der Industrie gehated.

Ich mache mir bei jedem Code, den ich schreibe, Gedanken darüber, welche Daten der Server sehen muss und welche nicht.
Spitze, genau so muss das sein! Ich selbst habe auch mehrere Server unter meiner Fuchtel, und ich bin sogar so weit gegangen, mir eigene Hashfunktionen dafür anzufertigen. Ganz ehrlich: Mit 30 min Einlesezeit auf Wikipedia (Kryptographische Hashfunktion – Wikipedia) und GitHub (XKCP/XKCP) kann man sein Verständnis schon beträchtlich boosten.
Und die Entwickler von Keccak (Basis des heutigen SHA-3) haben sogar für Python, Rust, und natürlich C Implementierung verfügbar gemacht.
Gerade in C findet man hier super einfach SHA-3 für die Integration in den eigenen Code:
Die sehr kompakte Version hat gerade mal 38 Zeilen! Es kann ja nicht schaden ein bisschen mit dem Zeug herumzuspielen :D

Und wenn man dann erst einmal etwas Erfahrung im Umgang mit Hashfunktionen hat, kann man einen Schritt zurücktreten und sich ein cleveres Authentifizierungssystem überlegen, so wie du das getan hast cwriter.

Gruß Technipion