Sven Rautenberg: Login

Beitrag lesen

Moin!

nochmal gaaanz langsam zum Mitschreiben:

Ich habe nicht exakt mitgezählt, aber grob geschätzt stellst du dein Konzept für eine sichere Session- und Login-Verwaltung hier schon zum dritten Mal zur Diskussion.

Bislang habe ich immer darauf geantwortet. Und du meine Antworten ignoriert. Schade eigentlich, denn vielleicht liege ich ja tatsächlich falsch, wenn ich behaupte, dass dein Extraaufwand _qualitativ_ keine Verbesserung der Sicherheit bringt, sondern nur _quantitativ_ (man muß mehr richtig raten).

Sessionverwaltung und Login haben miteinander (fast) nix zu tun.

In diesem Punkt stimme ich zu. Die Session-ID ist lediglich Grundlage dafür, auf dem Server für jeden Request die dem Benutzer zugeordneten Sessiondaten wiederzufinden.

Die Session identifiziert nur einen bestimmten Besucher. Über seine Rechte sagt sie alleine nichts aus. Du musst für diesen Besucher die Rechte explizit feststellen lassen und DANN kannst Du sie z.B. in die Sessiondatei eintragen. Das ist eine ganz einfache Lösung.

Genau. Irgendwann einmal hat der Benutzer Usernamen und Passwort übermittelt. Diese wurden in der Benutzer-DB gefunden, die gültigen Rechte wurden in die Session-Daten geschrieben - und schon kann der Benutzer zugreifen.

Jeder andere fremde Benutzer kann ab diesem Augenblick auch zugreifen, sofern er die Session-ID kennt oder errät.

Leider werden diese Rechte dann auch noch in der Sessiondatei drinstehen, wenn der benutzer schon lange schläft. Wenn jetzt jemand die Sessionnummer errät (Das ist hier ein Fachausdruck! Also bitte nicht wieder die Diskussion über die Wahrscheinlichkeit.) oder findet, dann würde er fälschlich als derjenige User identifiziert, der sich bereits logged hat.

Dasselbe gilt für Fremde, die Username und Passwort erraten. Die gelten dann fälschlich (aber im Sinne des Systems sogar korrekt!) als eingelogged.

Die Zugriffsrechte müssen von Kriterien abhängen, die flüchtig sind, also nirgens auf der Strecke (unter Normalumständen) gespeichert werden.

Eine Session-ID, die als Cookie übertragen wird, entspricht diesen Kriterien.

Das wären z.B. Username und Passwort über das Standard-Anmeldefenster (Auth 401) oder "Session-"Cookies, die nicht auf der Platte gespeichert werden oder "normale" Cookies mit ohne Speicherung. PHP übersetzt hier "Lebensdauer=0" mit "nicht speichern, nur für die aktuelle Browserinstanz und ihre Childs nutzen".

Zwei Anmerkungen:
1. Wie ein Cookie vom Client gespeichert wird, entscheidet der Client. Da hast du keinerlei Einflußmöglichkeit vom Server aus. Außerdem fällt dieses in den Aufgaben- und Sicherheitsbereicht des Benutzers.

2. Es gibt nur eine Sorte Cookies: Cookies. Ein Cookie hat eine vom Server definierte Lebensdauer, gilt für eine definierte Domain oder Domaingruppe und dort für einen definierten URL-Bereich. Man kann Cookies für 25 Jahre setzen, oder für die Dauer des Browserbetriebs. Letzteres wird dann gerne als "Session-Cookie" bezeichnet, ist aber dasselbe Cookie, wie jedes andere auch. Es sieht gegenüber dem Server auch absolut genau gleich aus, wie ein dauerhafter gespeichertes Cookie.

Wenn Du also einen Cookie mit

setcookie ( "PIN", $pin, 0, "/", "$damain")

nach erfolgreichem Logincheck an den Client schickst und ihn in Deine Session einträgst ($_SESSION["pin"] = $pin), dann hast Du ein relativ sicheres Kriterium dafür, von welchem Client die Session gerade genutzt wird. Denn nur genau ein Client hat auch den passenden Cookie zur Sessionnummer. Das musst Du dann natürlich in jedem Script am Anfang kontrollieren.

Jeder Client, der einen gültigen Usernamen und Passwort an den Server sendet, ist im Besitz solch eines Cookies, nicht nur "genau einer".

if ($_SESSION["pin"] == $_COOKIE["PIN"])
{
  $logged = true;
}

Diese Vorgehensweise funktioniert natürlich nur, wenn der Client Cookies akzeptiert. _Dann_ aber sind die normalen Session-Cookies genauso gut geschützt und werden nirgendwo gespeichert - außer natürlich, jemand lauscht am Netz.

Und das logout geht dann auch relativ unproblematisch: der User erbittet es und wenn er berechtigt ist, sendest Du einfach einen Cookie an den User setcookie("PIN") und löschst den aus der Session $_SESION["pin"]="" und schon ist der User nicht mehr logged.

Bis hierhin hatte ich eigentlich gedacht, dein Extraaufwand würde tatsächlich _substantiell_ was bringen. Aber: Was ist, wenn der User das Logout vergißt? Dann bleibt die Session offen, der PIN-Eintrag bleibt drin, und jeder, der mit der richtigen Session-ID und der richtigen PIN im Cookie ankommt, hat Zugriff.

Das Szenario ist also, bis auf den erhöhten Rateaufwand für die PIN, den man aber mit Sicherheit mitbekommt, wenn man ein guter Angreifer ist (und ihn deshalb berücksichtigen kann), absolut identisch mit ganz normalen Sessions.

Schon bei normalen Session-IDs ist der Rateaufwand so enorm, dass er sich nicht lohnt. Angriffe lohnen sich, wenn man weiß, welche Session-IDs aktuell benutzt werden. Also sollten die nicht per URL (Referrer etc.) in fremde Hände gelangen - klar.

Wenn die IDs nicht bekannt sind, wäre der erfolgversprechendste Ansatzpunkt hingegen, Usernamen und Passwort zu raten. Die Usernamen sind, wenn man dumm programmiert, möglicherweise öffentlich, zumindest aber nicht unbedingt schwer zu bilden. Für die Passworte lohnt sich eine Wörterbuchattacke.

Mit anderen Worten: Die Anstrengungen für mehr Sicherheit sollten in zwei vollkommen andere Richtungen gehen. Erstens: Sichere Passworte. Lang und zufällig müssen sie sein. Zweitens: Verschlüsselung. Dann kann niemand mehr lauschen.

- Sven Rautenberg

--
"Beim Stuff für's Web gibts kein Material, was sonst das Zeugs ist, aus dem die Sachen sind."
(fastix®, 13. Oktober 2003, 02:26 Uhr -> </archiv/2003/10/60137/#m338340>)