Ein paar grundlegende Sachen zur Sicherheit in PHP / MySQLi

Danke für den Link.

Rein zum Verständnis mal nachgefragt:
Ich habe die Session (bisher) immer angelegt und die Variablen mit session_register festgelegt.

Jetzt bin ich über session_create_id und session_id gestolpert.

Muss ich die SessionID manuell vergeben oder passiert das automatisch? Was ist mit dem Cookie? Wird der auch automatisch erstellt? Wenn ja, wie lösche ich den automatisch erstellten Cookie bei session_destroy? Bzw. kann ich irgendwie beim registrieren der Session die Lebenszeit des Cookies beschränken?

Achso und da steht ja ich soll einen eigenen Namen vergeben mit session_name. Gut , wenn ich das mache, Muss ich dann noch was ändern in den Scripten? Muss ich die Session anders aufrufen bzw. die Daten registrieren?
 
Zuletzt bearbeitet:
Hi,

Laut Doku ist das session_register mit 5.4 raus geflogen. Klar, das wurde ja nur benötigt um die globalen Variablen zu verarbeiten, was ja nicht mehr benötigt wird.

Das session_start() macht folgendens:
- Client hat Cookie mit SessionID geschickt?
-- Wenn ja: Session mit der gegebenen ID laden
-- Wenn nein: Neue Session erstellen und dem Client diese als Cookie geben

Die session_id() gibt dir nur die aktuelle ID zurück, diese kannst du zum Beispiel fürs Logging verwenden.
Die session_regenerate_id() generiert eine neue Session und schickt diese auch gleich dem Browser als Cookie rüber.

Muss ich die SessionID manuell vergeben oder passiert das automatisch?
Wird automatisch vergeben, ja nicht selber berechnen!

Was ist mit dem Cookie? Wird der auch automatisch erstellt?
Da kümmert sich rein PHP drum, ja.

Wenn ja, wie lösche ich den automatisch erstellten Cookie bei session_destroy?
Warum löschen? Du löscht die Session und machst somit die ID ungültig. Client kommt mit einer ungültigen ID an und bekommt somit eine neue, leere Session mit der ID. Beim Login bekommt er dann eine "richtige" Sesison zugeteilt.
Der Cookie selbst wird vom Browser nach Ablauf der Gültigkeit gelöscht, bzw. überschrieben wenn er eine neue ID bekommt.

Bzw. kann ich irgendwie beim registrieren der Session die Lebenszeit des Cookies beschränken?
http://www.php.net/manual/en/session.configuration.php
Die Session läuft standardmässig 24 Minuten (jeder Request setzt den Timer wieder auf "0"). Wenn du die Lebenszeit des Cookies anpassen willst, musst du auch die Gültigkeit der Session anpassen. (Es macht keinen Sinn den Cookie auf 10 Minuten zu beschränken wenn die Session 24h läuft oder umgekehrt.)

Grüsse,
BK
 
edit: Omg, bin ich wieder langsam :D

Ich habe selbstverständlich Kein PHP 5 mehr im Einsatz sondern das neuste
Ich habe die Session (bisher) immer angelegt und die Variablen mit session_register festgelegt.
php.net hat gesagt.:
session_register
Diese Funktion ist seit PHP 5.3.0 DEPRECATED (veraltet) und seit PHP 5.4.0 ENTFERNT.
:suspekt:
Du solltest das nochmal überprüfen...

...

Jedenfalls, die grundlegene Verwendung von Sessions ist ein session_start am Dateianfang und dann $_SESSION einfach verwenden (reinschreiben und später wieder rauslesen).

ID-Zeug (mit der eingestellten Defaultmethode, deren Sicherheit überprüft werden sollte) und Cookiezeug wird für dich automatisch erledigt.

