Fiksasi Sesi PHP / Pembajakan

145

Saya mencoba memahami lebih lanjut tentang Fiksasi Sesi PHP & pembajakan dan bagaimana mencegah masalah ini. Saya telah membaca dua artikel berikut di situs web Chris Shiflett:

Namun, saya tidak yakin saya memahami hal-hal dengan benar.

Untuk membantu mencegah fiksasi sesi, cukup menelepon session_regenerate_id (true); setelah berhasil masuk? Saya rasa saya mengerti itu dengan benar.

Dia juga berbicara tentang menggunakan token yang diteruskan dalam url melalui $ _GET untuk mencegah pembajakan sesi. Bagaimana tepatnya ini dilakukan? Saya menduga ketika seseorang login Anda menghasilkan token mereka & menyimpannya dalam variabel sesi, maka pada setiap halaman Anda akan membandingkan variabel sesi itu dengan nilai variabel $ _GET?

Apakah token ini perlu diubah hanya sekali per sesi atau pada setiap memuat halaman?

Juga apakah mereka cara yang baik untuk mencegah pembajakan tanpa harus memberikan nilai tambah dalam url? ini akan jauh lebih mudah.

saya 2
sumber
Mungkin Anda bisa menambahkan tautan ke halaman tempat Anda menemukan rekomendasi ini.
Gumbo

Jawaban:

220

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 = 0dalam php.inifile Anda . Ini akan memberi tahu PHP untuk tidak memasukkan pengenal dalam URL, dan tidak membaca URL untuk pengidentifikasi.

  • Ditetapkan session.use_only_cookies = 1dalam php.inifile 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_functiondi php.ini. Jika PHP <5.3, atur ke session.hash_function = 1SHA1. Jika PHP> = 5.3, atur ke session.hash_function = sha256atau session.hash_function = sha512.

  • Kirim hash yang kuat: session.hash_bits_per_characterdalam 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_filedan session.entropy_lengthdi php.inifile Anda . Tetapkan yang pertama ke session.entropy_file = /dev/urandomdan 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_idsesi 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();
}
ircmaxell
sumber
4
Menggunakan 5 bukannya 4 bit per karakter tidak mengubah "kekuatan" dengan cara apa pun (apa pun "kekuatan" artinya dalam kasus ini). Tetapi meskipun poin Anda disarankan secara umum, mereka tidak memiliki beberapa detail penting. Misalnya apa yang terjadi pada sesi yang terkait dengan ID sesi lama atau bagaimana sesi dengan ID sesi lama harus ditangani setelah tidak valid.
Gumbo
2
@battal: Tidak, itu intinya. session_regenerate_idtidak membatalkan sesi yang masih terkait dengan ID lama; hanya jika parameter delete_old_session disetel ke true, sesi akan dihancurkan. Tetapi bagaimana jika seorang penyerang memulai regenerasi ID ini?
Gumbo
6
Saya tidak setuju dengan regenerasi sesi setiap kali Anda mengubah variabel sesi, itu hanya boleh dilakukan saat masuk / keluar. Juga memeriksa agen-pengguna tidak ada artinya dan memeriksa REMOTE_ADDR bermasalah. Satu hal yang ingin saya tambahkan adalah session.entropy_file = /dev/urandom. Generasi entropi internal PHP terbukti sangat lemah dan kumpulan entropi yang disediakan oleh / dev / random atau / dev / uranom adalah yang terbaik yang bisa Anda dapatkan di server web tanpa rng perangkat keras.
benteng
4
Anda juga harus menambahkan session.cookie_httponlydan session.cookie_secure. Yang pertama membantu menggagalkan xss (tetapi tidak sempurna). Yang ke-2 adalah cara terbaik untuk menghentikan OWASP A9 ...
rook
4
Tidak mengerti jawaban yang begitu bagus tetapi melewatkan bagian yang paling penting: gunakan SSL / HTTPS. Peningkatan tandingan adalah sumber masalah dengan beberapa permintaan dengan cepat setelah satu sama lain, pengguna menyegarkan dua kali halaman atau menekan tombol kirim dua kali. Solusi alamat IP adalah masalah saat ini dengan semua pengguna ponsel dan selalu mengubah IP. Anda bisa melihat set IP pertama, tetapi masih meminta masalah. Best mencegah penemuan id sesi di tempat pertama dan yang menggunakan SSL / HTTPS.
Sanne
37

Kedua serangan sesi memiliki tujuan yang sama: Dapatkan akses ke sesi yang sah dari pengguna lain. Tetapi vektor serangannya berbeda:

  • Dalam serangan Fiksasi Sesi , penyerang sudah memiliki akses ke sesi yang valid dan mencoba untuk memaksa korban untuk menggunakan sesi khusus ini.

  • Dalam Sesi Pembajakan serangan , penyerang mencoba untuk mendapatkan ID sesi korban untuk menggunakan / nya sesinya.

