Wie eindeutig ist die PHP-Sitzungs-ID

90

Wie eindeutig ist die PHP-Sitzungs-ID? Ich hatte den Eindruck, dass ich mich nicht darauf verlassen sollte, dass zwei Benutzer nie dieselbe Sitzungs-ID erhalten. Ist es nicht eine GUID?

Jalov
quelle

Antworten:

39

Session_id kann zwar dupliziert werden, aber die Wahrscheinlichkeit ist sehr gering. Wenn Sie eine Website mit einem fairen Datenverkehr haben, kann dies einmal in Ihrem Website-Leben vorkommen und nur einen Benutzer für eine Sitzung ärgern.

Es lohnt sich nicht, sich darum zu kümmern, es sei denn, Sie erwarten, dass Sie eine Website mit sehr hohem Datenaufkommen oder einen Service für die Bankbranche erstellen.

e-satis
quelle
4
Ich habe Berichte von Websites gehört, bei denen es häufig zu Kollisionen gekommen ist.
ColinM
20
Die Frage wurde vor fast 4 Jahren gestellt. Es wäre interessant zu wissen, ob der Session-ID-Algorithmus seitdem improvisiert hat ...
Sliq
@ColinM: und diese Websites hatten 1 Million eindeutige Besucher / Tag.
E-Satis
1
Anscheinend basiert es derzeit (MD5 / SHA1-Hash) auf der Remote-Adresse des Benutzers, der Ortszeit und einer Zufallszahl (LCG) .
Caramiriel
2
Ich muss nicht mobil brechen, mobil bricht ständig selbst. :)
hakre
67

Es ist nicht sehr einzigartig wie ausgeliefert. In der Standardkonfiguration ist dies das Ergebnis eines Hash verschiedener Dinge, einschließlich des Ergebnisses von gettimeofday (was nicht besonders eindeutig ist). Wenn Sie sich jedoch Sorgen machen, sollten Sie es so konfigurieren, dass eine Entropie aus / dev / urandom gezogen wird

ini_set("session.entropy_file", "/dev/urandom");
ini_set("session.entropy_length", "512");

Suchen Sie im Code nach "php_session_create_id" für den tatsächlich verwendeten Algorithmus.

Bearbeitet, um hinzuzufügen: Es gibt einen DFA-Zufallszahlengenerator, der von der PID ausgesät wird und mit der Zeit in usecs gemischt wird. Es ist keine feste Eindeutigkeitsbedingung, insbesondere aus Sicherheitsgründen . Verwenden Sie die obige Entropiekonfiguration.

Aktualisieren:

Ab PHP 5.4.0 ist session.entropy_file standardmäßig / dev / urandom oder / dev / arandom, falls verfügbar. In PHP 5.3.0 bleibt diese Anweisung standardmäßig leer. PHP-Handbuch

djsadinoff
quelle
1
Ja, als ich einen Vertrag für eine Website abgeschlossen hatte, die gegen feindliche Kombattanten und dergleichen ultrasicher sein musste, habe ich tatsächlich meinen eigenen Sitzungshandler erstellt und ihm Entropiedaten direkt von random.org zugeführt. Aber die Anforderungen dieses Systems gingen weit über das hinaus, was die meisten Sterblichen mit w- ;-)
Theodore R. Smith
1
@ thomas-jensen, gettimeofday ist der Unix-Zeitstempel, außer er wird (manchmal) in μsec ausgedrückt. Lesen Sie die oben verlinkte Methode php_session_create_id.
DJsadinoff
4
Das Ändern der Entropielänge verbessert die Zufälligkeit, beeinflusst jedoch die Wahrscheinlichkeit einer Kollision nicht wesentlich, da der Hash immer noch dieselbe Länge hat. Wenn Sie jedoch session.hash_function ändern, können Sie längere Hashes wie z. B. sha512 verwenden.
ColinM
2
Ich finde es bizarr, dass es Kollisionen gibt. Sicherlich sollte PHP gemacht werden, um zu überprüfen, ob es eine gültige Sitzung unter dieser ID gibt, und anschließend eine andere ID zu generieren.
Luke
1
@ theodore-r-smith, es ist wirklich eine schlechte Praxis, Entropie aus einer öffentlich zugänglichen Quelle zu entnehmen. Sie sollten davon ausgehen, dass Ihre "feindlichen Kämpfer" auch Zugriff auf random.org haben ...
avri
12