Cookie löschen ist nicht unbedingt nötig, ein Cookie mit einer ID die serverseitig keine Daten mehr hat wird einfach ignoriert . Die serverseitigen Daten werden eben durch session_destroy entfernt (oder auch nach Ablauf der eingestellten Zeit, von PHP automatisch)

...

Es gibt ein paar andere Funktionen, aber ... naja, wenn man etwas spezielleres will kann es sinnvoll sein, das ganze Session-System selber zu machen (warum unten). Die oben beschriebene Grundverwendung wäre dann prinzipiell:
  • Eine DB-Tabelle SessionID-Ablaufzeitpunkt-Daten.
  • (Idealerweise) eIne Session-Klasse mit einer Variable ID, und Funktionen start, set, get, destroy (4 EInzelfunktionen und eine globale Variable würden auch reichen, aber ist klarerweise nicht ganz ideal)
  • Statt session_start die Funktion start: Wenn ein Cookie (Name selbst wählbar) mit einer SessionID, die in der DB ist, und deren Gültigkeitsdatum dort noch nicht überschritten wurde, existiert, dann: Diese ID als derzeitge SessionID in die Klassenvariable speichern, und den dazugehörenden Zeitpunkt in der DB auf x Minuten in der Zukunft setzen (Dauer wieder selbst wählbar), und das COokie auch neu setzen (selber Inhalt (die ID), aber entsprechende neu verlängerte Ablaufzeit). Falls es kein Cookie gab oder die ID in der DB nicht vorhanden war: Ein paar (zB. 20) Byte von dev/random lesen, die rohen Byte zB. hexadezimal nehmen, das als neue SessionID in die Klassenvariable speichern, einen neuen DB-Eintrag und ein neues Cookie setzen.
  • destroy: Den DB-Eintrag zur aktuellen SessionID (laut Klassenvariable) löschen. (Optional, nicht wirklich nötig, auch das Cookie neu setzen, mit einer Ablaufzeit in der Vergangenheit)
  • get/set: Die Daten vom DB-Eintrag zur SessionID lesen/schreiben
  • Irgendwo auch noch einen Cronjob oder so hin, der zB. einmal pro Stunde alle DB-Eintrage löscht, deren Gültigkeitszeit abgelaufen ist

Und warum (wann) man das so umständlch machen sollte? Verschiedene mögliche Gründe, zB.
  • Wenn die von PHP generierten SessionID nicht sicher sind (Entropie, wie schon irgendwo erwähnt) und man grad keinen Rootserver hat, bei dem man alles umstellen kann
  • Wenn man Kontrolle darüber braucht, wann Sessions ablaufen (wieder dann, wenn man das nicht umstellen kann, oder wenn man nicht immer die selbe Dauer will)
  • Wenn es wichtig ist, dass die Sessiondaten sekundengenau nach Ablaufdauer ungültig sind (PHP-Sessions können auch länger gültig sein, ohne ein bestimmtes Limit)
  • Wenn man die Cookiedaten kontrollieren will (ob es über JS zugreifbar ist (was es nicht sein sollte), ob es nur über HTTPS übertragen wird (worauf man sich bei PHP nicht immer verlassen kann, wenn die Seite selber HTTPS ist), ob der Browser das Cookie beim Schließen löschen soll (auch wenn es noch gültig wäre), ...)
  • Wenn man die Cookiedomain und -pfad kontrollieren will (zB. ob das Cookie auch für Subdomains der eigenen Seite gelten soll usw.usw.)
  • In manchen Fällen auch nötig wenn ein Login für mehrere verschiedene Sachen gilt (zB. ein Forum und eine Wordpressinstallation zusammen, wo man sich für beide zusammen ein/ausloggen können soll)
  • ...
 
Zuletzt bearbeitet:
Laut Doku ist das session_register mit 5.4 raus geflogen. Klar, das wurde ja nur benötigt um die globalen Variablen zu verarbeiten, was ja nicht mehr benötigt wird.

