PHP 세션 ID는 얼마나 고유합니까?


90

PHP 세션 ID는 얼마나 고유합니까? 나는 내가 읽은 여러 가지에서 두 명의 사용자에게 결코 동일한 세션 ID를 가져서는 안된다는 인상을 받았습니다. GUID 아닌가요?

답변:


39

Session_id는 실제로 복제 될 수 있지만 확률은 매우 낮습니다. 트래픽이 공정한 웹 사이트를 가지고 있다면, 웹 사이트 생활에서 한 번 발생할 수 있으며 한 세션 동안 한 사용자를 짜증나게 할 것입니다.

트래픽이 매우 많은 웹 사이트 나 은행 업계를위한 서비스를 구축 할 것으로 기대하지 않는 한 이것은 신경 쓸 가치가 없습니다.


4
충돌 사례가 많은 사이트에 대한보고를 들었습니다.
ColinM

20
이 질문은 거의 4 년 전에 제기되었습니다. 세션 ID 알고리즘이 그 이후로 즉석에서 진행되었는지 아는 것이 흥미로울 것입니다 ...
Sliq

@ColinM : 그리고 그 사이트는 하루에 100 만 명의 순 방문자가있었습니다.
e-satis 2012-06-22

1
Aparantly 는 사용자의 원격 주소에 현재 기반 (MD5 / SHA1 해시), 현지 시간과 약간의 난수 (LCG) .
Caramiriel 2013

2
나는 모바일을 깰 필요가 없습니다. :)
hakre

67

배송시 고유하지 않습니다. 기본 구성에서는 gettimeofday (매우 고유하지 않음)의 결과를 포함하여 다양한 항목의 해시 결과이지만 걱정이되는 경우 / dev / urandom에서 일부 엔트로피를 가져 오도록 구성해야합니다.

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

사용중인 실제 알고리즘 에 대한 코드 에서 "php_session_create_id"를 검색하십시오 .

추가 수정 : pid로 시드 된 DFA 난수 생성기가 usecs의 시간과 혼합되어 있습니다. 특히 보안 관점에서 볼 때 확고한 고유성 조건이 아닙니다 . 위의 엔트로피 구성을 사용하십시오.

최신 정보:

PHP 5.4.0부터 session.entropy_file의 기본값은 / dev / urandom 또는 / dev / arandom입니다. PHP 5.3.0에서이 지시문은 기본적으로 비어 있습니다. PHP 매뉴얼


1
네, 제가 적의 전투원들에 대해 매우 안전해야하는 웹 사이트 계약을했을 때, 저는 실제로 제 세션 핸들러를 만들고 random.org에서 직접 엔트로피 데이터를 제공했습니다. 그러나 그 시스템의 요구 사항은 대부분의 단순한 필사자가 처리하는 것보다 훨씬 많았습니다. ;-)
Theodore R. Smith

1
@ thomas-jensen, gettimeofday μsec (때때로)로 표현되는 것을 제외하고는 유닉스 타임 스탬프입니다. 위에 링크 된 php_session_create_id 메소드를 읽으십시오.
djsadinoff 2011

4
엔트로피 길이를 변경하면 임의성이 향상되지만 해시 길이가 여전히 동일하므로 충돌 가능성에 큰 영향을주지 않습니다. 그러나 session.hash_function을 변경하면 예를 들어 sha512와 같은 더 긴 해시를 사용할 수 있습니다.
ColinM

2
충돌이 있다는 것이 이상합니다. 확실히 PHP는 해당 ID 아래에 유효한 세션이 있는지 확인하고 이후에 다른 ID를 생성하도록 만들어야합니다.
Luke

1
@ theodore-r-smith, 공개적으로 사용 가능한 소스에서 엔트로피를 가져 오는 것은 정말 나쁜 습관입니다. "Enemy combatants"도 random.org에 액세스 할 수 있다고 가정해야합니다 ...
avri

12

PHP가 기본적으로 세션 ID를 생성하는 방법을 알고 싶다면 Github 의 소스 코드를 확인하십시오 . 확실히 무작위가 아니며 다음 성분의 해시 (기본값 : md5)를 기반으로합니다 (코드 스 니펫의 310 행 참조).

  1. 클라이언트의 IP 주소
  2. 현재 시간
  3. PHP Linear Congruence Generator- 의사 난수 생성기 (PRNG)
  4. OS 별 임의 소스 -OS에 사용 가능한 임의 소스가있는 경우 (예 : / dev / urandom)

OS에 사용 가능한 임의의 소스가있는 경우 세션 ID가 될 목적으로 생성 된 ID의 강도가 높습니다 ( / dev / urandom 및 기타 OS 임의 소스는 (일반적으로) 암호화 보안 PRNG ). 그러나 그렇지 않다면 만족 스럽습니다.

세션 식별 생성의 목표는 다음과 같습니다.

  1. 동일한 값으로 두 개의 세션 ID를 생성 할 가능성을 최소화합니다.
  2. 임의의 키를 생성하고 사용중인 키를 누르는 것은 계산적으로 매우 어렵습니다 .

이것은 세션 생성에 대한 PHP의 접근 방식에 의해 달성됩니다.

고유성을 절대적으로 보장 할 수는 없지만 동일한 해시를 두 번 칠 확률이 너무 낮아 일반적으로 걱정할 가치가 없습니다.


11

ID가 생성되는 방식을 사용자 지정하려는 경우 대체 해시 생성 기능을 설치할 수 있습니다 (기본적으로 MD5를 통해 생성되는 128 비트 번호). 참조 http://www.php.net/manual/en/session.configuration.php#ini.session.hash-function를

