Methoden um Sessions zu missbrauchen

GiFt-ZwErG

Erfahrenes Mitglied
Hallo,

ich arbeite gerade an meinem CMS und bin nun am überlegen wie ich bestimmte Daten des Users global verfügbar machen ohne jedes mal die MySQL DB zu quälen.
Möchte nun gern die Daten in die Session speichern und habe dazu noch ein paar Fragen.

Welche Möglichkeiten hat ein User an diese Sessiondaten zu kommen?
Wie lange ist die Session gültig und was ist wenn ich in einem Script kein Session_start() benutze ( was ist dann mit der Session auf dem Server und dem Cookie bei dem Client? )
Die Sessiondaten werden ja auf dem Server gespeichert und anhand des Cookies auf dem Client kann der PC identifiziert werden ( die Session des Clients ), was ist nun wenn jemand dass Cookie klaut oder die SessionID kennt?

Ich habe noch ein paar Fragen diesbezüglich aber ich denke die werden sich evtl. von alleine beantworten wenn die Fragen oben beantwortet werden.. ;)

EDIT:
Habe mich nun etwas mehr eingelesen in die Sessions von PHP und frage mich nun ob es sinnvoll ist, diese zu nutzen.
Wenn der User Cookies deaktiviert hat, sind alle Daten aus der Session weg da der User eine neue Session zu gewiesen bekommt.
Und die übergabe der SessionID über die URL kommt definitiv nicht in Frage.
Gibt es eine Möglichkeit Daten ( Einstellungen des Users usw ) für alle Scripts verfügbar zu machen ohne diese jedes mal neu aus der Datenbank auslesen zu müssen?
Wobei dass ja die Session von PHP genauso macht oder? Bei jeder Session die gestartet wird, wird eine Datei erstellt wo die vars drin gespeichert werden.
Liest PHP diese Datei JEDESMAL neu aus? Könnte ja sein dass sich vars ändern usw.
Hat jemand eine ausführliche Seite über Sessions? Ich möchte alles darüber wissen wenn es geht.. habe schon die Seite http://www.php.net/manual/de/ref.session.php komplett durch... gibt es noch mehr was man über Sessions wissen muss?
Evtl auch Alternativen ( Klassen, Funktionen etc ) oder Hinweise auf andere Möglichkeiten etc.

MFG
Sandro
 
Zuletzt bearbeitet:
Wenn Cookies deaktiviert sind wird die SessionID an die URL angehangen. Basiert dein Login-System mittels Auto-Login auf einer SessionID, kann mit Diebstahl des Cookies evtl. jemand an den Account des ursprünglichen Nutzers rankommen. Man hat nie eine 100%-ige Sicherheit, aber ich denke man sollte den User immer Aufmerksam vor möglichen Missbrauch machen.
 
Das HTTP, also das Transferprotokoll des WWWs, hat einen großen Nachteil: es ist zustandslos. Das heißt der User Agent muss sich auch nicht jedes Mal identifizieren und die Verbindung zwischen Client und Server wird nach jeder Anfrage getrennt. Das bedeutet wiederum, dass ein Benutzer auf seinem Weg durch eine Webanwendung nicht eindeutig identifiziert werden kann. Denn auch die IP-Adresse ist in Zeiten von gemeinsam genutzten Internetzugängen kein eindeutiges Merkmal.

Also hat man sich einen Trick ausgedacht, um eine eindeutige Identifizierung möglich zu machen. Nämlich eine Sitzungs-ID, die bei jeder Anfrage des Clients an den Server mitgeschickt wird – egal ob nun als Cookie, als GET- oder POST-Argument.

Doch dieser Trick stellt auch gleichzeitig die Schwachstelle des Systems dar. Denn PHP nimmt von Haus aus keinerlei besondere Validierung der Sitzungs-ID vor. Überhaupt ist die von PHP gebotene Sitzungsverwaltung wirklich nur sehr grundlegend. PHP bietet also quasi nur die Werkzeuge, mit denen der Entwickler seine Maschine bauen kann.

Daher ist es wichtig zu wissen, was eine Sitzung überhaupt ist und was sie nicht ist, was mit ihr möglich ist und was nicht, wo die Nachteile und Schwachstellen liegen und wie diese umgangen oder gestärkt werden können um einem Missbrauch vorzubeugen. Denn das Prinzip der Sitzung allgemein ist eigentlich sehr nützlich und oft auch notwendig. Nur die Implementierung ist oft sehr brüchig und unsicher gestaltet.

Lesenswerte Lektüre zum Thema sind die Artikel „The Truth about Sessions“ von Chris Shiflett sowie „Web Based Session Management“ von Gunter Ollmann. Auch die Websites beider Autoren sind sehr interessant und einen Blick wert.
 
