À quel point l'identifiant de session PHP est-il unique

90

Dans quelle mesure l'identifiant de session php est-il unique? J'ai eu l'impression d'après diverses choses que j'ai lues que je ne devrais pas compter sur deux utilisateurs qui n'obtiennent jamais le même identifiant de session. N'est-ce pas un GUID?

Jalov
la source

Réponses:

39

Session_id peut en effet être dupliqué, mais la probabilité est très faible. Si vous avez un site Web avec un trafic équitable, cela peut arriver une fois dans la vie de votre site Web et ne fera qu'ennuyer un utilisateur pendant une session.

Cela ne vaut pas la peine de s'en soucier, sauf si vous prévoyez de créer un site Web à très fort trafic ou un service pour le secteur bancaire.

e-satis
la source
4
J'ai entendu des rapports de sites qui ont eu de nombreux cas de collisions.
ColinM
20
La question a été posée il y a près de 4 ans. Il serait intéressant de savoir si l'algorithme d'identifiant de session s'est improvisé depuis ...
Sliq
@ColinM: et ces sites comptaient 1 million de visiteurs uniques / jour.
e-satis
1
Aparantly, il est actuellement basé (hachage MD5 / SHA1) sur l'adresse distante de l'utilisateur, l'heure locale et un certain nombre aléatoire (LCG) .
Caramiriel
2
Je n'ai pas besoin de casser le mobile, le mobile se brise constamment. :)
hakre
67

Ce n'est pas très unique tel qu'il est expédié. Dans la configuration par défaut, c'est le résultat d'un hachage de diverses choses, y compris le résultat de gettimeofday (qui n'est pas terriblement unique), mais si vous êtes inquiet, vous devez le configurer pour tirer une certaine entropie de / dev / urandom, comme ceci

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

recherchez "php_session_create_id" dans le code de l'algorithme qu'ils utilisent.

Modifié pour ajouter: il existe un générateur de nombres aléatoires DFA prédéfini par le pid, mélangé avec le temps en usecs. Ce n'est pas une condition d'unicité ferme, en particulier du point de vue de la sécurité . Utilisez la configuration d'entropie ci-dessus.

Mettre à jour:

Depuis PHP 5.4.0, session.entropy_file prend par défaut / dev / urandom ou / dev / arandom s'il est disponible. En PHP 5.3.0, cette directive est laissée vide par défaut. Manuel PHP

djsadinoff
la source
1
Ouais, quand j'étais un contrat pour un site Web qui devait être ultra-sécurisé contre les combattants ennemis et autres, j'ai en fait créé mon propre gestionnaire de session et l'ai alimenté en données d'entropie directement à partir de random.org. Mais les exigences de ce système étaient bien au-delà de ce que la plupart des simples mortels traitent avec ;-)
Theodore R. Smith
1
@ thomas-jensen, gettimeofday est l'horodatage unix, sauf qu'il est exprimé en μsec (parfois). Lisez la méthode php_session_create_id liée ci-dessus.
djsadinoff
4
La modification de la longueur d'entropie améliore le caractère aléatoire mais n'affecte pas de manière significative la probabilité d'une collision puisque le hachage est toujours de la même longueur. Cependant, changer session.hash_function vous permet d'utiliser des hachages plus longs comme sha512 par exemple.
ColinM
2
Je trouve bizarre qu'il y ait des collisions. PHP devrait sûrement être fait pour vérifier s'il y a une session valide sous cet identifiant et générer par la suite un identifiant différent.
Luc
1
@ theodore-r-smith, c'est vraiment une mauvaise pratique de prendre l'entropie d'une source accessible au public. Vous devriez supposer que vos «combattants ennemis» ont également accès à random.org ...
avri
12

Si vous voulez savoir comment PHP génère un identifiant de session par défaut, consultez le code source sur Github . Ce n'est certainement pas aléatoire et est basé sur un hachage (par défaut: md5) de ces ingrédients (voir la ligne 310 de l'extrait de code):

  1. Adresse IP du client
  2. Heure actuelle
  3. Générateur de congruence linéaire PHP - un pseudo générateur de nombres aléatoires (PRNG)
  4. Source aléatoire spécifique au système d'exploitation au système d'exploitation - si le système d'exploitation a une source aléatoire disponible (par exemple / dev / urandom)

Si le système d'exploitation a une source aléatoire disponible, la force de l'ID généré dans le but d'être un ID de session est élevée ( / dev / urandom et les autres sources aléatoires du système d'exploitation sont (généralement) des PRNG sécurisés par cryptographie ). Si toutefois ce n'est pas le cas, c'est satisfaisant.

L'objectif de la génération d'identification de session est de:

  1. minimiser la probabilité de générer deux ID de session avec la même valeur
  2. rendre le calcul très difficile pour générer des clés aléatoires et en frapper une en cours d'utilisation .

Ceci est réalisé par l'approche PHP de la génération de session.

Vous ne pouvez pas absolument garantir l'unicité , mais les probabilités de frapper deux fois le même hachage sont si faibles que cela ne vaut généralement pas la peine de s'inquiéter.

