Hi Christian,
So, hat etwas gedauert, bis ich über die Karnevals-Tage dazu gekommen bin hier mal zu antworten ;-)
Im Prinzip funktioniert Challenge-Response so:
A. Server sendet Client eine Zufallszahl.
B. Client sendet Server sowas wie Hash(Passwort + Zufallszahl)
C. Server generiert selbst Hash(Passwort + Zufallszahl) und vergleicht das mit der Clientangabe.
Ok, daran hatte ich nicht gedacht - meine Aussage „alle Loginsysteme” bezog sich vielmehr nur auf die gebräuchlichen Loginsysteme, zu welchen ich jetzt mal HTTP Basic Auth, sowie ein z.B. in PHP programmiertes, simples Login-System. Diese Systeme stellen alle kein Challenge-Response-Verfahren da und sind somit nicht sicher, solange man sie nicht über SSL/TLS laufen lässt. ;-)
Außerdem muss das Passwort im Klartext beim Server vorliegen. […] Muss man sich halt was dafür überlegen. ;-)
Ich überlege mir gerade, wie das wohl mit Auth Digest funktioniert. Auth Digest wäre ja vom Prinzip her Challenge-Response… Für den Server bedeutet dies meines Erachtens einen Mehraufwand - herkömmlicherweise kann z.B. Apache ja jeden Request für sich getrennt behandeln. Bei Auth Digest müsste Apache ja aber im Hintergrund eine Art Session führen, da er sich merken muss, welchem Client er welchen Zufallswert rausgegeben hat, oder? Würde mich mal interessieren wie man so etwas realisiert, unter anderem wenn man gar nicht weiß, welcher Prozess oder Thread den zweiten Request des Clients erhält.
Im Web kann man das ganze mit JavaScript machen - der Server übergibt dem JavaScript die Zufallszahl, merkt sie sich aber intern noch in der eigenen Session (wenn er es nur wieder als Formularfeld übergibt, könnte das von einem Angreifer gefälscht werden -> Sicherheit dahin). JavaScript macht dann beim Abschicken des Formulares das ganze Mojo (erfragt u.U. vorher noch per AJAX den Salt zum Usernamen) und schickt dem Server nur noch das endgültige Hash-Gemix aus Passwort, Challenge-Zufallszahl und evtl. Salt. Der Server kann das dann verifizieren.
Ich stehe dem Einsatz von Javascript für wichtige Operationen nach wie vor kritisch gegenüber. Meines Erachtens muss gerade ein Login-System auf jeden Fall ohne Javascript funktionieren - aber dann wäre die gewonnene Sicherheit ja futsch.
Und Usern, welche Javascript deaktiviert haben, keine Sicherheit bieten? Nun gut, man könnte es auch andersrum sehen: Usern, welche Javascript aktiviert haben zusätzliche Sicherheit bieten! *g* Dürfte letztendlich eine Frage der Philosophie sein, wobei bei ich wie gesagt im Zweifelsfall einfach SSL/TLS wählen würde, mit CAcert und einem Root-Server ist das auch schnell realisiert ;-)
Ja, deswegen schrieb ich ja, dass Challenge-Response gegen Live-Angriffe (!) nichts bewirkt [*].
Genau, allerdings nur, wenn man eine „Session” verwendet, also einen sich nicht ändernden Schlüssel, mit welchem man Zugang erhält. Das war ja eigentlich auch alles was ich sagen wollte - ich sehe keinen Sinn darin, aufwendig ein Challenge-Response Login-Verfahren zu programmieren mit jeder Menge Javascript auf der Client-Seite, wenn letztendlich im Anschluss daran nur der Session-Schlüssel abgehört werden muss, damit das System geknackt ist.
Wenn ich das richtig sehe, ist dies aber im Falle von Auth Digest aber nicht der Fall, oder? Hier müssten doch eigentlich bei jedem Request die Zugangsdaten übermittelt werden, wie bei Auth Basic. Und weil die URL mit als Salz für den Hash genommen wird, ist der übertragene Schlüssel bei jedem Request anders.
For subsequent requests, the hexadecimal request counter (nc) must be greater than the last
value it used – otherwise an attacker could simply "replay" an old request with the same
credentials. It is up to the server to ensure that the counter increases for each of the nonce
values that it has issued, rejecting any bad requests appropriately. Obviously changing the
method, URI and/or counter value will result in a different response value.
Aus dem oben verlinkten Artikel der englischen Wikipedia - dank des Counters wird also verhindert, dass zwei aufeinander folgenden Requests auf die gleiche URI nicht den gleichen Authorisierungs-Schlüssel verwenden. Auch hier überlege ich mir gerade wieder, dass muss sich der Server ja alles in einer Art „Session” im Hintergrund merken… ganz schön aufwendig ;-)
session_regenerate_id() hat aber dennoch seine extrem wichtige und sinnvolle Anwendung bezüglich Session-Sicherheit: Es ist gut gegen Session-Fixation. Stell Dir vor ich schicke Dir einen Link zu einer Seite auf der Du registriert bist mit einer von mir vorher bereits erzeugten Session-ID, die ich kenne. Dann bist Du auf diese Session-ID "fixiert". Wenn Du Dich dann einloggst (URL stimmt, Script-Code habe ich auch nicht eingeschleust oder so), dann habe ich trotzdem Zugriff auf das was Du hast, weil ich ja die Session-ID, die Du verwendest, bereits kenne.
Stimmt, an den Aspekt habe ich noch gar nicht gedacht, sofern der Server also Session-IDs über GET-Parameter akzeptiert sollte man hier gezielt vorbeugen.
[…] Wirkliche Sicherheit hat man natürlich nur mit SSL/TLS […]
Ok, da sind wir uns einig :-)
Viele Grüße,
~ Dennis.