Ich danke dir Gumbo.
Ich werde mich noch ein bisschen informieren und dann entscheiden ob ich mir meine eigene "Session-Klasse" schreibe.
Das Problem ist leider, dass man den User schlecht identifizieren kann wenn er Cookies deaktiviert und dann evtl noch einen Proxy ( Anonymisierungsservice wie TOR und Co ) benutzt..
Wenn ich eine Klasse schreiben möchte die genauso arbeitet wie die Sessions von PHP, allerdings die Daten in der MySQL DB ablegt ( hab gelesen es soll 3 mal schneller sein diese auszulesen bzw 10 mal schneller wenn die DB schon geöffnet ist, was ja in fast jedem Script der Fall ist ) und die User anhand anderer Methoden bzw Merkmalen wieder erkennt als das Cookie oder die SessionID in der URL, welche Erkennungsmerkmal des User kann ich da noch nutzen? Wenn ich die IP nutzen würde, muss ich ja sicher gehen dass alle Daten der Sitzung dieser IP gelöscht werden wenn der User SEINE IP nicht mehr hat. Kann man da mit einem Timeout oder etwas ähnlichem arbeiten? Mir schwirren viele Ideen im Kopf aber mir fehlen noch ein paar Denkanstöße dazu ;)


Danke für die Hilfe
MFG
Sandro
 
Chris Shiftlett schlägt die User-Agent-Kennung vor, die – anders als die IP-Adresse – besser geeignet ist, um eine Anfrage auch über einen größeren Zeitraum zu validieren. Er setzt sie aber nur innerhalb der Sitzung selbst ein, um eine Sitzungs-ID eines User Agent zu validieren. Ich würde sie jedoch sogar als Teil des Sitzungs-ID-Bezeichners (Standardwert „PHPSESSID“) einsetzen und alle nicht passenden zurückweisen.
 
Habe mir das Buch Sicherheitsrisiko Web-Anwendung von Sverre H. Huseby
( http://www.dpunkt.de/buecher/3-89864-259-3.html ) bestellt. Er behandelt dort unter anderem Crosssitescripting und SQL-Injections.
Das mit der User-Agent-Kennung ist sehr unsicher da ich in meinem Firefox zb. das Plugin User-Agent-Switcher nutze um mein Statistikmodul zu testen.
Mit diesem kann ich mir jede erdenkliche User-Agent-Kennung geben und könnte mit der Session-ID in die Session einsteigen.

Sessions und Sicherheitsmechanismen bei Webanwendungen ist eine sehr interessante Angelegenheit ;)

Ich habe von einem User aus diesem Forum eine PM bekommen indem er sein System beschreibt.

Ich hab da so n PHP Security-Buch gelesen (findeste auf amazon.de, "PHP-Sicherheit" heissts). Dadurch bin ich überhaupt so "gut" informiert, bzw. mein Sicherheitsdenken ist dadurch geweckt empfiehlt sich das mal anzuschaffen, auch wenns nicht unbedingt billig ist.

Okay, jedenfalls bin ich da stark ins grübeln gekommen. Man sagt, man solle auf die PHPSession-Funktion zurückgreifen und KEINE Userdaten im Cookie speichern. im selben buch steht aber auch, dass man per XSS-Angriffe (im hauptsächlichen durch einbringen von HTML-Code in die Datenbank) Cookies auslesen kann - und die SessionID von PHP wird als Cookie gespeichert. Du wirst nun wohl sehen worauf ich hinaus will: Kann man XSS durchführen, kann man sich die SessionIDs erschleichen und sich selbst ein Cookie setzen - und zack, hat man womöglich sogar zugriff auf einen Adminaccount. Fatal.

Ich hab mir nun die Frage gestellt: Wie kann ich eine möglichst sichere Session gestalten, ohne dass Userdaten wie Username und das md5(passwort) beim User per Cookie gespeichert werden?

Da bin ich nach einiger Zeit des Überlegens auf die Idee gekommen - mach eine eigene Session. Gesagt getan.

Was wird benötigt?
- Einen Code-Generator. Ich habe mir da einen geschmiedet, der einen 128bit Schlüssel erstellt. dürfte eigentlich ziemlich unmöglich sein, den zu knacken, da er aus insgesamt 3 teilen besteht (2x 50 bit, 1x 28 bit, sprich 3 zufallsparameter. Lässt sich aber beliebig erhöhen wie man will, man kann auch 12 zufallszahlen generieren und diese aneinanderreihen)
- Ein zusätzliches Feld in der Userdatenbank, namens sessionid. Hierin wird der generierte Sessioncode gespeichert.
- Ein Cookie, z.B. mit dem Namen cmsname_sessionid und als value die eigene 128bit sessionid
- Die PHP-Session. Warum? Ganz einfach. Bei erfolgtem Login werden sämtliche Userdaten AUSSER das PW in die $_SESSION-Variable gelegt. Die ist erstens ständig verfügbar solange die PHP-Session besteht, und zweitens brauchen wir die um einen Timestamp der Zeit des erfolgten Logins zu erstellen.