GordyD
la source
11

Vous pouvez installer une fonction alternative de génération de hachage si vous souhaitez personnaliser la façon dont l'ID est généré (c'est un nombre de 128 bits généré via MD5 par défaut). Voir http://www.php.net/manual/en/session.configuration.php#ini.session.hash-function

Pour plus d'informations sur les sessions PHP, essayez cet excellent article http://shiflett.org/articles/the-truth-about-sessions qui renvoie également à d'autres articles sur la fixation de session et le détournement.

Paul Dixon
la source
2
Pour être exact, définissez "session.hash_function = sha512" pour PHP 5.3 et plus pour passer au hachage 512 bits. Cela devrait faire l'affaire. Avec les valeurs par défaut, il est courant sur les sites à fort trafic d'obtenir des collisions.
ColinM
5

Taille de session_id
Supposons que seeion_id est uniformément distribué et a une taille = 128 bits. Supposons que chaque personne sur la planète se connecte une fois par jour avec une nouvelle session persistante pendant 1000 ans.

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 

Ainsi, la probabilité d'une ou de plusieurs collisions est inférieure à une sur 70 000 milliards. Par conséquent, la taille de 128 bits de session_id devrait être suffisamment grande. Comme mentionné dans d'autres commentaires, le session_manager peut également vérifier que le nouveau session_id n'existe pas déjà.

Aléatoire
Par conséquent, la grande question que je pense est de savoir si les session_id: s sont générés avec un bon pseudo-aléatoire. Sur cela, vous ne pouvez jamais être sûr, mais je recommanderais d'utiliser une solution standard bien connue et fréquemment utilisée à cette fin (comme vous le faites probablement déjà).

Même si les collisions sont évitées en raison de la vérification, le caractère aléatoire et la taille de session_id sont importants, de sorte que les pirates ne peuvent pas, d'une manière ou d'une autre, faire des suppositions qualifiées et trouver des session_id: s actifs avec une grande probabilité.

MrJ
la source
3
Je ne suis pas mathématicien, mais je pense que vous oubliez le problème d'anniversaire, donc les chances de collision, même si elles sont encore petites, sont beaucoup plus grandes que vous ne le suggérez. De plus, comme l'a suggéré djsadinoff, PHP n'utilise pas nécessairement une bonne méthode pour générer des nombres aléatoires par défaut.
ColinM
Non en fait l'estimation tient. Le calcul ci-dessus est une estimation simplifiée, où nous estimons que la probabilité d'une collision pour session_id nr i, est = 1/2 82 (elle devrait être 1/2 92 ci-dessus mais = faute de frappe). En réalité, la probabilité est de (i-1) / 2 128 tant qu'aucune collision antérieure ne s'est produite. 1/2 92 n'est valable que pour le dernier session_id.
MrJ
3

Je n'ai pas trouvé de confirmation à ce sujet, mais je crois que php vérifie si un identifiant de session existe déjà avant d'en créer un avec cet identifiant.

Le problème de piratage de session qui inquiète les gens est celui où quelqu'un découvre l'identifiant de session d'un utilisateur actif. Cela peut être évité de plusieurs façons, pour plus d'informations, vous pouvez voir cette page sur php.net et cet article sur la fixation de session

Ólafur Waage
la source
2
... mais si vous n'êtes qu'un serveur php dans une banque de plusieurs, il n'y a aucune garantie que le serveur a suffisamment de connaissances pour savoir si le sesssionID a encore été utilisé.
djsadinoff le
Pourquoi est-ce important que j'aie le même identifiant de session dans 2 serveurs PHP différents? En supposant 2 domaines différents, le cookie de session n'est accessible qu'à partir de chaque domaine ...?
daremon le
3
Le moyen le plus simple d'éviter les dupes dans un environnement multi-serveur est de stocker les sessions dans Memcached via le gestionnaire de session Memcached. problème résolu et vos utilisateurs peuvent rebondir autour des serveurs de différence sans perdre leurs affaires.
Theodore R. Smith
@daremon il parle de plusieurs serveurs pour un domaine.
gtd
C'est tout simplement incorrect. PHP ne vérifie pas les identifiants de session existants lors de la génération de nouveaux. Regardez n'importe quel code de gestionnaire de session PHP et il n'y a tout simplement aucune méthode implémentée à cet effet.
ColinM
2

Non, l'ID de session n'est pas un GUID, mais deux utilisateurs ne doivent pas obtenir le même ID de session car ils sont stockés côté serveur.

gadget
la source
2
Peut-être parce que le stockage côté serveur ne garantit en aucun cas l'unicité. L'unicité est une chose - en cas de collision, elle se heurtera quel que soit l'endroit où la session est stockée.
Pas par moi, j'apprécie votre réponse (ainsi que les autres). - Jalov
Jalov
2
L'ID de session est stocké à la fois côté serveur et côté client. Le contenu de la session est stocké côté serveur. Et le fait n'est pratiquement pas lié à l'unicité de l'identifiant de session.
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>

si votre nom d'utilisateur est différent ou unique, vous pouvez utiliser ce code pour la session

Arun Sharma
la source