Das session_start() macht folgendens:
- Client hat Cookie mit SessionID geschickt?
-- Wenn ja: Session mit der gegebenen ID laden
-- Wenn nein: Neue Session erstellen und dem Client diese als Cookie geben

Die session_id() gibt dir nur die aktuelle ID zurück, diese kannst du zum Beispiel fürs Logging verwenden.
Die session_regenerate_id() generiert eine neue Session und schickt diese auch gleich dem Browser als Cookie rüber.
Also bedeutet das für mich ich kann jetzt folgendes machen?

PHP:
$_SESSION['Meine_var'] = $lalelu;

Zurück zum regenerate_id: Ich rufe das also einfach immer auf beim Login? Weil dann würde im Fall das einer nicht eingeloggt ist eine SessionID vergeben werden und im Falle er ist schon drin wird diese einfach refreshed?

Wenn ich Dich richtig verstanden habe, brauche ich mir um den Cookie keine Gedanken machen. Er lebt nur solange die Session existiert und seine Lebenszeit ist eh nur auf 24 Minuten beschränkt. Ich würde die Session dann einfach noch killen, wenn jemand länger als 5 Minuten inaktiv ist. (Zur Sicherheit) Dazu einfach als Session Variable time setzen mit time() als Inhalt und diese mit der aktuellen Zeit vergleichen.

Danke auch ab sheel. Ich glaube für mich und mein überschaubares Projekt macht das Entwickeln solcher eigenen Lösungen keinen Sinn ;)
 
Noch was Ergänzendes:

Wie kann ich denn reagieren wenn zwei verschiedene IPs einen Account (womöglich sogar zur gleichen Zeit) nutzen? Bzw. sollte ich darauf prüfen? Oder ist das für mich eher unerheblich? Weil eigentlich ist das ja auch eine Form von Sicherheit.

Dann könnte ich ja zumindest den Account sperren. Komme ich denn an die jeweiligen aktiven Session ran und kann die beiden rauswerfen? Wie würdet Ihr das lösen?
 
Wie kann ich denn reagieren wenn zwei verschiedene IPs einen Account (womöglich sogar zur gleichen Zeit) nutzen? Bzw. sollte ich darauf prüfen? Oder ist das für mich eher unerheblich? Weil eigentlich ist das ja auch eine Form von Sicherheit.
Das kann auch einen normalen Anwendungsfall darstellen: Ich benutze deine Seite einmal über den PC und einmal übers Handy mit Mobilfunk.

Übrigens würde ich mit dem Speichern von Formulardaten in der Session aus Usability Sicht vorsichtig sein. Dein Skript sollte z. B. korrekt damit umgehen, wenn der Nutzer zwei Tabs mit demselben Formular offen hat, diese parallel mit unterschiedlichen Daten füllt und abschickt.
 
Das heißt auf die beiden IPs eher nicht reagieren? Oder dem User eine Mitteilung ausgeben?

Zu deiner Einsendung hinsichtlich des Formulars:

Wie stelle ich das an, dass das möglich ist?
 
Das heißt auf die beiden IPs eher nicht reagieren? Oder dem User eine Mitteilung ausgeben?
Solange die beiden IPs unterschiedliche Sessions haben ist alles OK. Würde hier die Sessions an die ClientIP binden, sprich die ersten 2-3 Oktets der IP bei jedem Request mit der in der Session hinterlegten IP prüfen. Das ganze aber auch konfigurier- und abschaltbar machen. Es gibt nämlich auch Firmenproxies, die als Loadbalancing die ausgehenden Anfragen auf mehrere Leitungen / IPs verteilen.

Wie stelle ich das an, dass das möglich ist?
Bei jedem Formular eine UUID als hidden Text angeben und diese als "Schlüssel" für die Werte verwenden.
$_SESSION[$uuid + '_anschrift'] = $_POST['anschrift'];

Grüsse,
BK
 
