Keamanan Sesi PHP

125

Apa saja pedoman untuk menjaga keamanan sesi yang bertanggung jawab dengan PHP? Ada informasi di seluruh web dan sudah waktunya semuanya mendarat di satu tempat!

saint_groceon
sumber

Jawaban:

88

Ada beberapa hal yang harus dilakukan untuk menjaga keamanan sesi Anda:

  1. Gunakan SSL saat mengautentikasi pengguna atau melakukan operasi sensitif.
  2. Regenerasi id sesi setiap kali tingkat keamanan berubah (seperti masuk). Anda bahkan dapat membuat ulang id sesi setiap permintaan jika Anda mau.
  3. Sesi waktu istirahat
  4. Jangan gunakan register global
  5. Simpan detail autentikasi di server. Artinya, jangan mengirim detail seperti nama pengguna dalam cookie.
  6. Periksa $_SERVER['HTTP_USER_AGENT']. Ini menambah penghalang kecil untuk pembajakan sesi. Anda juga dapat memeriksa alamat IP. Tapi ini menyebabkan masalah bagi pengguna yang mengubah alamat IP karena load balancing pada beberapa koneksi internet dll (yang terjadi di lingkungan kita di sini).
  7. Kunci akses ke sesi pada sistem file atau gunakan penanganan sesi khusus
  8. Untuk operasi sensitif, pertimbangkan untuk mewajibkan pengguna yang masuk untuk memberikan detail autenikasi lagi
grom
sumber
15
Menggunakan SSL hanya untuk beberapa operasi saja tidak cukup, kecuali jika Anda memiliki sesi terpisah untuk lalu lintas terenkripsi dan tidak terenkripsi. Jika Anda menggunakan satu sesi melalui HTTPS dan HTTP, penyerang akan mencurinya atas permintaan non-HTTPS pertama.
Kornel
6
-1 agen pengguna itu sepele untuk spoof. Apa yang Anda gambarkan kode limbah dan bukan sistem keamanan.
benteng
24
@The Rook, itu mungkin merupakan penghalang sepele (penyerang dapat menangkap agen pengguna korban menggunakan situs mereka sendiri) dan mengandalkan keamanan melalui ketidakjelasan tetapi masih merupakan satu penghalang tambahan. Jika HTTP User-Agent berubah selama penggunaan sesi, itu akan sangat mencurigakan dan kemungkinan besar serangan. Saya tidak pernah mengatakan Anda bisa menggunakannya sendiri. Jika Anda menggabungkannya dengan teknik lain, Anda memiliki situs yang jauh lebih aman.
grom
5
@rom, saya pikir itu seperti meletakkan selotip di depan pintu Anda dan mengatakan itu akan mencegah orang-orang membobol masuk.
rook
8
Jika Anda memeriksa agen pengguna, Anda akan memblokir semua permintaan dari pengguna IE8 ketika mereka beralih ke mode kompatibilitas. Lihat kesenangan saya melacak masalah ini dalam kode saya sendiri: serverfault.com/questions/200018/http-302-problem-on-ie7 . Saya mengambil agen pengguna check out, karena itu hal yang sepele untuk menipu, seperti yang orang lain katakan.
bestattendance
15

Satu pedoman adalah memanggil session_regenerate_id setiap kali tingkat keamanan sesi berubah. Ini membantu mencegah pembajakan sesi.

saint_groceon
sumber
11

Dua (atau lebih) sen saya:

  • Tidak percaya siapapun
  • Memfilter input, output melarikan diri (cookie, data sesi adalah input Anda juga)
  • Hindari XSS (pertahankan HTML Anda terbentuk dengan baik, lihat PHPTAL atau HTMLPurifier )
  • Pertahanan secara mendalam
  • Jangan memaparkan data

Ada sebuah buku kecil tapi bagus tentang topik ini: Essential PHP Security oleh Chris Shiflett .

Essential PHP Security http://shiflett.org/images/essential-php-security-small.png

