PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Anfängerfrage zu Sessions (PHP)


RattuS
2009-09-13, 00:01:23
Hallo,

die Funktion session_start() erzeugt Sessions bzw. setzt diese fort, sofern vorhanden. Ich habe einen Navigation A und einen Login auf Seite A. Wenn die Anmeldung erfolgreich ist, soll eine Session erzeugt werden (bzw. ist sie zu diesem Zeitpunkt erzeugt), in der ich die ID des Logins speichere. Seite A wird nun zum "identifizierten" Bereich. Navigation A soll an dieser Stelle allerdings ebenfalls "identifiziert" sein. Ich habe also auf jeder Seite des "identifizierten" Bereiches ein session_start() in der Navigation A. Das funktioniert soweit auch. Allerdings frage ich mich, ob das eine wirklich sinnvolle Umsetzung ist, da jeder Besucher, auch wenn er sich nicht einloggt, das session_start() in der Navigation A auslöst. Wäre es ratsam, den Login und die Navigation auszulagern, d.h. von Seite A auf Seite B weiterleiten, die eine Navigation B hat, die session_start() beinhaltet und Navigation A dann ohne session_start() zu haben. Was denkt ihr? Bzw. wie speicherkritisch ist session_start() überhaupt? Wann weiß der Server, dass eine Session nicht mehr benötigt wird (mal abgesehen von unset()).

Eine noch allgemeinere Frage: Ist es effektiver, wenn ich Form-Auswertungen prinzipiell in separaten Dokumenten verarbeite und danach weiterleite? Diese Weiterleitung mit header(seite.php) könnte bei bestimmten Browser-Einstellungen aber ignoriert werden oder?
Noch eine Frage: Was spricht für einen MD5-Hash bei Passwörtern in einer Datenbank? Wenn jemand an die Tabelle mit den Passwörtern rankommt, hilft MD5 auch nicht wirklich oder?

Fragen über Fragen. Danke im voraus. ^^

mapel110
2009-09-13, 00:09:41
Hm, also bei mir was das so.

Login.php <-- Session wird gestartet und Logindaten abgefragt
logincheck.php <-- wie der Name sagt, überprüfen der Daten, falls Daten nicht korrekt gehts zurück zur Login.php, ansonsten wird eine Session-Variable erzeugt, die eben den Login bestätigt.

von da aus dann ein redirect auf meine eigentliche PHP-Datei, wobei ich eben die Sessionvariable abfrage, ob der Login erfolgreich war, ansonsten auch hier ein redirect auf die Login.php

Hoffe, es ist verständlich. Alles wieder so lange her. :ugly:

p.s. zu Sessions gibts recht viel Material Online
http://www.usegroup.de/software/phptutorial/sessions.html
http://tut.php-q.net/de/sessions.html

RattuS
2009-09-13, 00:13:27
Login.php <-- Session wird gestartet und Logindaten abgefragt
logincheck.php <-- wie der Name sagt, überprüfen der Daten, falls Daten nicht korrekt gehts zurück zur Login.php, ansonsten wird eine Session-Variable erzeugt, die eben den Login bestätigt.

von da aus dann ein redirect auf meine eigentliche PHP-Datei, wobei ich eben die Sessionvariable abfrage, ob der Login erfolgreich war, ansonsten auch hier ein redirect auf die Login.php
Das heißt, dass du vor dem Login-Check auch erstmal eine Session startest oder? Wobei, mir fällt gerade auf, dass man gar nicht um session_start() herumkommt, da man sonst die $_SESSION-Variable gar nicht prüfen kann. :confused:

Der Web-Literatur vermag ich nicht wirklich zu trauen. Einige reden von veralteten Funktionen aus PHP4, die ab PHP6 rausfliegen, andere empfehlen, dass man die Session-ID in der URL oder Hidden Inputs stecken soll. Aber danke für den 2. Link, jetzt weiß ich, dass die Sessions etwa 30 Minuten im Speicher bleiben.

