ความปลอดภัยเซสชัน PHP


125

แนวทางในการรักษาความปลอดภัยของเซสชันที่รับผิดชอบด้วย PHP มีอะไรบ้าง? มีข้อมูลอยู่ทั่วเว็บและถึงเวลาแล้วที่ทุกอย่างจะมารวมอยู่ในที่เดียว!

คำตอบ:


88

มีสองสิ่งที่ต้องทำเพื่อให้เซสชันของคุณปลอดภัย:

  1. ใช้ SSL เมื่อตรวจสอบสิทธิ์ผู้ใช้หรือดำเนินการที่ละเอียดอ่อน
  2. สร้างรหัสเซสชันใหม่ทุกครั้งที่ระดับความปลอดภัยเปลี่ยนแปลง (เช่นการเข้าสู่ระบบ) คุณสามารถสร้างรหัสเซสชันใหม่ได้ทุกคำขอหากต้องการ
  3. หมดเวลาเซสชัน
  4. อย่าใช้ register globals
  5. จัดเก็บรายละเอียดการพิสูจน์ตัวตนบนเซิร์ฟเวอร์ นั่นคืออย่าส่งรายละเอียดเช่นชื่อผู้ใช้ในคุกกี้
  6. ตรวจสอบไฟล์$_SERVER['HTTP_USER_AGENT']. สิ่งนี้จะเพิ่มอุปสรรคเล็กน้อยในการจี้เซสชัน คุณยังสามารถตรวจสอบที่อยู่ IP แต่สิ่งนี้ทำให้เกิดปัญหาสำหรับผู้ใช้ที่มีการเปลี่ยนที่อยู่ IP เนื่องจากการโหลดบาลานซ์ในการเชื่อมต่ออินเทอร์เน็ตหลายรายการเป็นต้น (ซึ่งเป็นกรณีนี้ในสภาพแวดล้อมของเราที่นี่)
  7. ล็อกการเข้าถึงเซสชันบนระบบไฟล์หรือใช้การจัดการเซสชันแบบกำหนดเอง
  8. สำหรับการดำเนินการที่ละเอียดอ่อนให้พิจารณากำหนดให้ผู้ใช้ที่เข้าสู่ระบบเพื่อให้รายละเอียดการตรวจสอบสิทธิ์อีกครั้ง

15
การใช้ SSL เฉพาะสำหรับการดำเนินการบางอย่างนั้นไม่เพียงพอเว้นแต่คุณจะมีเซสชันแยกต่างหากสำหรับการรับส่งข้อมูลที่เข้ารหัสและไม่ได้เข้ารหัส หากคุณใช้เซสชันเดียวผ่าน HTTPS และ HTTP ผู้โจมตีจะขโมยไปในคำขอแรกที่ไม่ใช่ HTTPS
Kornel

6
-1 ตัวแทนผู้ใช้มีความสำคัญต่อการปลอมแปลง สิ่งที่คุณอธิบายรหัสสิ้นเปลืองและไม่ใช่ระบบรักษาความปลอดภัย
rook

24
@ The Rook อาจเป็นอุปสรรคเล็กน้อย (ผู้โจมตีสามารถจับตัวแทนผู้ใช้ของเหยื่อโดยใช้ไซต์ของตนเอง) และอาศัยการรักษาความปลอดภัยผ่านความสับสน แต่ก็ยังคงเป็นอุปสรรคพิเศษอย่างหนึ่ง หาก User-Agent HTTP มีการเปลี่ยนแปลงระหว่างการใช้งานเซสชันจะน่าสงสัยอย่างยิ่งและน่าจะเป็นการโจมตี ฉันไม่เคยบอกว่าคุณสามารถใช้มันคนเดียวได้ หากคุณใช้ร่วมกับเทคนิคอื่น ๆ คุณจะมีไซต์ที่ปลอดภัยกว่ามาก
ทม

5
@grom ฉันคิดว่ามันเหมือนกับการเอาสก็อตเทปมาพันไว้ที่ประตูของคุณและบอกว่ามันจะป้องกันไม่ให้คนเข้ามา
rook