Wenn Sie wissen möchten, wie PHP standardmäßig eine Sitzungs-ID generiert, lesen Sie den Quellcode auf Github . Es ist sicherlich nicht zufällig und basiert auf einem Hash (Standard: md5) dieser Zutaten (siehe Zeile 310 des Code-Snippets):

  1. IP-Adresse des Clients
  2. Aktuelle Uhrzeit
  3. PHP Linear Congruence Generator - ein Pseudozufallszahlengenerator (PRNG)
  4. Betriebssystemspezifische Zufallsquelle - wenn für das Betriebssystem eine Zufallsquelle verfügbar ist (z. B. / dev / urandom)

Wenn dem Betriebssystem eine zufällige Quelle zur Verfügung steht, ist die Stärke der generierten ID zum Zweck der Sitzungs-ID hoch ( / dev / urandom und andere zufällige Quellen des Betriebssystems sind (normalerweise) kryptografisch sichere PRNGs ). Wenn dies jedoch nicht der Fall ist, ist es zufriedenstellend.

Das Ziel bei der Generierung der Sitzungsidentifikation ist:

  1. Minimieren Sie die Wahrscheinlichkeit, zwei Sitzungs-IDs mit demselben Wert zu generieren
  2. Machen Sie es rechnerisch sehr schwierig, zufällige Schlüssel zu generieren und einen in Gebrauch befindlichen zu treffen .

Dies wird durch den PHP-Ansatz zur Sitzungsgenerierung erreicht.

Sie können die Eindeutigkeit nicht absolut garantieren , aber die Wahrscheinlichkeiten, denselben Hash zweimal zu treffen, sind so gering, dass es sich im Allgemeinen nicht lohnt, sich Sorgen zu machen.

GordyD
quelle
11

Sie können eine alternative Hash-Generierungsfunktion installieren, wenn Sie die Art und Weise anpassen möchten, in der die ID generiert wird (dies ist eine 128-Bit-Nummer, die standardmäßig über MD5 generiert wird). Siehe http://www.php.net/manual/en/session.configuration.php#ini.session.hash-function

Weitere Informationen zu PHP-Sitzungen finden Sie in diesem hervorragenden Artikel unter http://shiflett.org/articles/the-truth-about-sessions, der auch auf andere Artikel zu Sitzungsfixierung und -entführung verweist.

Paul Dixon
quelle
2
Um genau zu sein, setzen Sie "session.hash_function = sha512" für PHP 5.3 und höher, um zu 512-Bit-Hash zu gelangen. Dies sollte den Trick tun. Mit den Standardeinstellungen kommt es häufig auf stark frequentierten Websites zu Kollisionen.
ColinM
5

Größe von session_id
Angenommen, seeion_id ist gleichmäßig verteilt und hat eine Größe von 128 Bit. Angenommen, jede Person auf dem Planeten meldet sich einmal am Tag mit einer dauerhaften neuen Sitzung für 1000 Jahre an.

num_sesion_ids  = 1000*365.25 *7*10**9 < 2**36
collission_prob < 1 - (1-1/2**82)**(2**36)   1 - e**-(1/2**46) 
                 1/2**46 

Die Wahrscheinlichkeit einer oder mehrerer Kollisionen liegt also unter einer von 70.000 Milliarden. Daher sollte die 128-Bit-Größe der session_id groß genug sein. Wie in anderen Kommentaren erwähnt, überprüft der session_manager möglicherweise auch, ob die neue session_id noch nicht vorhanden ist.

Zufälligkeit
Daher ist die große Frage, die ich denke, ob die session_id: s mit guter Pseudozufälligkeit generiert werden. In diesem Punkt können Sie sich nie sicher sein, aber ich würde empfehlen, eine bekannte und häufig verwendete Standardlösung für diesen Zweck zu verwenden (wie Sie es wahrscheinlich bereits tun).

Selbst wenn Kollisionen aufgrund von Überprüfungen vermieden werden, ist die Zufälligkeit und Größe von session_id wichtig, damit Hacker nicht mit großer Wahrscheinlichkeit qualifiziert raten und aktive session_id: s finden können.