rotalever
2009-09-13, 00:16:48
Also ich erzeuge Sessions nur wenn sie auch wirklich benötigt werden.
Beim Einloggen mache ich das so:
login.php: user logged sich ein, login.php überprüft das Passwort, wenn ok dann Weiterleitung auf login_pruefen.php, wenn nicht, auf login.php verbleiben.
login_pruefen.php prüft ob der cookie die korrekten Daten hat, wenn ja, dann weiterleiten auf die gewünschte Seite, sonst session löschen und weiterleiten zurück zu login.php mit einem entsprechenden Parameter, sodass login.php dem Nutzer mitteilen kann, die Cookies zu aktivieren.

Formulare mach ich so das alles über eine Datei läuft. Bei manchen Formularen auch die Ausgabe, dass alles OK ist auf einer extra Seite, sodass beim versehentlichen Reload des Benutzers das Formular nicht noch mal abgeschickt wird.

Hashen des Passworts in der DB ist wichtig, da ein Angreifer sonst die Klartextpassworte erhalten würde. Viele Nutzer verwenden ihre Passwörter auf verschiedenen Seiten, das gibt dann viele Möglichkeiten. Md5 aber nicht mehr verwenden. Besser sha256 (nicht sha-1!) oder ähnliches und die Passwörter salzen.

rotalever
2009-09-13, 00:18:09
$_SESSION-Variable gar nicht prüfen kann. :confused:

Geht doch mit isset() etc.

RattuS
2009-09-13, 00:19:18
Wenn ich isset($_SESSION['var']) ohne session_start() prüfe, ist die Rückgabe immer false. D:

rotalever
2009-09-13, 00:24:23
Wenn ich isset($_SESSION['var']) ohne session_start() prüfe, ist die Rückgabe immer false. D:
Ja stimmt, das macht Sinn :smile: War mir nicht klar, da ich meist alles selber implementiere.

Allerdings könntest du den $_COOKIE abfragen, da die Sessions ja in Cookies gespeichert werden?

RattuS
2009-09-13, 00:29:42
Hashen des Passworts in der DB ist wichtig, da ein Angreifer sonst die Klartextpassworte erhalten würde. [...] Md5 aber nicht mehr verwenden. Besser sha256 (nicht sha-1!) oder ähnliches und die Passwörter salzen.
Hm ja, das macht Sinn. Aber können diese Hashs über Rainbow Tables nicht trotzdem entschlüsselt werden? Gegen eine Implementierung spricht natürlich nichts. Danke für den Tipp.

rotalever
2009-09-13, 00:40:42
Hm ja, das macht Sinn. Aber können diese Hashs über Rainbow Tables nicht trotzdem entschlüsselt werden? Gegen eine Implementierung spricht natürlich nichts. Danke für den Tipp.
Rainbow Tables funktionieren soweit ich weiß nicht mehr wenn man jedes Passwort mit einem unterschiedlichen Wert salzt, da man dadurch ja die Länge des Passworts sozusagen erhöht, wodurch einfache Passwörter der Benutzer, die man leicht über Rainbow Tables wieder herstellen könnte nun nicht mehr so leicht rückzugewinnen sind.
Dadurch kann der Angreifer nur noch Bruteforce verwenden, was entweder nur bei ganz einfachen Passwörtern schnell geht oder sonst eben nur für wenige der Passwörter in der DB in vertretbarer Zeit. Dann lohnt es sich für den Angreifer nicht mehr so stark.

Coda
2009-09-13, 12:54:36
Besser sha256 (nicht sha-1!) oder ähnliches und die Passwörter salzen.
Das ist auch nur SHA mit längerem Ergebnis. So unsicher ist SHA-1 auch noch nicht.

Eigentlich sollte man etwas neueres verwenden, aber da haben sich die Kryptoheinis ja noch nicht geeinigt was gut oder schlecht ist.

rotalever
2009-09-13, 13:07:37
Immerhin empfehlen die hier
http://csrc.nist.gov/groups/ST/hash/policy.html
sha-256 anstelle von sha-1 zu verwenden, also würde ich jetzt mal sagen, dass der schon irgendwie sicherer ist.
Aber es stimmt natürlich, dass man sich auch nach anderen umschauen muss. Vielleicht irgendwie RIPEMD-160 oder Whirlpool?

