รหัสเซสชัน php มีเอกลักษณ์เพียงใด


91

id เซสชัน php มีเอกลักษณ์เพียงใด ฉันได้รับความประทับใจจากสิ่งต่างๆที่ฉันได้อ่านว่าฉันไม่ควรพึ่งพาผู้ใช้สองคนที่ไม่เคยได้รับ sessionid เดียวกัน มันไม่ใช่ GUID เหรอ?

คำตอบ:


40

Session_id สามารถทำซ้ำได้แน่นอน แต่ความน่าจะเป็นต่ำมาก หากคุณมีเว็บไซต์ที่มีการเข้าชมที่เหมาะสมอาจเกิดขึ้นครั้งเดียวในชีวิตเว็บไซต์ของคุณและจะรบกวนผู้ใช้เพียงคนเดียวในหนึ่งเซสชัน

สิ่งนี้ไม่คุ้มค่าที่จะดูแลเว้นแต่คุณจะคาดหวังว่าจะสร้างเว็บไซต์ที่มีการเข้าชมสูงมากหรือบริการสำหรับอุตสาหกรรมธนาคาร


4
ฉันเคยได้ยินรายงานของไซต์ที่มีการชนกันหลายครั้ง
ColinM

20
คำถามถูกถามเมื่อเกือบ 4 ปีที่แล้ว มันจะน่าสนใจที่จะรู้ว่าอัลกอริทึมรหัสเซสชันได้ถูกปรับปรุงตั้งแต่นั้นมาหรือไม่ ...
Sliq

@ColinM: และไซต์เหล่านั้นมีผู้เยี่ยมชมที่ไม่ซ้ำกัน 1 ล้านคน / วัน
e-satis

1
Aparantlyของมันขึ้นอยู่ในขณะ (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 แต่ความต้องการของระบบนั้นไกลเกินกว่าที่มนุษย์ส่วนใหญ่จัดการกับ w / ;-)
Theodore

1
@ thomas-jensen, gettimeofday คือการประทับเวลา Unix ยกเว้นจะแสดงเป็นμsec (บางครั้ง) อ่านวิธี php_session_create_id ที่ลิงก์ด้านบน
djsadinoff

4
การเปลี่ยนความยาวเอนโทรปีช่วยเพิ่มการสุ่ม แต่ไม่มีผลอย่างมีนัยสำคัญต่อโอกาสที่จะเกิดการชนกันเนื่องจากแฮชยังคงมีความยาวเท่าเดิม อย่างไรก็ตามการเปลี่ยน session.hash_function ช่วยให้คุณใช้แฮชได้นานขึ้นเช่น sha512 เป็นต้น
ColinM

2
ฉันคิดว่ามันแปลกที่มีการชนกัน แน่นอน PHP ควรตรวจสอบว่ามีเซสชันที่ถูกต้องภายใต้ id นั้นหรือไม่และสร้าง ID อื่นในภายหลัง ..
ลุค

1
@ theodore-r-smith การใช้เอนโทรปีจากแหล่งที่เปิดเผยต่อสาธารณะเป็นวิธีปฏิบัติที่แย่มาก คุณควรถือว่า "ศัตรูผู้สู้รบ" ของคุณสามารถเข้าถึง random.org ได้เช่นกัน ...
avri

12

หากคุณต้องการที่จะทราบวิธี PHP สร้างรหัสเซสชั่นเริ่มต้นด้วยเช็คออกรหัสที่มาบนGithub มันไม่ใช่แบบสุ่มอย่างแน่นอนและขึ้นอยู่กับแฮช (ค่าเริ่มต้น: md5) ของส่วนผสมเหล่านี้ (ดูบรรทัด 310 ของข้อมูลโค้ด):

  1. ที่อยู่ IPของไคลเอนต์
  2. เวลาปัจจุบัน
  3. PHP Linear Congruence Generator - ตัวสร้างตัวเลขสุ่มหลอก (PRNG)
  4. แหล่งที่มาแบบสุ่มเฉพาะระบบปฏิบัติการ - หากระบบปฏิบัติการมีแหล่งที่มาแบบสุ่ม (เช่น / dev / urandom)

หากระบบปฏิบัติการมีแหล่งที่มาแบบสุ่มความแข็งแกร่งของ ID ที่สร้างขึ้นเพื่อจุดประสงค์ในการเป็นรหัสเซสชันจะสูง ( / dev / urandom และแหล่งข้อมูลแบบสุ่มของระบบปฏิบัติการอื่น ๆ (โดยปกติ) PRNG ที่ปลอดภัยในการเข้ารหัส ) หากไม่เป็นเช่นนั้นก็เป็นที่น่าพอใจ

เป้าหมายของการสร้างการระบุเซสชันคือ:

  1. ลดความน่าจะเป็นในการสร้างรหัสเซสชันสองรายการที่มีค่าเดียวกัน
  2. สร้างความท้าทายในการคำนวณในการสร้างคีย์แบบสุ่มและกดปุ่มที่ใช้งานอยู่

สิ่งนี้ทำได้โดยแนวทางของ PHP ในการสร้างเซสชัน

คุณไม่สามารถรับประกันความเป็นเอกลักษณ์ได้อย่างแน่นอนแต่ความน่าจะเป็นนั้นต่ำมากในการกดแฮชเดียวกันสองครั้งซึ่งโดยทั่วไปแล้วไม่ควรกังวล


11

