Наскільки унікальним є ідентифікатор сеансу php


90

Наскільки унікальний ідентифікатор сеансу php? З різних речей, які я прочитав, у мене склалося враження, що я не повинен покладатися на те, що двоє користувачів ніколи не отримують однаковий сеанс. Хіба це не GUID?

Відповіді:


39

Session_id дійсно можна продублювати, але ймовірність дуже низька. Якщо у вас є веб-сайт із належним трафіком, це може трапитися один раз у житті вашого веб-сайту, і це просто дратуватиме одного користувача за один сеанс.

Про це не варто турбуватися, якщо ви не сподіваєтесь створити веб-сайт із високим трафіком або послугу для банківської галузі.


4
Я чув повідомлення про сайти, які мали багато випадків зіткнень.
ColinM

20
Питання було задане майже 4 роки тому. Було б цікаво дізнатись, чи алгоритм ідентифікатора сесії імпровізував з тих пір ...
Sliq

@ColinM: і ці сайти мали 1 мільйон унікальних відвідувачів на день.
e-satisfa

1
Відповідно його поточно заснований (хеш MD5 / SHA1) віддалена адреса користувача, місцевий час та деяке випадкове число (LCG) .
Caramiriel

2
Мені не потрібно ламати мобільний, мобільний постійно ламається сам. :)
hakre

67

Це не дуже унікально, оскільки відправляється. У конфігурації за замовчуванням це результат хешу різних речей, включаючи результат gettimeofday (що не страшно унікально), але якщо ви стурбовані, вам слід налаштувати його, щоб намалювати якусь ентропію з / dev / urandom, ось так

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

шукати "php_session_create_id" у коді для фактичного алгоритму, який вони використовують.

Відредаговано, щоб додати: Існує генератор випадкових чисел DFA, засіяний pid, змішаний з часом в usecs. Це не є твердою умовою унікальності, особливо з точки зору безпеки . Використовуйте конфігурацію ентропії вище.

Оновлення:

Станом на PHP 5.4.0 session.entropy_file за замовчуванням має значення / dev / urandom або / dev / arandom, якщо він доступний. У PHP 5.3.0 ця директива за замовчуванням залишається порожньою. Посібник PHP


1
Так, коли я укладав контракт на веб-сайт, який повинен був бути надзахищеним від ворожих учасників бойових дій і подібних, я насправді створив власний обробник сеансів і подав його ентропійні дані безпосередньо з random.org. Але вимоги цієї системи набагато перевищували те, що мають справу більшість простих смертних з; ;-)
Теодор Р. Сміт

1
@ thomas-jensen, gettimeofday - це мітка часу unix, за винятком того, що вона виражається в мкс (іноді). Прочитайте метод php_session_create_id, зв’язаний вище.
djsadinoff

4
Зміна довжини ентропії покращує випадковість, але суттєво не впливає на ймовірність зіткнення, оскільки хеш все ще має однакову довжину. Однак зміна session.hash_function дозволяє використовувати довші хеші, наприклад sha512.
ColinM

2
Я вважаю дивним, що трапляються зіткнення. Безумовно, слід зробити PHP, щоб перевірити, чи є дійсним сеанс під цим ідентифікатором, і згодом згенерувати інший ідентифікатор.
Лука

1
@ theodore-r-smith, насправді погана практика брати ентропію з загальнодоступного джерела. Ви повинні припустити, що ваші "ворожі комбатанти" також мають доступ до random.org ...
avri

12

Якщо ви хочете знати, як PHP генерує ідентифікатор сеансу за замовчуванням, перевірте вихідний код на Github . Це, звичайно, не випадково і базується на хеші (за замовчуванням: md5) цих інгредієнтів (див. Рядок 310 фрагмента коду):

  1. IP-адреса клієнта
  2. Поточний час
  3. Генератор лінійної конгруентності PHP - генератор псевдовипадкових чисел (PRNG)
  4. Випадкове джерело для конкретної ОС - якщо в ОС доступне випадкове джерело (наприклад, / dev / urandom)

Якщо ОС має доступне випадкове джерело, тоді сила сформованого ідентифікатора для того, щоб бути ідентифікатором сеансу, є високою ( / dev / urandom та інші випадкові джерела ОС є (зазвичай) криптографічно захищеними PRNG ). Якщо ж це не так, то це задовільно.

Метою генерації ідентифікації сеансу є:

  1. мінімізувати ймовірність генерації двох ідентифікаторів сеансу з однаковим значенням
  2. зробити це дуже складним обчислювальним способом генерувати випадкові ключі та натискати на використовуваний .

Це досягається підходом PHP до генерації сеансів.

Ви не можете абсолютно гарантувати унікальність , але ймовірність того, що двічі потрапить в один і той же хеш, настільки мала, що про це, взагалі кажучи, не варто турбуватися.


