Ok, es gibt zwei separate, aber verwandte Probleme, und jedes wird anders behandelt.
Sitzungsfixierung
Hier legt ein Angreifer explizit die Sitzungskennung einer Sitzung für einen Benutzer fest. Normalerweise geschieht dies in PHP, indem man ihnen eine URL wie gibt http://www.example.com/index...?session_name=sessionid
. Sobald der Angreifer dem Client die URL gibt, entspricht der Angriff einem Sitzungsentführungsangriff.
Es gibt einige Möglichkeiten, um die Sitzungsfixierung zu verhindern (alle ausführen):
In session.use_trans_sid = 0
Ihrer php.ini
Datei einstellen. Dadurch wird PHP angewiesen, den Bezeichner nicht in die URL aufzunehmen und die URL für Bezeichner nicht zu lesen.
In session.use_only_cookies = 1
Ihrer php.ini
Datei einstellen. Dadurch wird PHP angewiesen, niemals URLs mit Sitzungskennungen zu verwenden.
Generieren Sie die Sitzungs-ID immer dann neu, wenn sich der Status der Sitzung ändert. Das bedeutet Folgendes:
- Benutzerauthentifizierung
- Speichern vertraulicher Informationen in der Sitzung
- Ändern Sie etwas an der Sitzung
- etc...
Sitzungsentführung
Hier erhält ein Angreifer eine Sitzungskennung und kann Anforderungen senden, als ob er dieser Benutzer wäre. Das bedeutet, dass der Angreifer, da er die Kennung hat, vom gültigen Benutzer in Bezug auf den Server so gut wie nicht zu unterscheiden ist.
Sie können die Entführung von Sitzungen nicht direkt verhindern. Sie können jedoch Schritte einleiten, um die Verwendung sehr schwierig und schwieriger zu machen.
Verwenden Sie eine starke Sitzungs-Hash-ID: session.hash_function
in php.ini
. Wenn PHP <5.3 ist, setzen Sie es session.hash_function = 1
für SHA1. Wenn PHP> = 5.3, setzen Sie es auf session.hash_function = sha256
oder session.hash_function = sha512
.
Senden Sie einen starken Hash: session.hash_bits_per_character
in php.ini
. Stellen Sie dies auf ein session.hash_bits_per_character = 5
. Dies macht das Knacken zwar nicht schwieriger , macht jedoch einen Unterschied, wenn der Angreifer versucht, die Sitzungskennung zu erraten. Die ID ist kürzer, verwendet jedoch mehr Zeichen.
Legen Sie eine zusätzliche Entropie mit session.entropy_file
und session.entropy_length
in Ihrer php.ini
Datei fest. Stellen Sie erstere auf session.entropy_file = /dev/urandom
und letztere auf die Anzahl der Bytes ein, die beispielsweise aus der Entropiedatei gelesen werden session.entropy_length = 256
.
Ändern Sie den Namen der Sitzung von der Standard-PHPSESSID. Dies wird erreicht, indem Sie vor dem Aufruf session_name()
mit Ihrem eigenen Bezeichnernamen als erstem Parameter aufrufen session_start
.
Wenn Sie wirklich paranoid sind, können Sie auch den Sitzungsnamen drehen. Beachten Sie jedoch, dass alle Sitzungen automatisch ungültig werden, wenn Sie dies ändern (z. B. wenn Sie ihn von der Zeit abhängig machen). Abhängig von Ihrem Anwendungsfall kann dies jedoch eine Option sein ...
Drehen Sie Ihre Sitzungskennung häufig. Ich würde dies nicht bei jeder Anfrage tun (es sei denn, Sie benötigen wirklich diese Sicherheitsstufe), sondern in zufälligen Abständen. Sie möchten dies häufig ändern, da ein Angreifer, der eine Sitzung entführt, nicht möchte, dass er sie zu lange verwenden kann.
Schließen Sie den Benutzeragenten von$_SERVER['HTTP_USER_AGENT']
in die Sitzung ein. Wenn die Sitzung beginnt, speichern Sie sie grundsätzlich in so etwas wie $_SESSION['user_agent']
. Überprüfen Sie dann bei jeder nachfolgenden Anforderung, ob sie übereinstimmt. Beachten Sie, dass dies gefälscht werden kann, so dass es nicht 100% zuverlässig ist, aber es ist besser als nicht.
Fügen Sie die IP-Adresse$_SERVER['REMOTE_ADDR']
des Benutzers von in die Sitzung ein. Wenn die Sitzung beginnt, speichern Sie sie grundsätzlich in so etwas wie $_SESSION['remote_ip']
. Dies kann bei einigen ISPs problematisch sein, die mehrere IP-Adressen für ihre Benutzer verwenden (wie dies früher bei AOL der Fall war). Aber wenn Sie es verwenden, wird es viel sicherer sein. Die einzige Möglichkeit für einen Angreifer, die IP-Adresse zu fälschen, besteht darin, das Netzwerk irgendwann zwischen dem tatsächlichen Benutzer und Ihnen zu gefährden. Und wenn sie das Netzwerk gefährden, können sie weitaus schlechter abschneiden als eine Entführung (wie MITM-Angriffe usw.).
Fügen Sie der Sitzung und auf der Browserseite ein Token hinzu, das Sie häufig erhöhen und vergleichen. Grundsätzlich für jede Anfrage $_SESSION['counter']++
auf der Serverseite tun . Machen Sie auch etwas in JS auf der Browserseite, um dasselbe zu tun (unter Verwendung eines lokalen Speichers). Wenn Sie dann eine Anfrage senden, nehmen Sie einfach eine Nonce eines Tokens und stellen Sie sicher, dass die Nonce auf dem Server identisch ist. Auf diese Weise sollten Sie in der Lage sein, eine entführte Sitzung zu erkennen, da der Angreifer nicht über den genauen Zähler verfügt. Andernfalls haben Sie zwei Systeme, die die gleiche Anzahl übertragen, und können feststellen, dass eines gefälscht ist. Dies funktioniert nicht für alle Anwendungen, ist jedoch eine Möglichkeit, das Problem zu bekämpfen.
Ein Hinweis zu den beiden
Der Unterschied zwischen Sitzungsfixierung und Hijacking besteht nur darin, wie die Sitzungskennung kompromittiert wird. Bei der Fixierung wird der Bezeichner auf einen Wert gesetzt, den der Angreifer vorher kennt. Beim Hijacking wird es entweder erraten oder dem Benutzer gestohlen. Ansonsten sind die Auswirkungen der beiden gleich, sobald die Kennung kompromittiert wird.
Regeneration der Sitzungs-ID
Immer wenn Sie die Sitzungskennung mit session_regenerate_id
der alten Sitzung neu generieren, sollte diese gelöscht werden. Dies geschieht transparent mit dem Core Session Handler. Einige benutzerdefinierte Sitzungshandler, diesession_set_save_handler()
dies verwenden, tun dies jedoch nicht und sind offen für Angriffe auf alte Sitzungskennungen. Stellen Sie sicher, dass Sie bei Verwendung eines benutzerdefinierten Sitzungshandlers den von Ihnen geöffneten Bezeichner nachverfolgen und den Bezeichner des alten explizit löschen (oder ändern), wenn er nicht derselbe ist, den Sie speichern.
Wenn Sie den Standard-Sitzungshandler verwenden, können Sie nur anrufen session_regenerate_id(true)
. Dadurch werden die alten Sitzungsinformationen für Sie entfernt. Die alte ID ist nicht mehr gültig und führt dazu, dass eine neue Sitzung erstellt wird, wenn der Angreifer (oder sonst jemand) versucht, sie zu verwenden. Seien Sie jedoch vorsichtig mit benutzerdefinierten Sitzungshandlern ....
Eine Sitzung zerstören
Wenn Sie eine Sitzung zerstören möchten (z. B. beim Abmelden), stellen Sie sicher, dass Sie sie gründlich zerstören. Dies beinhaltet das Deaktivieren des Cookies. Verwenden von session_destroy
:
function destroySession() {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
session_destroy();
}