8
หากคุณกำลังตรวจสอบตัวแทนผู้ใช้คุณจะบล็อกคำขอทั้งหมดจากผู้ใช้ IE8 เมื่อพวกเขาสลับโหมดความเข้ากันได้ ดูสนุกที่ผมได้ติดตามการลงปัญหานี้ในรหัสของตัวเอง: serverfault.com/questions/200018/http-302-problem-on-ie7 ฉันกำลังตรวจสอบตัวแทนผู้ใช้เพราะมันเป็นเรื่องเล็กน้อยที่จะปลอมแปลงอย่างที่คนอื่นพูด
bestattendance

15

แนวทางหนึ่งคือการเรียกsession_regenerate_idทุกครั้งที่ระดับความปลอดภัยของเซสชันเปลี่ยนแปลง ซึ่งช่วยป้องกันการจี้เซสชัน


11

สองเซ็นต์ (หรือมากกว่า) ของฉัน:

  • อย่าเชื่อใจใคร
  • อินพุตตัวกรองเอาต์พุตการหลีกเลี่ยง (คุกกี้ข้อมูลเซสชันก็เป็นข้อมูลของคุณเช่นกัน)
  • หลีกเลี่ยง XSS (สร้าง HTML ให้ดีดูPHPTALหรือHTMLPurifier )
  • การป้องกันในเชิงลึก
  • อย่าเปิดเผยข้อมูล

มีหนังสือเล่มเล็ก ๆ แต่ดีในหัวข้อนี้: Essential PHP Security โดย Chris ShiflettShiflett

การรักษาความปลอดภัย PHP ที่จำเป็น http://shiflett.org/images/essential-php-security-small.png

ในหน้าแรกของหนังสือคุณจะพบตัวอย่างโค้ดที่น่าสนใจและบทตัวอย่าง

คุณอาจใช้เทคนิคที่กล่าวถึงข้างต้น (IP & UserAgent) อธิบายไว้ที่นี่: วิธีหลีกเลี่ยงการโจรกรรม


+1 สำหรับการป้องกัน XSS หากปราศจากสิ่งนั้นก็เป็นไปไม่ได้ที่จะป้องกัน CSRF และทำให้ใครบางคนสามารถ "ขี่" เซสชันได้โดยไม่ต้องรับรหัสเซสชัน
Kornel

11

ฉันคิดว่าปัญหาสำคัญอย่างหนึ่ง (ซึ่งได้รับการแก้ไขใน PHP 6) คือ register_globals ตอนนี้เป็นหนึ่งในวิธีการมาตรฐานที่ใช้ในการหลีกเลี่ยงregister_globalsคือการใช้$_REQUEST, $_GETหรือ$_POSTอาร์เรย์

"ถูกต้อง" วิธีที่จะทำ (ราว 5.2 แม้ว่ามันจะเป็นรถเล็ก ๆ น้อย ๆ มี แต่มั่นคง ณ วันที่ 6 ซึ่งเป็นเร็ว ๆ นี้) คือผ่านฟิลเตอร์

แทนที่จะเป็น:

$username = $_POST["username"];

คุณจะทำ:

$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);

หรือแม้แต่:

$username = filter_input(INPUT_POST, 'username');

2
สิ่งนี้ไม่มีความเกี่ยวข้องกับคำถามเลย
The Pixel Developer

5
จริงๆ? แล้วทำไมในคำตอบที่ยอมรับพวกเขาถึงไม่ใช้ register globals? เท่าที่นักพัฒนาที่ดำเนินการตามโรงงานส่วนใหญ่กังวลการลงทะเบียน globals และรูปแบบการจัดการตัวแปรจะอยู่ภายใต้ร่มของ "เซสชัน" แม้ว่าในทางเทคนิคจะไม่ได้เป็นส่วนหนึ่งของออบเจ็กต์ "เซสชัน" ก็ตาม
cmcculloh

