Quão único é o id da sessão php

90

Quão único é o id de sessão php? Tenho a impressão de várias coisas que li que não devo confiar que dois usuários nunca obtenham o mesmo ID de sessão. Não é um GUID?

Jalov
fonte

Respostas:

39

Session_id pode realmente ser duplicado, mas a probabilidade é muito baixa. Se você tem um site com um tráfego razoável, isso pode acontecer uma vez na vida do seu site e irá incomodar apenas um usuário por uma sessão.

Não vale a pena se preocupar com isso, a menos que você pretenda construir um site de tráfego muito alto ou um serviço para o setor bancário.

e-satis
fonte
4
Já ouvi relatos de sites que tiveram muitos casos de colisões.
ColinM
20
A pergunta foi feita há quase 4 anos. Seria interessante saber se o algoritmo de id de sessão improvisou desde então ...
Sliq
@ColinM: e esses sites tiveram 1 milhão de visitantes únicos / dia.
e-satis em
1
Aparentemente está baseado atualmente (hash MD5 / SHA1) no endereço remoto do usuário, hora local e algum número aleatório (LCG) .
Caramiriel
2
Eu não preciso quebrar o celular, o celular se quebra constantemente. :)
hakre
67

Não é muito original quando enviado. Na configuração padrão é o resultado de um hash de várias coisas, incluindo o resultado de gettimeofday (que não é terrivelmente único), mas se você estiver preocupado, deve configurá-lo para extrair alguma entropia de / dev / urandom, assim

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

procure por "php_session_create_id" no código do algoritmo real que eles estão usando.

Editado para adicionar: há um gerador de número aleatório DFA propagado pelo pid, misturado com o tempo em usecs. Não é uma condição de exclusividade firme, especialmente do ponto de vista da segurança . Use a configuração de entropia acima.

Atualizar:

A partir do PHP 5.4.0 session.entropy_file o padrão é / dev / urandom ou / dev / arandom se estiver disponível. No PHP 5.3.0, esta diretiva é deixada em branco por padrão. Manual PHP

Djsadinoff
fonte
1
Sim, quando eu era um contrato para um site que tinha que ser ultrasseguro contra combatentes inimigos e tal, eu na verdade criei meu próprio gerenciador de sessão e alimentei com dados de entropia diretamente de random.org. Mas os requisitos desse sistema estavam muito além do que a maioria dos meros mortais lidam com ;-)
Theodore R. Smith
1
@ thomas-jensen, gettimeofday é o carimbo de data / hora unix, exceto que é expresso em µsec (às vezes). Leia o método php_session_create_id vinculado acima.
djsadinoff de
4
Alterar o comprimento da entropia melhora a aleatoriedade, mas não afeta significativamente a probabilidade de uma colisão, uma vez que o hash ainda tem o mesmo comprimento. No entanto, alterar session.hash_function permite que você use hashes mais longos como sha512, por exemplo.
ColinM
2
Acho bizarro que haja colisões. Certamente o PHP deve ser feito para verificar se existe uma sessão válida sob aquele id e subsequentemente gerar um ID diferente.
Lucas
1
@ theodore-r-smith, é uma prática muito ruim obter entropia de uma fonte disponível publicamente. Você deve assumir que seus "combatentes inimigos" também têm acesso a random.org ...
avri
12

Se você quiser saber como o PHP gera um ID de sessão por padrão, verifique o código-fonte no Github . Certamente não é aleatório e é baseado em um hash (padrão: md5) desses ingredientes (consulte a linha 310 do snippet de código):

  1. Endereço IP do cliente
  2. Hora atual
  3. PHP Linear Congruence Generator - um gerador de números pseudo-aleatórios (PRNG)
  4. Fonte aleatória específica do sistema operacional - se o sistema operacional tiver uma fonte aleatória disponível (por exemplo, / dev / urandom)

Se o sistema operacional tiver uma fonte aleatória disponível, a força do ID gerado com o propósito de ser um ID de sessão é alta ( / dev / urandom e outras fontes aleatórias do sistema operacional são (geralmente) PRNGs criptograficamente seguros ). Se, no entanto, não o fizer, então é satisfatório.

O objetivo com a geração de identificação de sessão é:

  1. minimizar a probabilidade de gerar dois IDs de sessão com o mesmo valor
  2. torna muito desafiador computacionalmente gerar chaves aleatórias e acertar uma em uso .

Isso é alcançado pela abordagem do PHP para geração de sessão.

Você não pode garantir absolutamente a exclusividade , mas as probabilidades são tão baixas de acertar o mesmo hash duas vezes que, em geral, não vale a pena se preocupar.

GordyD
fonte
11