11

Ви можете встановити альтернативну функцію генерації хешу, якщо хочете налаштувати спосіб генерації ідентифікатора (це 128-бітне число, генероване за допомогою MD5 за замовчуванням). Див. Http://www.php.net/manual/en/session.configuration.php#ini.session.hash-function

Щоб отримати додаткову інформацію про сесії PHP, спробуйте цю чудову статтю http://shiflett.org/articles/the-truth-about-sessions, яка також посилається на інші статті про фіксацію та викрадення сеансу.


2
Точніше, встановіть "session.hash_function = sha512" для PHP 5.3 і вище, щоб перейти до 512-бітного хешу. Це повинно зробити трюк. За замовчуванням на сайтах із великим трафіком часто зустрічаються зіткнення.
ColinM

5

Розмір session_id
Припустимо, що seeion_id рівномірно розподілений і має розмір = 128 біт. Припустимо, що кожна людина на планеті входить в систему один раз на день, постійно проводячи новий сеанс протягом 1000 років.

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 

Отже, ймовірність одного або декількох зіткнень менше одного на 70 тисяч мільярдів. Отже, 128-бітний розмір session_id повинен бути досить великим. Як зазначалося в інших коментарях, session_manager може також перевірити, що новий session_id ще не існує.

Випадковість
Тому велике питання, на мою думку, полягає в тому, чи створюються session_id: s з хорошою псевдовипадковістю. У цьому ви ніколи не можете бути впевнені, але я б порадив використовувати для цього добре відоме та часто використовуване стандартне рішення (як ви, мабуть, уже робите).

Навіть якщо зіткнень вдається уникнути через перевірку, важлива випадковість та розмір session_id, тому хакери не можуть, якось зробити кваліфіковане відгадування та знайти активний session_id: s з великою ймовірністю.


3
Я не математик, але я думаю, що ти забуваєш про проблему з Днем народження, тому шанси зіткнення, поки все ще малі, набагато більші, ніж ти передбачаєш. Крім того, як запропонував djsadinoff, PHP не обов'язково використовують хороший метод генерації випадкових чисел за замовчуванням.
ColinM

Насправді оцінка не відповідає. Наведений вище розрахунок є спрощеною оцінкою, де ми оцінюємо, що ймовірність зіткнення для session_id nr i дорівнює = 1/2 82 (вона повинна бути 1/2 92 вище, хоча = друкарська помилка). Насправді ймовірність становить (i-1) / 2 128 до тих пір, поки не відбулося жодного попереднього зіткнення. 1/2 92 утримується лише для останнього сеансу_id.
MrJ

3

Я не знайшов підтвердження на це, але я вважаю, що php перевіряє, чи вже існує ідентифікатор сеансу, перш ніж створювати такий із цим ідентифікатором.

Люди, які хвилюються через проблему викрадення сесії, це коли хтось дізнається ідентифікатор сеансу активного користувача. Цього можна запобігти різними способами, для отримання додаткової інформації про це ви можете ознайомитись на цій сторінці на php.net та у цій статті про фіксацію сеансу


2
... але якщо ви лише один php-сервер із декількох банків, немає гарантії, що сервер має достатньо знань, щоб знати, чи використовувався sesssionID.
djsadinoff

Чому це має значення, якщо я отримав однаковий ідентифікатор сеансу на 2-х різних php-серверах? Припускаючи 2 різні домени, сеансовий файл cookie доступний лише з кожного домену ...?
даремон

3
Найпростіший спосіб запобігти обману в мультисерверному середовищі - зберігати сеанси в memcached за допомогою обробника memcached сеансу. проблема вирішена, і ваші користувачі можуть відбиватися навколо серверів різниці без втрати своїх речей.
Теодор Р. Сміт

@daremon він говорить про кілька серверів для одного домену.
gtd

Це просто неправильно. PHP не перевіряє наявні ідентифікатори сеансів під час створення нових. Подивіться на будь-який код обробника сеансу PHP, і для цього просто немає методу.
ColinM

2

Ні, ідентифікатор сеансу не є GUID, але двоє користувачів не повинні отримувати однаковий ідентифікатор сеансу, оскільки вони зберігаються на стороні сервера.


2
Можливо, тому, що серверне сховище жодним чином не гарантує унікальність. Унікальність - це одне - у разі зіткнення воно зіткнеться незалежно від місця зберігання сеансу.

Не я, я ціную вашу відповідь (як і інші). - Jalov
Jalov

2
Ідентифікатор сеансу зберігається як на сервері, так і на стороні клієнта. Вміст сеансу зберігається на стороні сервера. І факт майже не пов’язаний з унікальністю ідентифікатора сеансу.
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>

якщо ваше ім'я користувача інше або унікальне, ви можете використовувати цей код для сеансу

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.