Fixierung / Hijacking von PHP-Sitzungen

145

Ich versuche mehr über PHP Session Fixation & Hijacking zu verstehen und wie man diese Probleme verhindert. Ich habe die folgenden zwei Artikel auf der Website von Chris Shiflett gelesen:

Ich bin mir jedoch nicht sicher, ob ich die Dinge richtig verstehe.

Um eine Sitzungsfixierung zu verhindern, reicht es aus, session_regenerate_id (true) aufzurufen. nach erfolgreicher Anmeldung? Ich denke, ich verstehe das richtig.

Er spricht auch über die Verwendung von Token, die in URLs über $ _GET weitergegeben werden, um Sitzungsentführungen zu verhindern. Wie würde das genau gemacht werden? Ich vermute, wenn sich jemand anmeldet, generieren Sie sein Token und speichern es in einer Sitzungsvariablen. Dann würden Sie auf jeder Seite diese Sitzungsvariable mit dem Wert der Variablen $ _GET vergleichen?

Müsste dieses Token nur einmal pro Sitzung oder bei jedem Laden der Seite geändert werden?

Ist dies auch eine gute Möglichkeit, Entführungen zu verhindern, ohne einen Wert in den URLs weitergeben zu müssen? das wäre viel einfacher.

me2
quelle
Vielleicht können Sie Links zu den Seiten hinzufügen, auf denen Sie diese Empfehlungen gefunden haben.
Gumbo

Antworten:

219

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 = 0Ihrer php.iniDatei 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 = 1Ihrer php.iniDatei 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_functionin php.ini. Wenn PHP <5.3 ist, setzen Sie es session.hash_function = 1für SHA1. Wenn PHP> = 5.3, setzen Sie es auf session.hash_function = sha256oder session.hash_function = sha512.

  • Senden Sie einen starken Hash: session.hash_bits_per_characterin 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_fileund session.entropy_lengthin Ihrer php.iniDatei fest. Stellen Sie erstere auf session.entropy_file = /dev/urandomund 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_idder 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();
}
ircmaxell
quelle
4
Die Verwendung von 5 anstelle von 4 Bits pro Zeichen ändert in keiner Weise die „Stärke“ (was auch immer „Stärke“ in diesem Fall bedeutet). Obwohl Ihre Punkte im Allgemeinen ratsam sind, fehlen ihnen einige wichtige Details. Zum Beispiel, was mit der Sitzung passiert, die der alten Sitzungs-ID zugeordnet ist, oder wie eine Sitzung mit einer alten Sitzungs-ID behandelt werden soll, nachdem sie ungültig geworden ist.
Gumbo
2
@battal: Nein, das ist der Punkt. session_regenerate_idmacht die Sitzung, die noch der alten ID zugeordnet ist, nicht ungültig; Nur wenn der Parameter delete_old_session auf true gesetzt ist, wird die Sitzung zerstört. Was aber, wenn ein Angreifer diese ID-Regeneration initiiert hat?
Gumbo
6
Ich bin mit der Sitzungsregeneration nicht einverstanden, wenn Sie eine Sitzungsvariable jedes Mal ändern. Dies sollte nur beim Anmelden / Abmelden erfolgen. Auch das Überprüfen des Benutzeragenten ist bedeutungslos und das Überprüfen von REMOTE_ADDR ist problematisch. Eine Sache, die ich hinzufügen möchte, ist session.entropy_file = /dev/urandom. Die interne Entropieerzeugung von PHP ist nachweislich extrem schwach und der Entropiepool von / dev / random oder / dev / uranom ist der beste, den Sie auf einem Webserver ohne Hardware-Rng erhalten können.
Turm
4
Auch sollten Sie hinzufügen session.cookie_httponlyund session.cookie_secure. Der erste hilft, xss zu vereiteln (aber es ist nicht perfekt). Der 2. ist der beste Weg, um OWASP A9 zu stoppen ...
Turm
4
Verstehe eine so gute Antwort nicht, aber es fehlt das wichtigste: Verwenden Sie SSL / HTTPS. Das Zählerinkrement ist eine Problemquelle, bei der mehrere Anforderungen schnell nacheinander ausgeführt werden. Ein Benutzer aktualisiert eine Seite zweimal oder drückt zweimal auf eine Senden-Schaltfläche. Die IP-Adresslösung ist heutzutage ein Problem für alle mobilen Benutzer und ständig wechselnde IPs. Sie könnten sich den ersten Satz der IP ansehen, aber es ist immer noch problematisch. Am besten verhindern Sie, dass die Sitzungs-ID zuerst erkannt wird und dass SSL / HTTPS verwendet wird.
Sanne
37

Beide Sitzungsangriffe haben dasselbe Ziel: Zugriff auf eine legitime Sitzung eines anderen Benutzers. Die Angriffsvektoren sind jedoch unterschiedlich:

  • In einem Session - Fixation - Angriff , der Angreifer hat bereits Zugriff auf eine gültige Sitzung und versucht , das Opfer zu zwingen , diese bestimmte Sitzung zu verwenden.

  • Bei einem Session Hijacking- Angriff versucht der Angreifer, die ID der Sitzung eines Opfers abzurufen, um seine Sitzung zu verwenden.