Você pode instalar uma função de geração de hash alternativa se quiser personalizar a forma como o ID é gerado (é um número de 128 bits gerado via MD5 por padrão). Veja http://www.php.net/manual/en/session.configuration.php#ini.session.hash-function

Para obter mais informações sobre sessões de PHP, experimente este excelente artigo http://shiflett.org/articles/the-truth-about-sessions que também possui links para outros artigos sobre fixação de sessão e hijack.

Paul Dixon
fonte
2
Para ser exato, defina "session.hash_function = sha512" para PHP 5.3 e superior para ir para hash de 512 bits. Isso deve funcionar. Com os padrões, é comum ocorrer colisões em sites de alto tráfego.
ColinM
5

Tamanho de session_id
Suponha que seeion_id seja uniformemente distribuído e tenha tamanho = 128 bits. Suponha que cada pessoa no planeta efetue login uma vez por dia com uma sessão persistente por 1000 anos.

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 

Portanto, a probabilidade de uma ou mais colisões é menor que uma em 70 mil bilhões. Portanto, o tamanho de 128 bits de session_id deve ser grande o suficiente. Conforme mencionado em outros comentários, o session_manager também pode verificar se o novo session_id ainda não existe.

Aleatoriedade
Portanto, a grande questão que penso é se os session_id: s são gerados com boa pseudo aleatoriedade. Você nunca pode ter certeza disso, mas eu recomendaria usar uma solução padrão bem conhecida e frequentemente usada para esse propósito (como você provavelmente já faz).

Mesmo que as colisões sejam evitadas devido à verificação, a aleatoriedade e o tamanho do session_id são importantes, para que os hackers não possam, de alguma forma, fazer uma suposição qualificada e encontrar session_id: s ativos com grande probabilidade.

MrJ
fonte
3
Não sou matemático, mas acho que você está se esquecendo do problema do aniversário, então as chances de colisão enquanto ainda são pequenas são muito maiores do que você sugere. Além disso, como djsadinoff sugeriu, o PHP não necessariamente usa um bom método de geração de números aleatórios por padrão.
ColinM
Não, na verdade, a estimativa se mantém. O cálculo acima é uma estimativa simplificada, onde estimamos que a probabilidade de uma colisão para session_id nr i, é = 1/2 82 (deve ser 1/2 92 acima embora = typo). Na realidade, a probabilidade é (i-1) / 2 128, desde que nenhuma colisão anterior tenha ocorrido. 1/2 92 é válido apenas para o último session_id.
MrJ
3

Não encontrei uma confirmação sobre isso, mas acredito que o php verifica se já existe um id de sessão antes de criar um com esse id.

O problema de sequestro de sessão com o qual as pessoas estão preocupadas é quando alguém descobre a id de sessão de um usuário ativo. Isso pode ser evitado de várias maneiras, para mais informações você pode ver esta página em php.net e este artigo sobre fixação de sessão

Ólafur Waage
fonte
2
... mas se você é apenas um servidor php em um banco de vários, não há garantia de que o servidor tenha conhecimento suficiente para saber se o sesssionID já foi usado.
djsadinoff
Por que isso importaria se eu obtivesse a mesma id de sessão em 2 servidores php diferentes? Assumindo 2 domínios diferentes, o cookie de sessão só pode ser acessado de cada domínio ...?
daremon
3
A maneira mais fácil de evitar enganos em um ambiente de vários servidores é armazenar as sessões no memcached por meio do manipulador de sessão memcached. problema resolvido e seus usuários podem saltar em torno de servidores diff sem perder suas coisas.
Theodore R. Smith
@daremon ele está falando sobre vários servidores para um domínio.
gtd,
Isso é simplesmente incorreto. O PHP não verifica os ids de sessão existentes ao gerar novos. Observe qualquer código de manipulador de sessão PHP e simplesmente não há nenhum método implementado para esse propósito.
ColinM
2

Não, a id de sessão não é um GUID, mas dois usuários não devem obter a mesma id de sessão que estão armazenados no lado do servidor.

gizmo
fonte
2
Possivelmente porque o armazenamento do lado do servidor não garante exclusividade de forma alguma. A exclusividade é uma coisa - se houver uma colisão, ela colidirá independentemente de onde a sessão está armazenada.
Não por mim, agradeço sua resposta (assim como as outras). - Jalov
Jalov
2
O ID da sessão é armazenado no servidor e no cliente. O conteúdo da sessão é armazenado no lado do servidor. E o fato não está muito relacionado à exclusividade do id de sessão.
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>

se o seu nome de usuário for diferente ou único, você pode usar este código para a sessão

Arun Sharma
fonte