Letztendlich scheitert es dann daran, dass die Leute "Geheim" oder ähnliches als Passwort wählen...

dav133
2009-09-13, 13:15:52
Wann weiß der Server, dass eine Session nicht mehr benötigt wird (mal abgesehen von unset()).

Bitte nie unset für Sessions verwenden, dazu gibt es session_destroy.

Diese Weiterleitung mit header(seite.php) könnte bei bestimmten Browser-Einstellungen aber ignoriert werden oder?

Mir wäre kein Browser bekannt, der einem HTTP-Redirect nicht folgt. Bei Javascript window.location-Geschichten ist da die Gefahr wesentlich größer. ein Location-Wechsel per PHP ist eigentlich die beste Art der Weiterleitung.

Noch eine Frage: Was spricht für einen MD5-Hash bei Passwörtern in einer Datenbank? Wenn jemand an die Tabelle mit den Passwörtern rankommt, hilft MD5 auch nicht wirklich oder?

Wie schon beschrieben: Die beste (und gegen Rainbow-Tables verlässlichste) Variante ist das erzeugen eines nicht-MD5-Hashs mit einem angehangenen, geheimen String (salt). Allerdings ist md5 um längen besser als keine Verschlüsselung. Soweit ich weiß, wurden nur ein paar Kollisionen beim MD5-Algo gefunden (d.h. 2 verschiedene Inputs führen zum selben Hash). Das ist aber bei keinem Hash zu vermeiden, nur kann man die Wahrscheinlichkeit einer Kollision senken. Dann würde deine PW-Generierung etwa so aussehen $pwForDatabase = sha1($mySalt.$userPw);

lg