PHP 세션에 대한 자세한 내용 은 세션 고정 및 하이재킹에 대한 다른 기사로 연결되는 이 훌륭한 기사 http://shiflett.org/articles/the-truth-about-sessions 를 참조 하십시오 .


2
정확히 말하면 PHP 5.3에 대해 "session.hash_function = sha512"를 설정하고 최대 512 비트 해시로 이동합니다. 이것은 트릭을 할 것입니다. 기본값을 사용하면 트래픽이 많은 사이트에서 충돌이 발생하는 것이 일반적입니다.
ColinM

5

session_id의 크기
seesion_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 

따라서 하나 이상의 충돌 확률은 7 천억 분의 1 미만입니다. 따라서 session_id의 128 비트 크기는 충분히 커야합니다. 다른 의견에서 언급했듯이 session_manager는 새 session_id가 이미 존재하지 않는지 확인할 수도 있습니다.

임의성
따라서 내가 생각하는 가장 큰 질문은 session_id : s가 좋은 의사 임의성으로 생성되는지 여부입니다. 확신 할 수는 없지만이 목적을 위해 잘 알려져 있고 자주 사용되는 표준 솔루션을 사용하는 것이 좋습니다 (아마도 이미 사용했듯이).

검사로 인해 충돌을 피하더라도 session_id의 임의성과 크기가 중요하므로 해커는 할 수 없기 때문에 어떻게 든 자격을 갖춘 추측을 수행하고 큰 확률로 활성 session_id : s를 찾습니다.


3
나는 수학자는 아니지만 생일 문제를 잊고 있다고 생각 하므로 아직 작지만 충돌 가능성이 제안한 것보다 훨씬 큽니다. 또한 djsadinoff가 제안했듯이 PHP는 기본적으로 난수를 생성하는 좋은 방법을 반드시 사용하지는 않습니다.
ColinM

실제로 추정치는 유효하지 않습니다. 위의 계산은 단순화 된 추정값으로 session_id nr i에 대한 충돌 확률은 = 1/2 82 ( = typo이지만 1/2 92 이상 이어야 함 )입니다. 실제로 이전 충돌이 발생하지 않는 한 확률은 (i-1) / 2128입니다 . 1/2 92는 마지막 session_id에 대해서만 유지됩니다.
MrJ

3

나는 이것에 대한 확인을 찾지 못했지만 PHP는 해당 ID로 세션 ID를 만들기 전에 세션 ID가 이미 존재하는지 확인한다고 생각합니다.

사람들이 걱정하는 세션 하이재킹 문제는 누군가가 활성 사용자의 세션 ID를 알아낼 때입니다. 이것은 php.net 에서이 페이지 를 볼 수 있고 세션 고정에 대한이 문서에서 볼 수있는 더 많은 정보를 위해 여러 가지 방법으로 방지 할 수 있습니다.


2
...하지만 여러 은행에있는 하나의 PHP 서버 인 경우 서버가 sesssionID가 아직 사용되었는지 여부를 알 수있는 충분한 지식을 가지고 있다는 보장이 없습니다.
djsadinoff

두 개의 다른 PHP 서버에서 동일한 세션 ID를 얻는 것이 왜 중요합니까? 2 개의 다른 도메인을 가정하면 세션 쿠키는 각 도메인에서만 액세스 할 수 있습니다 ...?
daremon

3
다중 서버 환경에서 중복을 방지하는 가장 쉬운 방법은 memcached 세션 핸들러를 통해 memcached에 세션을 저장하는 것입니다. 문제가 해결되고 사용자는 물건을 잃지 않고 diff 서버를 돌아 다닐 수 있습니다.
Theodore R. Smith

@daremon 그는 하나의 도메인에 대해 여러 서버에 대해 이야기하고 있습니다.
gtd

이것은 단순히 잘못된 것입니다. PHP는 새 세션 ID를 생성 할 때 기존 세션 ID를 확인하지 않습니다. PHP 세션 핸들러 코드를 보면이 목적을 위해 구현 된 메소드가 없습니다.
ColinM

2

아니요, 세션 ID는 GUID가 아니지만 두 사용자는 서버 측에 저장된 것과 동일한 세션 ID를 가져서는 안됩니다.


2
서버 측 스토리지가 어떤 식 으로든 고유성을 보장하지 않기 때문일 수 있습니다. 고유성은 한 가지입니다. 충돌이 발생하면 세션이 저장된 위치에 관계없이 충돌합니다.

저가 아니라 귀하의 답변에 감사드립니다. -Jalov
Jalov

2
세션 ID는 서버 측과 클라이언트 측 모두에 저장됩니다. 세션 내용은 서버 측에 저장됩니다. 그리고 사실은 세션 ID의 고유성과 거의 관련이 없습니다.
YudhiWidyatama 2013 년

0

DB 생성 고유 필드와 함께 다양한 세션을 DB에 저장하도록 선택할 수 있습니다. 둘을 병합하고 세션 변수에 저장 한 다음 세션 ID 대신 하나를 확인하십시오.


stackoverflow에 오신 것을 환영합니다. 귀하의 답변은 불행히도 질문에 대한 답변을 시도하지 않습니다. OP는 세션 ID가 얼마나 고유한지 물었습니다. 데이터베이스에 데이터를 저장 한 다음 세션 변수를 사용하여 검색하면 문제가 더 복잡해지지 않습니까?
Noah Boegli

@NoahBoegli 다른 솔루션은 더 복잡한 방법을 제안했습니다.
악성

-4
<?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>

사용자 이름이 다르거 나 고유 한 경우이 코드를 세션에 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.