Das ist also die Grundbasis.
Nun brauchen wir eine Funktion, die überprüft ob der User existiert. Dies macht sie, in dem sie die Datenbank connektiert. Die vom Benutzer übergebenen Daten werden NICHT in dieser Abfrage erwähnt. Es wird eine Abfrageschleife gestartet, die die Usernamen abgleicht. Beispiel:

Code:
PHP-Code:
while($getUserData = mysql_fetch_object($query)) {
     if(md5($getUserData->username) == md5($_POST['username'])){
          weitere prüfungen...
Warum bei Usernamen md5 einsetzen? ist n zuverlässiger Check ob die groß/kleinschreibung beachtet wurde
Gibt es dann den User und stimmt das Passwort, löst diese Funktion die eigentliche Session-Funktion aus. Diese macht nun folgendes:

1.: Generierung des SessionCodes
2.: Speichern des Sessioncodes im Cookie (MIT! Sessionverfallsdatum!)
3.: Speichern des Sessioncodes in der Datenbank
4.: Starten der PHP-Session
5.: Speichern aller Userdaten ausser dem PW in der $_SESSION-Variable
6.: Speichern des Logintimestamps in der $_SESSION-Variable.

Okay, das alles nutzt aber noch gar nichts. Es wird eine SessionStart-Funktion benötigt Hier wird NICHT die startsession() funktion von PHP genutzt, sondern wieder eine eigene. die wird am ANFANG jeder PHP-Datei gesetzt. diese macht dann folgendes:

1.: Ist der sessioncookie mit 128Bits vorhanden?
2.: wenn nein - juckt uns nicht, dann wird eben nichts gemacht und zur Sicherheit $_SESSION = array(); und session_destroy(); ausgeführt. schaden kann es nicht.
3.: wenn der Cookie existiert, wird ersteinmal überprüft, ob schon eine PHP-Session existiert.
4.: wenn JA - dann wird überprüft - und aha - ob der $_SESSION['timestamp'] ÄLTER ist als die aktuelle zeit - abzüglich 60 sekunden!
5.: wenn dies zutrifft wird die eigene Session regeneriert - sprich ein neuer code wird generiert, im cookie und in der Datenbank gespeichert. der user bekommt dies gar nicht mit.
6.: falls punkt 3. nicht zutrifft, checken wir, ob es diesen Sessioncode in der Datenbank gibt.
7.: Falls ja, dann wird der User wieder eingeloggt, sprich neue PHP-Session erstellt und Userdaten hineingeladen sowie auch wieder ein Timestamp erstellt.

Sooo, okay. Man kann nun ja auch Cookies manipulieren, deswegen brauchen wir noch eine Funktion, die auch checkt, ob der Cookie gültig ist. Er muss aus 128 zeichen bestehen, darf keine Sonderzeichen beinhalten und vor allem keine script-parameter. Falls der Cookie manipuliert ist -> die(); und hackversuch loggen. PHPSession-Cookie sollte man auch prüfen, und zwar auf vorhandensein eines int-Values, sprich dieser Cookie darf nur aus 12 zeichen und ausschliesslich aus zahlen bestehen.

Jetzt brauchen wir noch eine Logout-Funktion. Diese Funktion macht die Session in der Datenbank ungültig (durch einen nicht-128bit-schlüssel, denn es sind ja NUR 128Bits zugelassen), killt den eigenen Sessioncookie und killt die Variable $_SESSION. Zudem setzt er in der usertabelle das feld "loggedin" auf 0.

Der einzige Unsicherheitsfaktor ist die Lebensdauer des Sessioncookies mit der selbst erstellten Session-ID. Wenn ein User dauerhaft eingeloggt sein will, muss die Lebensdauer des Cookies erhöht werden. Kann man ja auch auf 7 Tage begrenzen oder was auch immer, selbst dann ist es eher nicht möglich per Bruteforce-Attacken die Sessionid zufällig bei einem nicht-ausgeloggten User zu finden. Doch je länger der Cookie mit dem zuletzt benutztem Sessionkey existiert, desto höher ist die Wahrscheinlichkeit, dass der Account gehighjacked werden kann. Allerdings ist die Wahrscheinlichkeit auch nich allzu hoch, geh ich mal davon aus.

Wichtig ist natürlich auch alle Abfragen vor manipulierten Daten zu schützen, aber das versteht sich, denk ich mal, nun auch von selbst

Zusammengefasst schauts so aus:
- Userlogin wird nicht direkt, sondern per Schleife aus der Datenbank gelesen
- PHPSession zum temporären Speichern der Userdaten, erspart später unnötige MySQL-Connections.
- Eigene Sessionid mit >= 128bits, die sich alle 60 sekunden neu generiert
- Secure-Logout: Komplette Session wird zerstört, in der Datenbank sowie auch bei den Cookies und der $_SESSION Variable

So, das war reichlich Text, aber im Groben spiegelt das mein eigenes Loginscript wider. Und ich denk mal, dass es wohl eines der Sichersten ist, die ich persönlich kenne.

Das ist die PM mit der Beschreibung seines Systems.
Ich habe es mit angeschaut aber leider nutzt mir die Methode mit den Cookies nix.
Aber die Idee mit dem 128bit Schlüssel ( ID ) die alle 60 sek neu generiert wird ist sehr interessant.
Leider basiert das alles auf Cookies ( die deaktiviert werden können ) oder URL-Parameter ( die mir zu unsicher sind )

MFG
Sandro
 
Das mit der User-Agent-Kennung ist sehr unsicher da ich in meinem Firefox zb. das Plugin User-Agent-Switcher nutze um mein Statistikmodul zu testen.
Mit diesem kann ich mir jede erdenkliche User-Agent-Kennung geben und könnte mit der Session-ID in die Session einsteigen.
Die Berücksichtigung der User-Agent-Kennung würde selbstverständlich mehr Sicherheit bieten, da nur ein aus der User-Agent-Kennung generierter Sitzungs-ID-Bezeichner akzeptiert würde. Und selbst wenn die User-Agent-Kennung fehlt oder leer ist, wäre der generierte Sitzungs-ID-Bezeichner ein anderer als das allzu offensichtliche „PHPSESSID“.
Die Frage ist dann allerdings, was passieren soll, wenn die User-Agent-Kennung sich ändert, da beispielsweise der Webbrowser aktualisiert wurde. Dort wäre dann – falls es Teil eines Authentifizierungssystems ist – eine Authentifizierung des Benutzers nötig.
 
Ok, ich habe keine großen PHP Kenntnisse, daher wenn ich einen Login realisieren würde, würde ich per Formular Username und Passwort übergeben, die Post Daten mit Daten in der Datenbank vergleichen, wenn die Daten übereinstimmen eine Session starten, z.B. $_SESSION['loggedin']. Es würde nichts per URL übergeben werden. Bedeutet also Cookies müssen aktiviert sein, was mich aber nicht stört. Ist die Session gesetzt, bekommt der User Zugang zu den "geheimen" Daten, andernfalls eben nicht.
Für einen dauerhaften Login würde ich einen Cookie setzen, auch einfach nur $_COOKIE['loggedin']. Ist dieser gesetzt wird ebenfalls zutritt gewährt. Zum ausloggen wird die Session und der Cookie gelöscht. Ich speichere also keine Userdaten, wie Name oder Passwort in der Session oder dem Cookie. Ist das jetzt irgendwie super Risiko behaftet?

Und danke für die Links, Gumbo, sieht interessant aus, werde ich mir wenn Zeit ist alles mal genauer ansehen.
 
Eigene Cookies anzulegen ist mit vielen Browsern ein Kinderspiel. Denn entweder besitzt der Webbrowser selbst schon eine solche Funktion oder sie lässt sich durch Erweiterungen bequem nachrüsten. Notfalls kann der Cookie auch direkt am Speicherort der Cookies hinzugefügt werden, kennt man sich mit dem Webbrowser etwas aus. So wäre es also eine Leichtigkeit sich als jemand anderes beim System anzumelden, hat man erst mal die Sitzungs-ID eines Benutzers.
Wird die Sitzungs-ID regelmäßig gewechselt, kann der Schutz vor einer solchen Entführung der Sitzung erhöht werden. Zusätzlich kann auch eine weitere Validierung der Anfrage (beispielsweise der Vergleich der User-Agent-Kennung) die Sicherheit erhöhen. Das System sollte dann aber natürlich auf ungültige Anfragen entsprechend reagieren, um einen Missbrauchsversuch zu verhindern.
 
Ja ok, aber wenn ich die Sitzungs ID nicht über die URL übergebe, wo wird sie noch für einen möglichen Angreifer sichtbar? Wird sie das überhaupt? Also in meinem Beispiel, wäre es also für einen Angreifer möglich, die $_SESSION['loggedin'] ganz einfach zu fälschen?
 
Zurück