Ok, ada dua masalah yang terpisah tetapi terkait, dan masing-masing ditangani secara berbeda.
Fiksasi Sesi
Di sinilah penyerang secara eksplisit menetapkan pengidentifikasi sesi untuk pengguna. Biasanya dalam PHP itu dilakukan dengan memberi mereka semacam url http://www.example.com/index...?session_name=sessionid
. Setelah penyerang memberikan url kepada klien, serangan itu sama dengan sesi serangan pembajakan.
Ada beberapa cara untuk mencegah fiksasi sesi (lakukan semuanya):
Ditetapkan session.use_trans_sid = 0
dalam php.ini
file Anda . Ini akan memberi tahu PHP untuk tidak memasukkan pengenal dalam URL, dan tidak membaca URL untuk pengidentifikasi.
Ditetapkan session.use_only_cookies = 1
dalam php.ini
file Anda . Ini akan memberitahu PHP untuk tidak pernah menggunakan URL dengan pengidentifikasi sesi.
Regenerasi ID sesi kapan saja status sesi berubah. Itu berarti salah satu dari yang berikut:
- Otentikasi pengguna
- Menyimpan info sensitif dalam sesi ini
- Mengubah apa pun tentang sesi ini
- dll ...
Pembajakan Sesi
Di sinilah penyerang memegang pengidentifikasi sesi dan dapat mengirim permintaan seolah-olah mereka pengguna itu. Itu berarti bahwa karena penyerang memiliki pengidentifikasi, mereka semua tidak dapat dibedakan dari pengguna yang valid sehubungan dengan server.
Anda tidak dapat secara langsung mencegah pembajakan sesi. Namun Anda dapat melakukan langkah-langkah untuk membuatnya sangat sulit dan sulit untuk digunakan.
Gunakan pengidentifikasi hash sesi yang kuat: session.hash_function
di php.ini
. Jika PHP <5.3, atur ke session.hash_function = 1
SHA1. Jika PHP> = 5.3, atur ke session.hash_function = sha256
atau session.hash_function = sha512
.
Kirim hash yang kuat: session.hash_bits_per_character
dalam php.ini
. Setel ini menjadi session.hash_bits_per_character = 5
. Meskipun ini tidak membuat lebih sulit untuk retak, itu membuat perbedaan ketika penyerang mencoba menebak pengidentifikasi sesi. ID akan lebih pendek, tetapi menggunakan lebih banyak karakter.
Atur entropi tambahan dengan session.entropy_file
dan session.entropy_length
di php.ini
file Anda . Tetapkan yang pertama ke session.entropy_file = /dev/urandom
dan yang terakhir ke jumlah byte yang akan dibaca dari file entropi, misalnya session.entropy_length = 256
.
Ubah nama sesi dari PHPSESSID default. Ini dilakukan dengan memanggil session_name()
nama pengenal Anda sendiri sebagai parameter pertama sebelum menelepon session_start
.
Jika Anda benar - benar paranoid, Anda dapat memutar nama sesi juga, tetapi berhati-hatilah karena semua sesi secara otomatis akan batal jika Anda mengubah ini (misalnya, jika Anda membuatnya tergantung pada waktu). Tetapi tergantung pada kasus penggunaan Anda, itu mungkin pilihan ...
Putar pengidentifikasi sesi Anda sesering mungkin. Saya tidak akan melakukan ini setiap permintaan (kecuali Anda benar - benar membutuhkan tingkat keamanan itu), tetapi secara acak. Anda ingin sering mengubahnya karena jika seorang penyerang membajak suatu sesi, Anda tidak ingin mereka terlalu lama menggunakannya.
Sertakan agen pengguna dari$_SERVER['HTTP_USER_AGENT']
dalam sesi. Pada dasarnya, ketika sesi dimulai, simpan dalam sesuatu seperti $_SESSION['user_agent']
. Kemudian, pada setiap permintaan berikutnya periksa apakah itu cocok. Perhatikan bahwa ini bisa dipalsukan sehingga tidak 100% andal, tetapi lebih baik daripada tidak.
Masukkan alamat IP pengguna dari$_SERVER['REMOTE_ADDR']
dalam sesi. Pada dasarnya, ketika sesi dimulai, simpan dalam sesuatu seperti $_SESSION['remote_ip']
. Ini mungkin bermasalah dari beberapa ISP yang menggunakan beberapa alamat IP untuk penggunanya (seperti AOL dulu). Tetapi jika Anda menggunakannya, itu akan jauh lebih aman. Satu-satunya cara bagi penyerang untuk memalsukan alamat IP adalah dengan kompromi jaringan di beberapa titik antara pengguna yang sebenarnya dan Anda. Dan jika mereka membahayakan jaringan, mereka dapat melakukan jauh lebih buruk daripada pembajakan (seperti serangan MITM, dll).
Sertakan token di sesi dan di sisi browser yang sering Anda tambahkan dan bandingkan. Pada dasarnya, untuk setiap permintaan lakukan $_SESSION['counter']++
di sisi server. Juga lakukan sesuatu di JS di sisi browser untuk melakukan hal yang sama (menggunakan penyimpanan lokal). Kemudian, ketika Anda mengirim permintaan, cukup ambil satu dari satu token, dan verifikasi bahwa nonce itu sama di server. Dengan melakukan ini, Anda harus dapat mendeteksi sesi yang dibajak karena penyerang tidak akan memiliki penghitung yang tepat, atau jika mereka melakukannya, Anda akan memiliki 2 sistem yang mentransmisikan jumlah yang sama dan dapat mengatakan bahwa ada yang dipalsukan. Ini tidak akan berfungsi untuk semua aplikasi, tetapi merupakan salah satu cara untuk mengatasi masalah tersebut.
Sebuah catatan pada keduanya
Perbedaan antara Sesi Fiksasi dan Pembajakan hanya tentang bagaimana pengidentifikasi sesi dikompromikan. Dalam fiksasi, pengidentifikasi diatur ke nilai yang diketahui penyerang sebelumnya. Di Hijacking itu bisa ditebak atau dicuri dari pengguna. Kalau tidak, efek keduanya sama setelah pengidentifikasi dikompromikan.
Regenerasi ID Sesi
Setiap kali Anda membuat ulang pengidentifikasi sesi menggunakan session_regenerate_id
sesi lama harus dihapus. Ini terjadi secara transparan dengan pengendali sesi inti. Namun beberapa penangan sesi kustom menggunakansession_set_save_handler()
tidak melakukan ini dan terbuka untuk menyerang pengidentifikasi sesi lama. Pastikan bahwa jika Anda menggunakan pengendali sesi khusus, Anda melacak pengenal yang Anda buka, dan jika itu tidak sama dengan yang Anda simpan yang Anda hapus secara eksplisit (atau ubah) pengenal pada yang lama.
Menggunakan pengendali sesi default, Anda baik-baik saja hanya dengan menelepon session_regenerate_id(true)
. Itu akan menghapus informasi sesi lama untuk Anda. ID lama tidak lagi valid dan akan menyebabkan sesi baru dibuat jika penyerang (atau orang lain dalam hal ini) mencoba menggunakannya. Berhati-hatilah dengan penangan sesi khusus ....
Menghancurkan Sesi
Jika Anda akan menghancurkan suatu sesi (misalnya saat logout), pastikan Anda menghancurkannya secara menyeluruh. Ini termasuk membatalkan cookie. Menggunakan session_destroy
:
function destroySession() {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
session_destroy();
}