MrJ
quelle
3
Ich bin kein Mathematiker, aber ich denke, Sie vergessen das Geburtstagsproblem, sodass die Wahrscheinlichkeit einer Kollision, obwohl sie noch klein ist, viel größer ist, als Sie vermuten. Wie von djsadinoff vorgeschlagen, verwenden PHPs nicht unbedingt standardmäßig eine gute Methode zum Generieren von Zufallszahlen.
ColinM
Nein, eigentlich gilt die Schätzung. Die obige Berechnung ist eine vereinfachte Schätzung, bei der wir schätzen, dass die Wahrscheinlichkeit für eine Kollision für session_id nr i = 1/2 82 ist (sie sollte jedoch 1/2 92 über = Tippfehler liegen). In Wirklichkeit ist die Wahrscheinlichkeit (i-1) / 2 128, solange keine vorherigen Kollisionen aufgetreten sind. 1/2 92 gilt nur für die letzte session_id.
MrJ
3

Ich habe keine Bestätigung dazu gefunden, aber ich glaube, PHP prüft, ob bereits eine Sitzungs-ID vorhanden ist, bevor eine mit dieser ID erstellt wird.

Das Problem der Sitzungsentführung ist, wenn jemand die Sitzungs-ID eines aktiven Benutzers herausfindet. Dies kann auf viele Arten verhindert werden. Weitere Informationen dazu finden Sie auf dieser Seite auf php.net und in diesem Dokument zur Sitzungsfixierung

Ólafur Waage
quelle
2
... aber wenn Sie nur ein PHP-Server in einer Bank von mehreren sind, gibt es keine Garantie dafür, dass der Server über ausreichende Kenntnisse verfügt, um zu wissen, ob die sesssionID bereits verwendet wurde.
Djsadinoff
Warum sollte es wichtig sein, wenn ich dieselbe Sitzungs-ID auf 2 verschiedenen PHP-Servern habe? Unter der Annahme von 2 verschiedenen Domänen ist das Sitzungscookie nur von jeder Domäne aus zugänglich ...?
Daremon
3
Der einfachste Weg, um Dupes in einer Umgebung mit mehreren Servern zu verhindern, besteht darin, die Sitzungen in memcached über den memcached session handler zu speichern. Problem gelöst und Ihre Benutzer können auf verschiedenen Servern herumspringen, ohne ihre Sachen zu verlieren.
Theodore R. Smith
@daremon er spricht über mehrere Server für eine Domain.
GTD
Das ist einfach falsch. PHP sucht beim Generieren neuer IDs nicht nach vorhandenen Sitzungs-IDs. Schauen Sie sich einen PHP-Session-Handler-Code an und es ist einfach keine Methode für diesen Zweck implementiert.
ColinM
2

Nein, die Sitzungs-ID ist keine GUID, aber zwei Benutzer sollten nicht dieselbe Sitzungs-ID erhalten, wie sie auf der Serverseite gespeichert sind.

Gizmo
quelle
2
Möglicherweise, weil der serverseitige Speicher in keiner Weise die Eindeutigkeit garantiert. Eindeutigkeit ist eine Sache - wenn es zu einer Kollision kommt, kollidiert diese unabhängig davon, wo die Sitzung gespeichert ist.
Nicht von mir, ich schätze Ihre Antwort (wie auch die anderen). - Jalov
Jalov
2
Die Sitzungs-ID wird sowohl auf der Server- als auch auf der Clientseite gespeichert. Der Sitzungsinhalt wird auf der Serverseite gespeichert. Und die Tatsache hängt so ziemlich nicht mit der Eindeutigkeit der Sitzungs-ID zusammen.
YudhiWidyatama
-3
<?php
session_start();
$_SESSION['username']="username";
?>

<!DOCTYPE html>
<html>
<head>
    <title>Update</title>
</head>
<body>

<table border="2">
    <tr>
        <th>Username</th>
        <th>Email</th>
        <th>Edit</th>
    </tr>
<?php
     $conn=mysqli_connect("localhost","root","","telephasic");
     $q2="select * from register where username = '".$_SESSION['username']."'";
     $run=mysqli_query($conn, $q2);
     while($row=mysqli_fetch_array($run))
     {
         $name=$row[1];
         $email=$row[2];
     ?>

    <tr>
        <td><?php echo $name; ?></td>
        <td><?php echo $email; ?></td>
        <td><a href="edit.php"> Edit </a></td>
    </tr>
 <?php } ?>
 </table> 
 </body>

Wenn Ihr Benutzername anders oder eindeutig ist, können Sie diesen Code für die Sitzung verwenden

Arun Sharma
quelle