Bei beiden Angriffen ist die Sitzungs-ID die vertrauliche Daten, auf die sich dieser Angriff konzentriert. Es ist also die Sitzungs-ID, die sowohl für einen Lesezugriff (Session Hijacking) als auch für einen Schreibzugriff (Session Fixation) geschützt werden muss.

Auch in diesem Fall gilt die allgemeine Regel zum Schutz sensibler Daten mit HTTPS. Darüber hinaus sollten Sie Folgendes tun:

Stellen Sie Folgendes sicher, um Angriffe zur Sitzungsfixierung zu verhindern :

Stellen Sie Folgendes sicher, um Angriffe auf Sitzungsentführungen zu verhindern :

Stellen Sie Folgendes sicher, um beide Sitzungsangriffe zu verhindern :

  • um nur Sitzungen zu akzeptieren, die Ihre Anwendung initiiert hat. Sie können dies tun, indem Sie bei der Initiierung eine Sitzung mit Client-spezifischen Informationen abzeichnen. Sie können die User-Agent- ID verwenden, jedoch nicht die Remote-IP-Adresse oder andere Informationen, die sich zwischen den Anforderungen ändern können.
  • Ändern der Sitzungs-ID session_regenerate_id(true)nach einem Authentifizierungsversuch ( truenur bei Erfolg) oder einer Änderung der Berechtigungen und Zerstören der alten Sitzung. (Stellen Sie sicher, dass Sie alle Änderungen der $_SESSIONVerwendung speichern , session_write_close bevor Sie die ID neu generieren, wenn Sie die der alten ID zugeordnete Sitzung beibehalten möchten. Andernfalls ist nur die Sitzung mit der neuen ID von diesen Änderungen betroffen.)
  • So verwenden Sie eine ordnungsgemäße Implementierung für den Sitzungsablauf (siehe Wie läuft eine PHP-Sitzung nach 30 Minuten ab? ).
Gumbo
quelle
Toller Beitrag, besonders der letzte Abschnitt.
Mattis
6

Die Token, die Sie erwähnen, sind eine "Nonce" -Nummer, die einmal verwendet wird. Sie müssen nicht unbedingt nur einmal verwendet werden, aber je länger sie verwendet werden, desto höher ist die Wahrscheinlichkeit, dass das Nonce erfasst und zur Entführung der Sitzung verwendet werden kann.

Ein weiterer Nachteil von Nonces ist, dass es sehr schwierig ist, ein System zu erstellen, das sie verwendet und mehrere parallele Fenster in derselben Form zulässt. Beispiel: Der Benutzer öffnet zwei Fenster in einem Forum und beginnt mit der Arbeit an zwei Posts:

window 'A' loads first and gets nonce 'P'
window 'B' loads second and gets nonce 'Q'

Wenn Sie nicht in der Lage sind, mehrere Fenster zu verfolgen, haben Sie nur eine Nonce gespeichert - die von Fenster B / Q. Wenn der Benutzer dann seinen Beitrag aus Fenster A einreicht und nonce 'P' übergibt, lehnt dieses System den Beitrag als ab P != Q.

Marc B.
quelle
Was hat das mit der Sitzungsfixierung zu tun?
Turm
2
Er hat einen gültigen Punkt, insbesondere im Bereich der gleichzeitigen Verwendung vieler AJAX-Anforderungen.
DanielG
2

Ich habe Shifletts Artikel nicht gelesen, aber ich denke, Sie haben etwas falsch verstanden.

Standardmäßig übergibt PHP das Sitzungstoken in der URL, wenn der Client keine Cookies akzeptiert. Andernfalls wird das Sitzungstoken im häufigsten Fall als Cookie gespeichert.

Dies bedeutet, dass wenn Sie ein Sitzungstoken in die URL einfügen, PHP es erkennt und versucht, es anschließend zu verwenden. Die Sitzungsfixierung erfolgt, wenn jemand eine Sitzung erstellt und dann einen anderen Benutzer dazu verleitet, dieselbe Sitzung freizugeben, indem eine URL geöffnet wird, die das Sitzungstoken enthält. Wenn sich der Benutzer auf irgendeine Weise authentifiziert, kennt der böswillige Benutzer das Sitzungstoken eines authentifizierten Benutzers, der möglicherweise über andere Berechtigungen verfügt.

Wie Shiflett sicher erklärt, besteht die übliche Vorgehensweise darin, jedes Mal, wenn sich die Berechtigungen eines Benutzers ändern, ein anderes Token neu zu generieren.

Andrea
quelle
Um dies hinzuzufügen, müssen Sie alle zuvor geöffneten Sitzungen zerstören, da diese mit den vorhandenen Benutzerberechtigungen weiterhin gültig sind.
corrodedmonkee
0

Ja, Sie können die Sitzungsfixierung verhindern, indem Sie die Sitzungs-ID bei der Anmeldung einmal neu generieren. Auf diese Weise, wenn der Angreifer den Cookie-Wert der neu authentifizierten Sitzung nicht kennt. Ein anderer Ansatz, der das Problem vollständig stoppt, ist session.use_only_cookies=Truein Ihrer Laufzeitkonfiguration festgelegt. Ein Angreifer kann den Wert eines Cookies nicht im Kontext einer anderen Domäne festlegen. Die Sitzungsfixierung basiert auf dem Senden des Cookie-Werts als GET oder POST.

Turm
quelle