Kann mir einer noch erklären was da der Unterschied zur normalen Speicherung in den Sessions ist? In beiden Fällen werden doch die Daten gespeichert und können wieder abgerufen werden? Wo ist also der Vorteil da nun eine uuid zu vergeben? Ist die uuid dann pro Formularseite zu vergeben oder pro Formular?

Achso ich wollte nochmal die eine Frage aufrufen. Weiß nicht ob sie eventuell untergegangen ist weil dann mehrere Poste waren:

Zurück zum regenerate_id: Ich rufe das also einfach immer auf beim Login? Weil dann würde im Fall das einer nicht eingeloggt ist eine SessionID vergeben werden und im Falle er ist schon drin wird diese einfach refreshed?

Solange die beiden IPs unterschiedliche Sessions haben ist alles OK
Wie prüfe ich denn ob es zwei verschiedene Sessions sind? Bei jedem Seitenaufruf innerhalb des Logins die aktuelle IP mit der in der Session vergleichen.

Wenn ungleich dann logout und account sperren?

Achso und nochmal was zu den Cookies:
Ich habe bei einer Seite von mir mal Cookies ausgeschaltet. Ein Login ging dann nicht mehr. Ich habe die Tage gelesen, dass dann an die URL die SID angehängt wird.

Das scheint nicht automatisch zu geschehen bzw. eventuell auf meinem Server ausgeschaltet zu sein. Was muss ich denn dann verändern, damit das ohne Cookies läuft? Muss ich nun die SSID mit in die Session übergeben?

Mir ist gerade noch etwas eingefallen:
Ich würde bei der Registrierung eines Users einen Salt in die User Datenbank schreiben, zufällig 20 Zeichen aus Buchstaben, Zahlen, Sonderzeichen. Diesen Salt würde ich dann beim hashen Mitnutzen und eventuell Später bei sensiblen Daten als Passwort zum ver- bzw. entschlüsseln über mcrypt nutzen. Meint Ihr das ist sicher? Kann ich sowas direkt per SQL erzeugen? Ich würde die Spalte sonst noch auf Unique setzen. Aber was passiert denn wenn es dieses Zeichen schon mal gibt? Kriege ich dann eine Fehlermeldung?
 
Zuletzt bearbeitet:
Kann mir einer noch erklären was da der Unterschied zur normalen Speicherung in den Sessions ist? In beiden Fällen werden doch die Daten gespeichert und können wieder abgerufen werden? Wo ist also der Vorteil da nun eine uuid zu vergeben? Ist die uuid dann pro Formularseite zu vergeben oder pro Formular?
Du hast eine UUID pro "Workflow". Dieser kann sich ja über mehrere Seiten / Formulare erstecken. Somit kann der Benutzer auch mit 2 Tabs zwei verschiedene Durchläufe machen, ohne dass sich die Daten vermischen.

Zurück zum regenerate_id: Ich rufe das also einfach immer auf beim Login? Weil dann würde im Fall das einer nicht eingeloggt ist eine SessionID vergeben werden und im Falle er ist schon drin wird diese einfach refreshed?
Genau, nach jedem erfolgreichen Login. Somit kann die SessionID nicht vom Benutzer kontrolliert werden, bzw. die Daten werden in die richtige Session geschrieben.

Wie prüfe ich denn ob es zwei verschiedene Sessions sind? Bei jedem Seitenaufruf innerhalb des Logins die aktuelle IP mit der in der Session vergleichen.
Wenn ungleich dann logout und account sperren?
Wenn ein angemeldeter Benutzer eine SessionID präsentiert, welche durch einen Login durch IP a.b.c.d erstellt wurde, dann kann er nicht plötzlich von der IP w.x.y.z kommen. Das bedeutet im Regelfall, dass die SessionID geklaut wurde. In dem Falle einfach die präsentierte SessionID löschen (session_destroy() oder noch besser: Eine spezielle Fehlermeldung drin speichern und diese dem legitimen Benutzer zeigen. Gleichzeitig natürlich dafür sorgen, dass dieser nicht mehr eingeloggt ist)
Hierbei aber nicht die komplette IP speichern (Datenschutz) und vergleichen, sondern nur die ersten 2 oder 3 Blöcke. Idealerweise sollte die Einstellung vom Benutzer festgelegt und auch komplett abschaltbar sein.

