Sven Rautenberg: HTTP Auth (wieder mal...)

Beitrag lesen

Moin!

...einen _Schlüssel_ auf den Auth-Datensatz in der DB parken, am besten mit einer zweiten _eindeutig_ erzeugten ID, aber mehr sollte man das ganze nicht verzahnen. Und: Es muss immer sichergestellt sein, dass bei Zweifeln eher abgebrochen wird, als auf Verdacht weiter zu machen.

das trifft so ungefähr die Problematik. Eine Sessionnummer gibt nur eine Positivaussage, wenn sie passt. Leider ist diese Aussage nicht umkehrbar, da HTTP kein verbindungsorientiertes Protokoll ist. Wenn die Sessionnummer die einzige Größe ist, über die ein User erkannt werden kann, dann stellt sie kaum einen Schutz dar.

Hier möchte ich widersprechen. Eine Session schützt genauso gut (oder schlecht) wie eine Username/Passwort-Authentifizierung.

Der User könnte ja theoretisch beliebig oft wiederkommen und damit gültige Sessionnummern erraten. Da es keine Möglichkeit gibt, festzustellen, ob es der selbe User ist (wie gesagt, alles Theorie), aknn man ihn auch nicht aussperren. Da aufgrund der Positiverkennung auch nicht festgestellt werden kann, welche Sessionnummer attakiert wird, kan man diese auch nicht schützen.

Dasselbe Argument kann man für Username/Passwort-Authentifizierung anbringen. Auch da kann der Angreifer beliebig oft wiederkommen und ausprobieren. Nur hat er da noch den kleinen Vorteil, dass er den menschlichen Faktor einrechnen kann - wenn die User sich ihr Passwort frei wählen können, wird es mindestens einen User geben, der für Wörterbuchattacken anfällig ist - und BUMM.

Das ganze ändert sich, wenn man eine Authentifizierung mittels Datenbank und einem Schlüsselpaar (Loginname und Passwort sind da üblich) vorschaltet und dan auf ein anderes Schlüsselpaar (Sessionummer und SessionPIN, beides Cookies) umschaltet. Nun ist es plötzlich nicht mehr möglich, eine "erratene" Sessionnummer einfach zu benutzen, da auch der Key dazu passen muss.

Das ändert nichts grundsätzlich, es vergrößert nur den Aufwand.

Ich will das mal genauer ausführen:
Um in HTTP einen User wiederzuerkennen, muss dieser bei jedem Request ein eindeutiges Identifikationsmerkmal senden. _Alles_, was der berechtigte Benutzer sendet, kann ein Angreifer auch senden. Und alles kann durch Ausprobieren angegriffen werden.

Um den Benutzer also zu authentifizieren, ist entweder eine Username/Passwort-Kombination notwendig, oder ersatzweise eine gültige Session-ID. Die üblichen Session-Login-Mechanismen geben jedem Benutzer sofort eine Session-ID, und erst wenn der Benutzer innerhalb dieser Session einen gültigen Usernamen und Passwort gesendet hat, erlaubt die Session den Zugang zu geschützten Bereichen. Die Session-ID ist also zum Ersatz-Schlüssel geworden.

Du willst das jetzt angreifen. Dazu gibt es zwei Methoden: Entweder greifst du Username/Passwort an und errätst eine korrekte Kombination, oder du greifst die Session-ID an und errätst eine gültige Session.

Wie wahrscheinlich ist aber, dass dir eines von beiden gelingt? Beim Passwort-Angriff hast du zumindest theoretisch einen beliebig hohen Aufwand, sofern der Angreifer keinerlei Informationen hat. Sobald er einen Usernamen hat, ist eine Komponente schon mal geklärt, und mit Glück ist ein kurzes Passwort schnell geraten oder eine Wörterbuchattacke möglich.

Beim Raten der Session-ID hingegen gibt es nur endlich viele Kombinationen. Die PHP-SessIDs sind 128 Bit lange Zahlen, ausgedrückt als 32 Zeichen lange Hex-Zahl. 128 Bit ermöglichen 2^128 Kombinationen, oder etwa 3,4e+38.

Wieviele Versuche pro Sekunde soll ein Angreifer schaffen? Eine Milliarde? Das wären 1e+9 Versuche pro Sekunde, und es würde immer noch 3,4e+29 Sekunden dauern, bis alle Kombinationen ausprobiert sind. Durchschnittlich muß man nur die Hälfte aller Kombinationen ausprobieren, um eine einzig gültige Kombination rauszufinden - wenn mehrere Benutzer gleichzeitig aktiv sind, braucht man nicht mehr die Hälfte, sondern sogar noch einen kleineren Teil. Die 3,4e+38 Möglichkeiten könnten schön symmetrisch unterteilt sein. Wieviele Besucher sollen gleichzeitig aktiv sein? Eine Million? Ok, dann kriegt man nach 1/1.000.001stel Kombinationen die richtige raus (und nicht nach 1/2). Bleiben 3,4e+23 Sekunden, die ein Angriff dauert. Oder in Jahren: 10781329274479959,4114662607813293

Glaubst du nicht auch, dass dieser Angriff reichlich uninteressant ist. Natürlich kann man beim ersten Versuch Glück haben, aber systematisch kann man kaum angreifen.

Gucken wir noch, was man bei Username/Passwort an Sicherheit hat: Ein Username soll 10 Zeichen lang sein, ein Passwort ebenfalls. Erlaubt sind grob geschätzt 100 verschiedene Zeichen. Dann gibt es 100^10 verschiedene Usernamen und 100^10 verschiedenen Passwörter - insgesamt 1e+40 Kombinationsmöglichkeiten. Diese werden allerdings dahingehens eingeschränkt, dass nicht alle kombinierbaren Usernamen auch wirklich benutzt werden. Ich würde vermuten, dass erstens nur 62 Zeichen (Klein-/Grossbuchstaben, Zahlen) verwendet werden, und außerdem die Auswahl deswegen stark eingeschränkt ist, weil beschreibende Namen und keine kryptischen Passwörter gewählt werden. Also statt 1e+20 Usernamen gibt es nur 8e+17 Usernamen, und von denen dürften nicht mehr als 1% wirklich verwendet werden - also 8e+15 Stück. Macht zusammen 8e+35 Kombinationen - und das liegt absolut im Bereich der Möglichkeiten, wie sie Sessions auch bieten - zuzüglich dem menschlichen Faktor!

In Wirklichkeit ist also nicht die Session-ID das Problem, sondern Username/Passwort. Nur bei sehr günstigen Voraussetzungen (im Sinne der Sicherheit) ist die Angreifbarkeit ähnlich schlecht. Wenn hingegen nur kurze Usernamen und Passwörter und nur ein eingeschränkter Zeichenvorrat verwendet werden, dann sinkt die Sicherheit des Username/Passwort-Systems ganz rapide.

Sicherheit ist relativ. Ein System ist dann ausreichend sicher, wenn der Aufwand, die Sperren zu überwinden, teurer ist als der durch den Einbruch zu erwartende Gewinn. Außerdem gibt es absolute Sicherheit nicht - ein System wäre dann absolut sicher, wenn niemand rein kommt - auch keine berechtigten Benutzer. Denn ein Angreifer kann es immer irgendwie schaffen, sich als berechtigter Benutzer auszugeben. Selbst DNS-Kontrollen können garantiert umgangen werden - siehe den Film GATACA. :)

- Sven Rautenberg

--
"Bei einer Geschichte gibt es immer vier Seiten: Deine Seite, ihre Seite, die Wahrheit und das, was wirklich passiert ist." (Rousseau)