Di halaman beranda buku Anda akan menemukan beberapa contoh kode menarik dan bab-bab sampel.

Anda dapat menggunakan teknik yang disebutkan di atas (IP & UserAgent), yang dijelaskan di sini: Cara menghindari pencurian identitas

takeshin
sumber
+1 untuk pencegahan XSS. Tanpa itu tidak mungkin untuk melindungi terhadap CSRF, dan dengan demikian seseorang dapat "naik" sesi tanpa mendapatkan ID sesi.
Kornel
11

Saya pikir salah satu masalah utama (yang sedang dibahas di PHP 6) adalah register_globals. Saat ini salah satu metode standar yang digunakan untuk menghindari register_globalsadalah menggunakan $_REQUEST, $_GETatau $_POSTarray.

Cara yang "benar" untuk melakukannya (pada 5.2, meskipun ada sedikit buggy di sana, tetapi stabil pada 6, yang akan segera hadir) adalah melalui filter .

Jadi alih-alih:

$username = $_POST["username"];

Anda akan melakukan:

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

atau bahkan hanya:

$username = filter_input(INPUT_POST, 'username');
cmcculloh
sumber
2
Ini tidak ada hubungannya dengan pertanyaan sama sekali.
Pengembang Pixel
5
Betulkah? Lalu mengapa dalam jawaban yang diterima mereka menyebutkan tidak menggunakan register global? Tidakkah, sejauh menyangkut kebanyakan pengembang run-of-the-mill, mendaftarkan global dan membentuk penanganan variabel berada di bawah payung "sesi" bahkan jika itu secara teknis bukan bagian dari objek "sesi"?
cmcculloh
9
Saya setuju, ini tidak sepenuhnya menjawab pertanyaan, tetapi sudah pasti BAGIAN dari jawaban atas pertanyaan. Sekali lagi, ini menghasilkan poin di jawaban yang diterima, "Jangan gunakan register global". Ini memberitahu apa yang harus dilakukan sebagai gantinya.
cmcculloh
5

Menggunakan alamat IP sebenarnya bukan ide terbaik dalam pengalaman saya. Sebagai contoh; kantor saya memiliki dua alamat IP yang digunakan tergantung pada beban dan kami terus mengalami masalah dengan menggunakan alamat IP.

Sebagai gantinya, saya memilih untuk menyimpan sesi dalam database terpisah untuk domain di server saya. Dengan cara ini, tidak ada seorang pun di sistem file yang memiliki akses ke info sesi itu. Ini sangat membantu dengan phpBB sebelum 3.0 (mereka sudah memperbaikinya) tetapi saya kira itu adalah ide yang bagus.

Eric Lamb
sumber
3

Ini cukup sepele dan jelas, tetapi pastikan untuk session_destroy setelah setiap kali digunakan. Ini bisa sulit untuk diterapkan jika pengguna tidak keluar secara eksplisit, sehingga timer dapat diatur untuk melakukan ini.

Berikut ini adalah tutorial yang bagus tentang setTimer () dan clearTimer ().

helloandre
sumber
3

Masalah utama dengan sesi PHP dan keamanan (selain pembajakan sesi) hadir dengan lingkungan tempat Anda berada. Secara default, PHP menyimpan data sesi dalam file di direktori temp OS. Tanpa pemikiran atau perencanaan khusus, ini adalah direktori yang dapat dibaca dunia sehingga semua informasi sesi Anda bersifat publik bagi siapa saja yang memiliki akses ke server.

Adapun untuk mempertahankan sesi melalui beberapa server. Pada titik itu akan lebih baik untuk beralih PHP ke sesi yang ditangani pengguna di mana ia memanggil fungsi yang disediakan untuk CRUD (membuat, membaca, memperbarui, menghapus) data sesi. Pada titik itu Anda dapat menyimpan informasi sesi dalam database atau solusi seperti memcache sehingga semua server aplikasi memiliki akses ke data.

Menyimpan sesi Anda sendiri mungkin juga menguntungkan jika Anda berada di server bersama karena itu akan membiarkan Anda menyimpannya di database yang Anda sering kali memiliki kontrol lebih besar daripada sistem file.