9
ฉันเห็นนี้ไม่ได้อย่างเต็มที่ตอบคำถาม แต่เป็นที่แน่นอนส่วนหนึ่งของคำตอบให้กับคำถาม อีกครั้งสิ่งนี้ทำให้เกิดสัญลักษณ์แสดงหัวข้อย่อยในคำตอบที่ยอมรับว่า "Don't use register globals" สิ่งนี้บอกถึงสิ่งที่ต้องทำแทน
cmcculloh


5

การใช้ที่อยู่ IP ไม่ใช่ความคิดที่ดีที่สุดในประสบการณ์ของฉัน ตัวอย่างเช่น; สำนักงานของฉันมีที่อยู่ IP สองแห่งที่ถูกใช้โดยขึ้นอยู่กับการโหลดและเราพบปัญหาในการใช้ที่อยู่ IP อยู่ตลอดเวลา

แต่ฉันได้เลือกที่จะจัดเก็บเซสชันในฐานข้อมูลแยกต่างหากสำหรับโดเมนบนเซิร์ฟเวอร์ของฉัน วิธีนี้จะไม่มีใครในระบบไฟล์เข้าถึงข้อมูลเซสชันนั้นได้ สิ่งนี้มีประโยชน์มากกับ phpBB ก่อน 3.0 (พวกเขาได้แก้ไขสิ่งนี้แล้ว) แต่ก็ยังเป็นความคิดที่ดีที่ฉันคิด


3

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

นี่คือบทช่วยสอนที่ดีเกี่ยวกับ setTimer () และ clearTimer ()


3

ปัญหาหลักเกี่ยวกับเซสชัน PHP และความปลอดภัย (นอกเหนือจากการจี้เซสชัน) มาพร้อมกับสภาพแวดล้อมที่คุณอยู่โดยค่าเริ่มต้น PHP จะเก็บข้อมูลเซสชันไว้ในไฟล์ในไดเร็กทอรี temp ของ OS โดยไม่ต้องคิดหรือวางแผนเป็นพิเศษนี่คือไดเร็กทอรีที่สามารถอ่านได้ทั่วโลกดังนั้นข้อมูลเซสชันทั้งหมดของคุณจึงเป็นแบบสาธารณะสำหรับทุกคนที่เข้าถึงเซิร์ฟเวอร์

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

การจัดเก็บเซสชันของคุณเองอาจเป็นประโยชน์หากคุณอยู่บนเซิร์ฟเวอร์ที่ใช้ร่วมกันเนื่องจากจะช่วยให้คุณจัดเก็บไว้ในฐานข้อมูลซึ่งบ่อยครั้งคุณสามารถควบคุมระบบไฟล์ได้มากกว่า


3

ฉันตั้งเซสชันของฉันแบบนี้ -

ในหน้าเข้าสู่ระบบ:

$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR']);

(วลีที่กำหนดในหน้าการกำหนดค่า)

จากนั้นในส่วนหัวที่อยู่ตลอดส่วนที่เหลือของไซต์:

session_start();
if ($_SESSION['fingerprint'] != md5($_SERVER['HTTP_USER_AGENT'] . PHRASE . $_SERVER['REMOTE_ADDR'])) {       
    session_destroy();
    header('Location: http://website login page/');
    exit();     
}

3

php.ini

session.cookie_httponly = 1
change session name from default PHPSESSID

eq Apache เพิ่มส่วนหัว:

X-XSS-Protection    1

httpd.conf -> <FilesMatch "\. (php | phtml | aspx | htm | html) $"> ชุดส่วนหัว X-XSS-Protection "1" </FilesMatch>
user956584

โปรดทราบว่าX-XSS-Protectionไม่มีประโยชน์เลย ในความเป็นจริงอัลกอริทึมการปกป้องนั้นสามารถใช้ประโยชน์ได้จริงทำให้แย่ลงกว่าเดิม
Pacerier

2

ฉันจะตรวจสอบทั้ง IP และ User Agent เพื่อดูว่ามีการเปลี่ยนแปลงหรือไม่