RattuS
2009-09-13, 13:33:04
Ich habe hier (http://phpperformance.de/session-verwaltung-optimieren/) übrigens die Antwort auf die session_start()-Frage bekommen:

Ich werde sha1 mit Salt für die Passwörter verwenden. sha256 ist vielleicht etwas Overkill für mein kleines nicht-kommerzielles Projekt, da ich es erst implementieren müsste, wobei es den Code ja im Netz gibt. :uponder:

DanMan
2009-09-13, 15:45:14
Ja stimmt, das macht Sinn :smile: War mir nicht klar, da ich meist alles selber implementiere.

Allerdings könntest du den $_COOKIE abfragen, da die Sessions ja in Cookies gespeichert werden?
Dann musst du aber alle ohne Cookies aussperren, weil die Session-ID dann ja in der URL stünde.

Nebenbei bemerkt gibts auch noch die HTTP-auth Methode, die ohne Session auskommt. Wenn der Server Digest-Authentication unterstützt, dann ist das eine recht sichere Alternative.

Die Frage bei sowas ist immer: geht es um Sicherheit oder eigentlich um Identifizierung (oder beides, klar). Für Identifizierung ist die Session ok (Cookies tuns aber auch), für Sicherheit würd ich eher die komplette Seite über HTTPS laufen lassen.

fezie
2009-09-13, 15:51:24
Ich werde sha1 mit Salt für die Passwörter verwenden. sha256 ist vielleicht etwas Overkill für mein kleines nicht-kommerzielles Projekt, da ich es erst implementieren müsste, wobei es den Code ja im Netz gibt. :uponder:

Wieso selber implementieren?
Musst halt nur statt sha1($pw) eben hash("sha256", $pw) verwenden.
http://de.php.net/manual/de/function.hash.php

RattuS
2009-09-13, 16:18:57
Wieso selber implementieren?
Musst halt nur statt sha1($pw) eben hash("sha256", $pw) verwenden.
http://de.php.net/manual/de/function.hash.php
Oh, danke für den Hinweis. ^_^

dav133
2009-09-13, 18:06:46
Ist ja sehr interessant, bei den Kommentaren auf PHP.net grad gesehen, dass print_r(hash_algos()); alle unterstützten algos wunderbar ausliefert. Wusste noch garnicht, dass es so eine Funktion gibt.

lg

rotalever
2009-09-13, 18:11:17
Dann musst du aber alle ohne Cookies aussperren, weil die Session-ID dann ja in der URL stünde.

Ja, so macht man das dann :biggrin: Session-ID in der Url ist auch nicht gut.


Die Frage bei sowas ist immer: geht es um Sicherheit oder eigentlich um Identifizierung (oder beides, klar). Für Identifizierung ist die Session ok (Cookies tuns aber auch), für Sicherheit würd ich eher die komplette Seite über HTTPS laufen lassen.
HTTPs bringt doch eh nur was gegen man-in-the-middle Attacken, ansonsten erhöht das auch nicht die Sicherheit.
Zu Sicherheit zählen dann auch so sachen wie schwierigkeit des Erraten von Sessioncookies und so.

fezie
2009-09-13, 18:18:46
Ist ja sehr interessant, bei den Kommentaren auf PHP.net grad gesehen, dass print_r(hash_algos()); alle unterstützten algos wunderbar ausliefert. Wusste noch garnicht, dass es so eine Funktion gibt.

lg

Gibts auch erst seit 5.1.2
http://de.php.net/manual/de/function.hash-algos.php

The_Invisible
2009-09-13, 21:25:56
session handling ist sowieso ein eigenes kapitel, vor allem wenn es unterschiedliche stufen einer session geben soll (registered, moderator, admin zb) und der kleinere auf features der größeren auf keinen fall kommen soll.

man sollte da nicht unbedingt ne session variable registrieren die den wert hinterlegt hat und danach gehen, vielleicht noch mit globalen variablen aktiviert. aber selbst auf gleicher stufe muss überprüft werden ob das zu bearbeitende objekt dem benutzer überhaupt gehört usw.

es gibt da so viel zu beachten, mir selbst hängt es schon zum hals raus und habe meine eigene klassen dazu.

mfg

DanMan
2009-09-13, 22:55:39
HTTPs bringt doch eh nur was gegen man-in-the-middle Attacken, ansonsten erhöht das auch nicht die Sicherheit.
Zu Sicherheit zählen dann auch so sachen wie schwierigkeit des Erraten von Sessioncookies und so.
Mit Sessions ohne HTTPS wird das Passwort unverschlüsselt als Klartext übers Netz geschickt. Bedeutet schon mal eine Hürde weniger für einen Angreifer.

dav133
2009-09-13, 23:26:34
es gibt da so viel zu beachten, mir selbst hängt es schon zum hals raus und habe meine eigene klassen dazu.

dito. Grad bei so sicherheitsrelevanten, wichtigen Sachen sollte man lieber auf bewährte Techniken zurückgreifen oder sich zumindest stark inspirieren lassen. Eine sehr schöne Zusammenfassung von Angriffstechniken mit wirksamen Gegenmaßnahmen samt Quellcode gibt es hier (http://carsonified.com/blog/dev/how-to-create-bulletproof-sessions/), man glaubt nämlich garnicht wie extrem kreative Techniken es gibt, das Session-System auszuhebeln.

lg

RattuS
2009-09-14, 00:14:54
Neue Frage: Wie kann ich auf Anwender mit deaktivieren Cookies reagieren? Nach dem Login könnte ich doch theoretisch auf den Cookie mit der Session-ID prüfen oder? Aber wie? Wie bekomme ich die Session aus $_COOKIE bzw. ist $_COOKIE bei einer Session automatisch ergänzt und bei deaktivieren Cookies leer?

Edit: Wenn ich die Array-Größe von $_COOKIE mit count() prüfe, weiß ich ja eigentlich schon, ob Cookies akzeptiert wurden oder nicht. Trifft das generell zu?

dav133
2009-09-14, 10:37:48
Neue Frage: Wie kann ich auf Anwender mit deaktivieren Cookies reagieren? Nach dem Login könnte ich doch theoretisch auf den Cookie mit der Session-ID prüfen oder? Aber wie? Wie bekomme ich die Session aus $_COOKIE bzw. ist $_COOKIE bei einer Session automatisch ergänzt und bei deaktivieren Cookies leer?

Es gibt einmal "Session-Cookies" und einmal "Cookies". Bei einer sessionbasierten Heransgehensweise wird auf dem User-PC nur die Session-ID in besagtem Session-Cookie gespeichert - alles, was du in der Session unterbringst wird auf dem Server in der Regel in einem /tmp-Verzeichnis abgelegt. Der Session-Cookie weißt dem User also nur "seine" Daten im /tmp-Verzeichnis zu.

Die Cookies (setcookie(...)) werden vollends lokal auf dem Rechner gespeichert, der Server kriegt davon also nichts mit, da sie quasi "durch den Browser" an ihn gesendet werden. Bei abgeschalteten Cookies ist diese Form der Identifizierung also definitiv nicht möglich.

Ob jetzt die Session-Cookies von abgeschalteten Cookies auch betroffen sind, wäre zu prüfen, denke aber schon. In diesem Fall würde dann die Session-ID an die URL angehangen werden.

Ob Cookies aktiviert sind koenntest du so prüfen: function areCookiesActive()
{
setcookie('cookieCheck', 'test', time() + 60);
return ($_COOKIE['cookieCheck']=='test');
}

lg

RattuS
2009-09-14, 14:58:35
Ob jetzt die Session-Cookies von abgeschalteten Cookies auch betroffen sind, wäre zu prüfen, denke aber schon. In diesem Fall würde dann die Session-ID an die URL angehangen werden.
Die Session fordert vom Anwender, dass er einen Cookie mit der auf dem Webserver zugewiesenen SID lokal speichert. Wenn der Anwender aber keine Cookies akzeptiert, hat er auch keinen Cookie mit SID. Folglich kann er sich nicht identifizieren. Meine Idee war, dass ich direkt nach dem Start der Session prüfe, ob der Anwender einen Cookie mit der SID besitzt, denn das wäre der Soll-Zustand für weiteres Gelingen.

Der Code, den du gepostet hast, funktioniert übrigens so nicht, da der Cookie erst nach einem Reload abgerufen werden kann.

Hab eine Lösung gefunden: Mit isset($_COOKIE['PHPSESSID']) kann ich prüfen, ob die Session angelegt wurde.

rotalever
2009-09-14, 16:59:47
Mit Sessions ohne HTTPS wird das Passwort unverschlüsselt als Klartext übers Netz geschickt. Bedeutet schon mal eine Hürde weniger für einen Angreifer.
Ja, aber wie gesagt, bringt es nur etwas gegen man-in-the-middle Attacken. Wenn ich mich direkt über meinen Router mit T-online oder was auch immer zu dem Server verbinde, ist dieses Risiko wohl eher gering.
dito. Grad bei so sicherheitsrelevanten, wichtigen Sachen sollte man lieber auf bewährte Techniken zurückgreifen oder sich zumindest stark inspirieren lassen. Eine sehr schöne Zusammenfassung von Angriffstechniken mit wirksamen Gegenmaßnahmen samt Quellcode gibt es hier (http://carsonified.com/blog/dev/how-to-create-bulletproof-sessions/), man glaubt nämlich garnicht wie extrem kreative Techniken es gibt, das Session-System auszuhebeln.
lg
Die Seite schlägt aber vor, die Sessions an einen Host/Ip zu binden. Das funktioniert aber bei gewissen Providern nicht.

Es gibt einmal "Session-Cookies" und einmal "Cookies". Bei einer sessionbasierten Heransgehensweise wird auf dem User-PC nur die Session-ID in besagtem Session-Cookie gespeichert - alles, was du in der Session unterbringst wird auf dem Server in der Regel in einem /tmp-Verzeichnis abgelegt. Der Session-Cookie weißt dem User also nur "seine" Daten im /tmp-Verzeichnis zu.

Gibt es tatsächlich diesen Unterschied zwischen den Cookies, oder ist das dann nur eine Frage wie man das dann in PHP handhabt? Ich dachte der einzige Unterschied sei die Dauer bis der Cookie abläuft.


Ob jetzt die Session-Cookies von abgeschalteten Cookies auch betroffen sind, wäre zu prüfen, denke aber schon. In diesem Fall würde dann die Session-ID an die URL angehangen werden.
Ja, aber das sollte man vermeiden, da es Benutzer gibt, die die URL mit der enthaltenen Session-ID dann kopieren und dann kann viel schlechtes passieren.



Um zu prüfen ob Cookies funktionieren, hatte ich ja am Anfang mal was vorgeschlagen, dass man nach dem Login auf eine Cookie-Prüf-Seite weiterleitet, die den beim Login gesetzten Cookie checkt, ist er Okay, wird der Benutzer weitergeleitet, andernfalls zurück zu login und Ausgabe einer Fehlermeldung.

RattuS
2009-09-14, 17:07:14
Um zu prüfen ob Cookies funktionieren, hatte ich ja am Anfang mal was vorgeschlagen, dass man nach dem Login auf eine Cookie-Prüf-Seite weiterleitet, die den beim Login gesetzten Cookie checkt, ist er Okay, wird der Benutzer weitergeleitet, andernfalls zurück zu login und Ausgabe einer Fehlermeldung.
So hab ich das jetzt auch gelöst. Wenn der Benutzer seine Cookies während der Session deaktiviert, wird er allerdings ohne Meldung auf die Login-Seite zurückgeschmissen.

rotalever
2009-09-14, 17:28:08
Das reicht dann ja auch. Wenn er sich dann neu anmeldet, bekommt er ja die Meldung.

DanMan
2009-09-14, 18:48:41
Hab eine Lösung gefunden: Mit isset($_COOKIE['PHPSESSID']) kann ich prüfen, ob die Session angelegt wurde.
Das geht auch mit session_id()Wenn der Rückgabewert keine Session-ID ist, dann läuft noch keine Session.

RattuS
2009-09-14, 19:04:33
Das geht auch mit session_id()Wenn der Rückgabewert keine Session-ID ist, dann läuft noch keine Session.
Die Session läuft webserverseitig ja, nur clientseitig läuft die Session bei deaktivieren Cookies nicht.

rotalever
2009-09-14, 22:23:42
Die Session läuft webserverseitig ja, nur clientseitig läuft die Session bei deaktivieren Cookies nicht.
Hmm.. Auf dem Server sind ja immer viele Sessions gespeichert, aber wenn der Client den Cookie deaktiviert hat, weiß der Server ja gar nicht, welcher Client da jetzt gerade ist, kann also auch keine Session diesem Client zuordnen. Deshalb sollte dann session_id() auch "" zurückliefern.

fezie
2009-09-14, 22:26:06
Das Problem ist nur das die Session ID erst existiert nach dem session_start () aufgerufen wurde.
Und das wird eben wenn keine Cookies erlaubt sind und trans_sid abgeschaltet ist, eben jedesmal eine neue Session erzeugen mit neuer ID.

rotalever
2009-09-15, 17:52:51
Das Problem ist nur das die Session ID erst existiert nach dem session_start () aufgerufen wurde.
Und?

fezie
2009-09-15, 19:00:57
Die Session läuft webserverseitig ja, nur clientseitig läuft die Session bei deaktivieren Cookies nicht.

Das lässt sich damit überhaupt nicht unterscheiden.
Vor session_start gibt session_id () immer garnichts zurück und danach gibts entweder immer wieder selbe ID zurück oder immer wieder ne neue.
Also warum soll er überhaupt session_id verwenden?
Dann müsste er Serverseitig erstmal die Cliet IP speichern + UserAgent + was weiß ich noch was gut ist zum unterscheiden von NAT Verbindungen um festzustellen ob Sessions tatsächlich funktionieren oder nicht.
Da kann er auch einfach ein Test Cookie setzen.

rotalever
2009-09-15, 19:27:35
Das lässt sich damit überhaupt nicht unterscheiden.
Vor session_start gibt session_id () immer garnichts zurück
Achso Ok.