John Downey
sumber
3

Saya mengatur sesi saya seperti ini-

di halaman login:

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

(frasa yang ditentukan pada halaman konfigurasi)

lalu pada tajuk yang ada di seluruh situs:

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

php.ini

session.cookie_httponly = 1
change session name from default PHPSESSID

eq Apache tambahkan tajuk:

X-XSS-Protection    1
pengguna956584
sumber
httpd.conf -> <FilesMatch "\. (php | phtml | aspx | htm | html) $"> Header set X-XSS-Protection "1" </FilesMatch>
user956584
Sadarilah bahwa X-XSS-Protectionitu tidak terlalu berguna sama sekali. Bahkan, algoritma perlindungan itu sendiri sebenarnya bisa dieksploitasi, membuatnya lebih buruk dari sebelumnya.
Pacerier
2

Saya akan memeriksa IP dan User Agent untuk melihat apakah mereka berubah

if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']
    || $_SESSION['user_ip'] != $_SERVER['REMOTE_ADDR'])
{
    //Something fishy is going on here?
}
Teifion
sumber
5
IP dapat secara sah berubah jika pengguna berada di belakang proxy farm yang seimbang.
Kornel
2
Dan user_agent dapat berubah setiap kali pengguna memutakhirkan browser mereka.
scotts
3
@scotts Saya setuju dengan bagian IP tetapi untuk peningkatan browser, Anda akan mengatur sesi ketika mereka login jadi saya tidak melihat bagaimana mereka akan meningkatkan browser di sana tanpa membuat sesi baru setelah mereka login lagi.
JasonDavis
Saya percaya user_agent juga dapat berubah saat beralih antara mode yang kompatibel di IE8. Ini juga sangat mudah untuk dipalsukan.
Yap tetapi bagaimana dengan pengguna yang memiliki IP statis eq GSM dan diubah setiap setengah jam. Jadi, IP yang tersimpan di Sesi + nama host, KETIKA IP! = REMOTE_ADDR periksa host dan bandingkan hostanmes eq. 12.12.12.holand.nl-> kapan holand.nl == benar. Tetapi beberapa host memiliki hostname berbasis IP Kemudian perlu membandingkan mask 88.99.XX.XX
user956584
2

Jika Anda menggunakan session_set_save_handler () Anda dapat mengatur pengendali sesi Anda sendiri. Misalnya Anda bisa menyimpan sesi Anda di database. Lihat komentar php.net untuk contoh-contoh penangan sesi basis data.

Sesi DB juga bagus jika Anda memiliki beberapa server sebaliknya jika Anda menggunakan sesi berbasis file, Anda perlu memastikan bahwa setiap server web memiliki akses ke sistem file yang sama untuk membaca / menulis sesi.

ejunker
sumber
2

Anda harus yakin bahwa data sesi aman. Dengan melihat php.ini Anda atau menggunakan phpinfo (), Anda dapat menemukan pengaturan sesi Anda. _session.save_path_ memberi tahu Anda di mana mereka disimpan.

Periksa izin folder dan orang tuanya. Itu tidak boleh publik (/ tmp) atau dapat diakses oleh situs web lain di server bersama Anda.

Dengan asumsi Anda masih ingin menggunakan sesi php, Anda dapat mengatur php untuk menggunakan folder lain dengan mengubah _session.save_path_ atau menyimpan data dalam database dengan mengubah _session.save_handler_.

Anda mungkin dapat mengatur _session.save_path_ di php.ini Anda (beberapa penyedia memungkinkan) atau untuk apache + mod_php, dalam file .htaccess di folder root situs Anda: php_value session.save_path "/home/example.com/html/session". Anda juga dapat mengaturnya pada saat dijalankan dengan _session_save_path () _.

Lihat tutorial Chris Shiflett atau Zend_Session_SaveHandler_DbTable untuk mengatur dan penangan sesi alternatif.

Dinoboff
sumber