if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
    || $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
    //Something fishy is going on here?
}

5
IP สามารถเปลี่ยนแปลงได้อย่างถูกต้องตามกฎหมายหากผู้ใช้อยู่เบื้องหลังพร็อกซีฟาร์มแบบโหลดบาลานซ์
Kornel

2
และ user_agent สามารถเปลี่ยนแปลงได้ทุกครั้งที่ผู้ใช้อัปเกรดเบราว์เซอร์
scotts

3
@scotts ฉันเห็นด้วยกับส่วน IP แต่สำหรับการอัปเกรดเบราว์เซอร์คุณจะตั้งค่าเซสชันเมื่อเข้าสู่ระบบดังนั้นฉันจึงไม่เห็นว่าพวกเขาจะอัปเกรดเบราว์เซอร์ที่นั่นอย่างไรโดยไม่ต้องสร้างเซสชันใหม่เมื่อเข้าสู่ระบบอีกครั้ง
JasonDavis

ฉันเชื่อว่า user_agent สามารถเปลี่ยนแปลงได้เช่นกันเมื่อสลับระหว่างโหมดที่เข้ากันได้ใน IE8 นอกจากนี้ยังปลอมได้ง่ายมาก

ใช่ แต่สิ่งที่เกี่ยวกับผู้ใช้ที่มี IP eq GSM แบบคงที่และมีการเปลี่ยนแปลงทุกครึ่งชั่วโมง ดังนั้น IP ที่เก็บไว้ใน Session + host name WHEN IP! = REMOTE_ADDR check host และเปรียบเทียบ hostanmes eq 12.12.12.holand.nl-> เมื่อไหร่ที่ holand.nl == จริง แต่โฮสต์บางตัวมีชื่อโฮสต์ตาม IP จากนั้นต้องเปรียบเทียบมาสก์ 88.99.XX.XX
user956584

2

หากคุณใช้session_set_save_handler ()คุณสามารถตั้งค่าตัวจัดการเซสชันของคุณเองได้ ตัวอย่างเช่นคุณสามารถจัดเก็บเซสชันของคุณในฐานข้อมูล อ้างถึงความคิดเห็นของ php.net สำหรับตัวอย่างของตัวจัดการเซสชันฐานข้อมูล

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


2

คุณต้องแน่ใจว่าข้อมูลเซสชันปลอดภัย โดยดูที่ php.ini ของคุณหรือใช้ phpinfo () คุณจะพบการตั้งค่าเซสชันของคุณ _session.save_path_ บอกคุณว่าบันทึกไว้ที่ไหน

ตรวจสอบสิทธิ์ของโฟลเดอร์และของผู้ปกครอง ไม่ควรเป็นสาธารณะ (/ tmp) หรือสามารถเข้าถึงได้โดยเว็บไซต์อื่นบนเซิร์ฟเวอร์ที่ใช้ร่วมกันของคุณ

สมมติว่าคุณยังต้องการใช้เซสชัน php คุณสามารถตั้งค่า php ให้ใช้โฟลเดอร์อื่นได้โดยเปลี่ยน _session.save_path_ หรือบันทึกข้อมูลในฐานข้อมูลโดยเปลี่ยน _session.save_handler_

คุณอาจสามารถตั้งค่า _session.save_path_ ใน php.ini ของคุณ (ผู้ให้บริการบางรายอนุญาต) หรือสำหรับ apache + mod_php ในไฟล์. htaccess ในโฟลเดอร์รูทของไซต์ของคุณ: php_value session.save_path "/home/example.com/html/session"ไฟล์ในโฟลเดอร์รากเว็บไซต์ของคุณ: คุณยังสามารถตั้งค่าในขณะรันได้ด้วย _session_save_path () _

ตรวจสอบบทช่วยสอนของ Chris ShiflettหรือZend_Session_SaveHandler_DbTableเพื่อตั้งค่าและตัวจัดการเซสชันทางเลือก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.