Achso und nochmal was zu den Cookies:
Ich habe bei einer Seite von mir mal Cookies ausgeschaltet. Ein Login ging dann nicht mehr. Ich habe die Tage gelesen, dass dann an die URL die SID angehängt wird.
Ja, das ist auch richtig so. Dass die SessionID an die URL angehängt wird, gab es meines Wissens nach mal. Da das aber nicht immer funktioniert hat wurde die Funktion wieder entfernt, bzw. per Standard abgeschaltet. Würde ich auch so belassen, denn dadurch funktionieren dann Lesezeichen nicht mehr korrekt und der Benutzer hat einfacher Kontrolle über die ID.

ch würde bei der Registrierung eines Users einen Salt in die User Datenbank schreiben, zufällig 20 Zeichen aus Buchstaben, Zahlen, Sonderzeichen. Diesen Salt würde ich dann beim hashen Mitnutzen und eventuell Später bei sensiblen Daten als Passwort zum ver- bzw. entschlüsseln über mcrypt nutzen. Meint Ihr das ist sicher?
Zum Salt: Sehr gut, jeder Benutzer sollte seinen eigenen haben, das ist wichtig. Gleichzeitig muss dieser nicht allzu geheim sein, in der Datenbank neben dem Passwort zu speichern ist OK. 20 Zeichen sind auch mehr als ausreichend, ob da jetzt aber unbedingt auch Sonderzeichen dabei sein müssen, darüber lässt sich streiten. Selbst wenn der Benutzer nur "a" als Passwort eingibt, so ist der Hash über effektiv 21 Zeichen erstellt. Und diese sind an sich schon quasi nicht zu knacken.
Wenn du den aber auch als Passwort zum ver- und entschlüsseln verwenden willst, dann wirds etwas tricky. Dann sollte dieser nicht so einfach in der Datenbank am Benutzer hängen sondern extra geschützt wo anders. Ausserdem sollte sich der Salt normalerweise bei jeder Passwortänderung auch ändern. Wenn du hiermit dann irgenwas verschlüsselt hast, dann kommst du da nicht mehr dran.
Extra Tabelle für die Verschlüsselungs-Schlüssel, mit extra Benutzer und Passwort. Am besten auch von einem extra Service aus anzusprechen, nicht von deiner Hauptanwendung aus drauf gehen. Der Extraservice bietet eine definierte Schnittstelle an und gibt die Schlüssel niemals raus. Zum Beispiel nur per REST ansprechbar, "verschlüssele Datei X für den Benutzer Y" oder "entschlüssele Datei Z für Benutzer X und liefere Daten".

Kann ich sowas direkt per SQL erzeugen? Ich würde die Spalte sonst noch auf Unique setzen. Aber was passiert denn wenn es dieses Zeichen schon mal gibt? Kriege ich dann eine Fehlermeldung?
Natürlich kannst du den Salt auch per SQL erzeugen lassen, dieser muss nicht kryptografisch sicher sein. Unique würde ich nicht nehmen, sollte ja quasi nie den selben Salt für zwei Benutzer erzeugen.
Wenn die Spalte auf Unique ist, dann gibt es einen Fehler, ja.
Würde mir in dem Zusammenhang übrigens auch noch Transaktionen in der Datenbank anschauen, diese helfen dir deine Daten konsistent und sauber zu halten. Vorallem wenn mal irgendwie was abbricht hast nicht nur die Hälfte der Änderungen drin.

Grüsse,
BK
 

Neue Beiträge

Zurück