Dalam kedua serangan, ID sesi adalah data sensitif yang menjadi fokus serangan ini. Jadi itu adalah ID sesi yang perlu dilindungi untuk akses baca (Pembajakan Sesi) dan akses tulis (Perbaikan Sesi).

Aturan umum melindungi data sensitif dengan menggunakan HTTPS juga berlaku dalam kasus ini. Selain itu, Anda harus melakukan hal berikut:

Untuk mencegah serangan Sesi Fiksasi , pastikan bahwa:

Untuk mencegah serangan Pembajakan Sesi , pastikan bahwa:

Untuk mencegah kedua serangan sesi, pastikan bahwa:

  • untuk hanya menerima sesi yang telah dimulai aplikasi Anda. Anda dapat melakukan ini dengan sidik jari pada sesi inisiasi dengan informasi spesifik klien. Anda dapat menggunakan ID Pengguna-Agen tetapi tidak menggunakan alamat IP jarak jauh atau informasi lain yang mungkin berubah dari antara permintaan.
  • untuk mengubah ID sesi menggunakan session_regenerate_id(true)setelah upaya otentikasi ( truehanya pada keberhasilan) atau perubahan hak istimewa dan menghancurkan sesi lama. (Pastikan untuk menyimpan perubahan $_SESSIONpenggunaan session_write_close sebelum membuat kembali ID jika Anda ingin mempertahankan sesi yang terkait dengan ID lama; jika tidak hanya sesi dengan ID baru yang akan terpengaruh oleh perubahan itu.)
  • untuk menggunakan implementasi kedaluwarsa sesi yang tepat (lihat Bagaimana cara saya mengakhiri sesi PHP setelah 30 menit? ).
Gumbo
sumber
Pos yang luar biasa, terutama bagian terakhir.
Mattis
6

Token yang Anda sebutkan adalah "nonce" - nomor yang digunakan satu kali. Mereka tidak harus digunakan hanya sekali, tetapi semakin lama digunakan, semakin tinggi peluang bahwace dapat ditangkap dan digunakan untuk membajak sesi.

Kelemahan lain untuk nonces adalah sangat sulit untuk membangun sistem yang menggunakannya dan memungkinkan beberapa jendela paralel pada bentuk yang sama. mis. pengguna membuka dua jendela di forum, dan mulai mengerjakan dua posting:

window 'A' loads first and gets nonce 'P'
window 'B' loads second and gets nonce 'Q'

Jika Anda tidak memiliki cara untuk melacak beberapa jendela, Anda hanya akan menyimpan satu jendela - jendela B / Q. Ketika pengguna kemudian mengirimkan posting mereka dari jendela A dan melewati di 'P', sistem akan menolak posting sebagai P != Q.

Marc B
sumber
Jadi apa hubungannya ini dengan fiksasi sesi?
bangun
2
Dia memiliki poin yang valid terutama di bidang menggunakan banyak permintaan AJAX secara bersamaan.
DanielG
2

Saya tidak membaca artikel Shiflett, tetapi saya pikir Anda telah salah mengerti sesuatu.

Secara default, PHP memberikan token sesi di URL setiap kali klien tidak menerima cookie. Sebaliknya dalam kasus yang paling umum token sesi disimpan sebagai cookie.

Ini berarti bahwa jika Anda meletakkan token sesi di URL, PHP akan mengenalinya dan mencoba menggunakannya selanjutnya. Fiksasi sesi terjadi ketika seseorang membuat sesi dan kemudian menipu pengguna lain untuk berbagi sesi yang sama dengan membuka URL yang berisi token sesi. Jika pengguna mengautentikasi dengan cara tertentu, pengguna yang jahat kemudian mengetahui token sesi sesi yang diautentikasi, yang mungkin memiliki hak istimewa berbeda.

Seperti yang saya yakin Shiflett menjelaskan, hal yang biasa dilakukan adalah membuat kembali token yang berbeda setiap kali hak pengguna berubah.

Andrea
sumber
Untuk menambah ini, harap pastikan untuk menghancurkan sesi yang sebelumnya dibuka karena masih akan valid dengan izin pengguna yang ada.
corrodedmonkee
0

Ya, Anda dapat mencegah fiksasi sesi dengan membuat ulang id sesi sekali saat masuk. Dengan cara ini jika penyerang tidak akan tahu nilai cookie dari sesi yang baru diautentikasi. Pendekatan lain yang benar-benar menghentikan masalah diatur session.use_only_cookies=Truedalam konfigurasi runtime Anda. Seorang penyerang tidak dapat menetapkan nilai cookie dalam konteks domain lain. Fiksasi sesi bergantung pada pengiriman nilai cookie sebagai GET atau POST.

benteng
sumber