คุณสามารถติดตั้งฟังก์ชันการสร้างแฮชทางเลือกได้หากคุณต้องการปรับแต่งวิธีสร้าง ID (เป็นหมายเลข 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 บิต สมมติว่าทุกคนบนโลกเข้าสู่ระบบวันละครั้งพร้อมกับเซสชั่นใหม่อย่างต่อเนื่องเป็นเวลา 1,000 ปี

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,000 พันล้าน ดังนั้น 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 (ควรเป็น 1/2 92 ด้านบนแม้ว่า = พิมพ์ผิด) ในความเป็นจริงความน่าจะเป็นคือ (i-1) / 2 128 ตราบเท่าที่ไม่มีการชนกันก่อนหน้านี้เกิดขึ้น 1/2 92 เก็บไว้สำหรับ session_id สุดท้ายเท่านั้น
MrJ

3

ฉันไม่พบการยืนยันในเรื่องนี้ แต่ฉันเชื่อว่า php ตรวจสอบว่ามีรหัสเซสชันอยู่แล้วหรือไม่ก่อนที่จะสร้างด้วยรหัสนั้น

ปัญหาการจี้เซสชันที่ผู้คนกังวลคือเมื่อมีคนพบรหัสเซสชันของผู้ใช้ที่ใช้งานอยู่ สิ่งนี้สามารถป้องกันได้หลายวิธีสำหรับข้อมูลเพิ่มเติมที่คุณสามารถดูหน้านี้ใน php.net และเอกสารนี้เกี่ยวกับการตรึงเซสชัน


2
... แต่ถ้าคุณเป็นเพียงเซิร์ฟเวอร์ php เดียวในหลายธนาคารไม่มีการรับประกันว่าเซิร์ฟเวอร์จะมีความรู้เพียงพอที่จะทราบว่ามีการใช้ sesssionID หรือยัง
djsadinoff

เหตุใดจึงมีความสำคัญหากฉันได้รับรหัสเซสชันเดียวกันในเซิร์ฟเวอร์ php 2 เครื่องที่แตกต่างกัน สมมติว่า 2 โดเมนที่แตกต่างกันคุกกี้เซสชันสามารถเข้าถึงได้จากแต่ละโดเมนเท่านั้น ... ?
Daremon

3
วิธีที่ง่ายที่สุดในการป้องกันการเกิดซ้ำบนสภาพแวดล้อมแบบหลายเซิร์ฟเวอร์คือการจัดเก็บเซสชันใน memcached ผ่านตัวจัดการเซสชัน memcached แก้ไขปัญหาและผู้ใช้ของคุณสามารถเด้งไปรอบ ๆ เซิร์ฟเวอร์ที่แตกต่างกันโดยไม่สูญเสียข้อมูล
Theodore

@daremon เขากำลังพูดถึงเซิร์ฟเวอร์หลายเครื่องสำหรับโดเมนเดียว
gtd

สิ่งนี้ไม่ถูกต้อง PHP ไม่ตรวจสอบรหัสเซสชันที่มีอยู่เมื่อสร้างใหม่ ดูโค้ดตัวจัดการเซสชัน PHP และไม่มีวิธีใดที่นำมาใช้เพื่อจุดประสงค์นี้
ColinM

2

ไม่รหัสเซสชันไม่ใช่ GUID แต่ผู้ใช้สองคนไม่ควรได้รับรหัสเซสชันเดียวกันเนื่องจากถูกเก็บไว้ที่ฝั่งเซิร์ฟเวอร์


2
อาจเป็นเพราะที่เก็บข้อมูลฝั่งเซิร์ฟเวอร์ไม่รับประกันความเป็นเอกลักษณ์ แต่อย่างใด ความเป็นเอกลักษณ์เป็นสิ่งหนึ่ง - หากมีการชนกันมันจะชนกันไม่ว่าจะจัดเก็บเซสชันไว้ที่ใด

ไม่ใช่ฉันขอขอบคุณสำหรับการตอบกลับของคุณ (เช่นเดียวกับคนอื่น ๆ ) - Jalov
Jalov

2
รหัสเซสชันถูกเก็บไว้ทั้งในฝั่งเซิร์ฟเวอร์และไคลเอนต์ เนื้อหาเซสชันจะถูกเก็บไว้ในฝั่งเซิร์ฟเวอร์ และความจริงก็ไม่ค่อยเกี่ยวข้องกับความเป็นเอกลักษณ์ของรหัสเซสชัน
YudhiWidyatama

0

คุณสามารถเลือกที่จะจัดเก็บเซสชันต่างๆบน DB พร้อมกับ aa DB เพื่อสร้างฟิลด์เฉพาะ รวมทั้งสองและบันทึกในตัวแปรเซสชันจากนั้นตรวจสอบว่าอันนั้นแทนรหัสเซสชัน


ยินดีต้อนรับสู่ stackoverflow คำตอบของคุณไม่ได้พยายามตอบคำถามอย่างน่าเสียดาย OP ถามว่ารหัสเซสชันมีลักษณะเฉพาะอย่างไร การจัดเก็บข้อมูลบนฐานข้อมูลแล้วใช้ตัวแปรเซสชันเพื่อดึงข้อมูลจะเพิ่มความซับซ้อนให้กับปัญหาหรือไม่?
Noah Boegli

@NoahBoegli วิธีแก้ปัญหาอื่น ๆ แนะนำวิธีที่ซับซ้อนมากขึ้น
Pernicious

-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.