Apa cara terbaik untuk mencegah pembajakan sesi?

124

Secara khusus ini berkaitan dengan saat menggunakan cookie sesi klien untuk mengidentifikasi sesi di server.

Apakah jawaban terbaik untuk menggunakan enkripsi SSL / HTTPS untuk seluruh situs web, dan Anda memiliki jaminan terbaik bahwa tidak ada orang di tengah serangan yang dapat mengendus cookie sesi klien yang ada?

Dan mungkin yang terbaik kedua untuk menggunakan semacam enkripsi pada nilai sesi itu sendiri yang disimpan di cookie sesi Anda?

Jika pengguna jahat memiliki akses fisik ke mesin, mereka masih dapat melihat sistem file untuk mengambil cookie sesi yang valid dan menggunakannya untuk membajak sesi?

Adam
sumber

Jawaban:

140

Mengenkripsi nilai sesi akan memiliki efek nol. Cookie sesi sudah menjadi nilai arbitrer, mengenkripsinya hanya akan menghasilkan nilai arbitrer lain yang dapat diendus.

Satu-satunya solusi nyata adalah HTTPS. Jika Anda tidak ingin melakukan SSL di seluruh situs Anda (mungkin Anda memiliki masalah kinerja), Anda mungkin bisa lolos hanya dengan SSL yang melindungi area sensitif. Untuk melakukan itu, pertama-tama pastikan halaman login Anda adalah HTTPS. Saat pengguna masuk, tetapkan cookie aman (artinya browser hanya akan mengirimkannya melalui tautan SSL) selain cookie sesi biasa. Kemudian, saat pengguna mengunjungi salah satu area "sensitif" Anda, alihkan mereka ke HTTPS, dan periksa keberadaan cookie aman tersebut. Pengguna sungguhan akan memilikinya, pembajak sesi tidak akan memilikinya.

EDIT : Jawaban ini awalnya ditulis pada tahun 2008. Sekarang 2016, dan tidak ada alasan untuk tidak memiliki SSL di seluruh situs Anda. Tidak ada lagi HTTP teks biasa!

Josh Hinman
sumber
28
HTTPS hanya akan mencegah mengendus. Tetapi jika Anda memiliki XSS, atau ID sesi dapat ditebak dengan mudah, atau Anda rentan terhadap fiksasi sesi, atau penyimpanan ID sesi Anda lemah (injeksi SQL?), SSL tidak akan ada peningkatan sama sekali.
Calimo
5
@Josh Jika pengguna jahat memiliki akses fisik ke mesin, mereka masih dapat melihat sistem file untuk mengambil cookie sesi yang valid dan menggunakannya untuk membajak sesi?
Pacerier
72
Jika pengguna jahat memiliki akses fisik ke sistem file, mereka tidak perlu membajak sesi.
Josh Hinman
25
@Josh. Tidak benar, terkadang pengguna memiliki waktu terbatas untuk mengakses sistem file. Bayangkan sebuah laptop dibiarkan tidak terkunci oleh seorang rekan yang bergegas ke toilet, sekarang yang perlu saya lakukan hanyalah pergi ke laptop itu, instal plugin EditThisCookie, ambil cookie-nya di plus.google.com menggunakan fitur ekspor EditThisCookie dan sekarang saya memiliki akunnya . Waktu yang dibutuhkan: 18 detik.
Pacerier
1
Saya cukup yakin Google akan memiliki semacam fitur keamanan
bawaan
42

SSL hanya membantu dengan serangan sniffing. Jika penyerang memiliki akses ke mesin Anda, saya akan berasumsi bahwa mereka juga dapat menyalin cookie aman Anda.

Setidaknya, pastikan cookie lama kehilangan nilainya setelah beberapa saat. Bahkan serangan pembajakan yang berhasil akan digagalkan ketika cookie berhenti bekerja. Jika pengguna memiliki cookie dari sesi yang masuk lebih dari sebulan yang lalu, buat mereka memasukkan kembali sandi mereka. Pastikan bahwa setiap kali pengguna mengklik link "log out" situs Anda, bahwa UUID sesi lama tidak akan pernah dapat digunakan lagi.

Saya tidak yakin apakah ide ini akan berhasil tetapi begini: Tambahkan nomor seri ke cookie sesi Anda, mungkin string seperti ini:

SessionUUID, Serial Num, Tanggal / Waktu Sekarang

Enkripsi string ini dan gunakan sebagai cookie sesi Anda. Ubah nomor seri secara teratur - mungkin saat cookie berumur 5 menit dan kemudian terbitkan ulang cookie. Anda bahkan dapat menerbitkannya kembali di setiap tampilan halaman jika Anda mau. Di sisi server, simpan catatan nomor seri terakhir yang Anda keluarkan untuk sesi itu. Jika seseorang pernah mengirim cookie dengan nomor seri yang salah itu berarti penyerang mungkin menggunakan cookie yang mereka intersep sebelumnya sehingga membatalkan sesi UUID dan meminta pengguna untuk memasukkan kembali kata sandi mereka dan kemudian menerbitkan kembali cookie baru.

Ingatlah bahwa pengguna Anda mungkin memiliki lebih dari satu komputer sehingga mereka mungkin memiliki lebih dari satu sesi aktif. Jangan melakukan sesuatu yang memaksa mereka untuk masuk lagi setiap kali mereka berpindah antar komputer.


sumber
Saya tahu ini adalah posting lama, tetapi hanya ingin memasukkan bahwa jika penyerang membajak sesi dalam jendela yang dialokasikan oleh "nomor seri" maka ini tidak akan mempengaruhinya.
hancurkan
@ Crush, tapi kemudian penyerang akan dikunci setelah jendela yang ditentukan, bukan? Jadi paling tidak jendela serangannya kecil (er).
Johanneke
2
Satu-satunya masalah adalah jika pengguna meninggalkan situs web Anda selama 5 menit, mereka harus masuk lagi
elipoultorak
21

Pernahkah Anda mempertimbangkan untuk membaca buku tentang keamanan PHP? Sangat dianjurkan.

Saya telah banyak berhasil dengan metode berikut untuk situs yang tidak bersertifikat SSL.

  1. Larang beberapa sesi dalam akun yang sama, pastikan Anda tidak memeriksa ini hanya berdasarkan alamat IP. Melainkan memeriksa dengan token yang dihasilkan saat login yang disimpan dengan sesi pengguna di database, serta alamat IP, HTTP_USER_AGENT, dan sebagainya

  2. Menggunakan hyperlink berbasis Relasi Menghasilkan tautan (mis. Http://example.com/secure.php?token=2349df98sdf98a9asdf8fas98df8 ) Tautan ditambahkan dengan string MD5 asin acak x-BYTE (ukuran yang lebih disukai), setelah pengalihan halaman dibuat secara acak token sesuai dengan halaman yang diminta.

    • Setelah memuat ulang, beberapa pemeriksaan dilakukan.
    • Alamat IP Asal
    • HTTP_USER_AGENT
    • Token Sesi
    • Anda mengerti maksudnya.
  3. Cookie otentikasi sesi seumur hidup. Seperti yang diposting di atas, cookie yang berisi string aman, yang merupakan salah satu referensi langsung ke validitas sesi adalah ide yang bagus. Buat itu kedaluwarsa setiap x Menit, terbitkan ulang token itu, dan sinkronkan kembali sesi dengan Data baru. Jika ada kesalahan kecocokan dalam data, logout pengguna, atau minta mereka mengautentikasi ulang sesi mereka.

Saya sama sekali bukan ahli dalam hal ini, saya memiliki sedikit pengalaman dalam topik khusus ini, semoga beberapa di antaranya dapat membantu siapa pun di luar sana.

Nathan
sumber
4
Apakah ada buku yang akan Anda rekomendasikan?
Rikki
1
Terutama mengingat bahwa OP tidak menyatakan apa pun tentang PHP secara khusus, saya akan mengatakan bahwa lebih baik melihat hanya buku keamanan umum (terutama karena keamanan antara bahasa yang berbeda hanya berbeda dalam detail implementasi, tetapi konsepnya tetap sama).
matts1
pada tahun 2017, bahkan facebook / gmail dll. mengizinkan banyak sesi di bawah akun yang sama (terutama dengan perangkat seluler) kecuali Anda membenci pengguna Anda, # 1 agak ketinggalan jaman.
cowbert
20
// Collect this information on every request
$aip = $_SERVER['REMOTE_ADDR'];
$bip = $_SERVER['HTTP_X_FORWARDED_FOR'];
$agent = $_SERVER['HTTP_USER_AGENT'];
session_start();

// Do this each time the user successfully logs in.
$_SESSION['ident'] = hash("sha256", $aip . $bip . $agent);

// Do this every time the client makes a request to the server, after authenticating
$ident = hash("sha256", $aip . $bip . $agent);
if ($ident != $_SESSION['ident'])
{
    end_session();
    header("Location: login.php");
    // add some fancy pants GET/POST var headers for login.php, that lets you
    // know in the login page to notify the user of why they're being challenged
    // for login again, etc.
}

Apa yang dilakukannya adalah menangkap informasi 'kontekstual' tentang sesi pengguna, potongan informasi yang seharusnya tidak berubah selama masa aktif satu sesi. Seorang pengguna tidak akan berada di depan komputer di AS dan di China pada saat yang bersamaan, bukan? Jadi, jika alamat IP tiba-tiba berubah dalam sesi yang sama yang sangat menyiratkan upaya pembajakan sesi, jadi Anda mengamankan sesi dengan mengakhiri sesi dan memaksa pengguna untuk mengautentikasi ulang. Ini menggagalkan upaya peretasan, penyerang juga dipaksa untuk masuk alih-alih mendapatkan akses ke sesi. Beri tahu pengguna tentang upaya tersebut (ajax sedikit), dan vola, Pengguna yang diberi tahu + sedikit jengkel dan sesi / informasi mereka dilindungi.

Kami memasukkan Agen Pengguna dan X-FORWARDED-FOR untuk melakukan yang terbaik untuk menangkap keunikan sesi untuk sistem di belakang proxy / jaringan. Anda mungkin dapat menggunakan lebih banyak informasi daripada itu, merasa bebas untuk menjadi kreatif.

Ini tidak 100%, tapi sangat efektif.

Masih ada lagi yang dapat Anda lakukan untuk melindungi sesi, kedaluwarsa, ketika pengguna meninggalkan situs web dan kembali memaksa mereka untuk masuk lagi mungkin. Anda dapat mendeteksi pengguna yang keluar dan kembali dengan mengambil HTTP_REFERER kosong (domain diketik di bilah URL), atau periksa apakah nilai di HTTP_REFERER sama dengan domain Anda atau tidak (pengguna mengeklik tautan eksternal / dibuat untuk membuka situs).

Kedaluwarsa sesi, jangan biarkan sesi tetap valid tanpa batas.

Jangan bergantung pada cookie, cookie dapat dicuri, itu salah satu vektor serangan untuk pembajakan sesi.

mereka
sumber
3
Saya pernah mengalami situasi sebelumnya di mana ISP tertentu (cukup besar, tetapi secara teknis terbelakang) akan mengubah IP browser pengguna dari waktu ke waktu berdasarkan perutean ulang koneksi pengguna mereka. Ini membuat pemeriksaan REMOTE_ADDR mengembalikan negatif palsu untuk kami.
goofballLogic
Mengapa repot-repot membuat hash? $_SESSION['ident'] = $aip . $bip . $agent;akan sama amannya.
Dan Bray
2
Jika Anda memiliki pengguna Seluler yang menggunakan situs web Anda saat dalam perjalanan dan berpindah dari satu titik akses ke titik akses lainnya, IP mereka akan terus berubah dan mereka akan terus keluar dari akun mereka.
Kareem
Bagaimana dengan proxy dan VPN? Siapapun yang menggunakan proxy TOR akan terus-menerus keluar dari akun mereka .. faktanya setiap beberapa menit.
Bradley
Bahkan jika Anda mengabaikannya, alamat IP dapat dimanipulasi oleh klien, jadi ini tidak akan banyak membantu penyerang.
Bradley
9

Coba protokol Secure Cookie yang dijelaskan dalam makalah ini oleh Liu, Kovacs, Huang, dan Gouda:

Sebagaimana tercantum dalam dokumen:

Protokol cookie aman yang berjalan antara klien dan server perlu menyediakan empat layanan berikut: otentikasi, kerahasiaan, integritas, dan anti-replay.

Adapun kemudahan penerapan:

Dalam hal efisiensi, protokol kami tidak melibatkan pencarian database atau kriptografi kunci publik. Dalam hal penerapan, protokol kami dapat dengan mudah diterapkan di server web yang ada, dan tidak memerlukan perubahan apa pun pada spesifikasi cookie Internet.

Singkatnya: ini aman, ringan, bekerja dengan baik untuk saya.

Hubert
sumber
9
Tautan Anda adalah spesifikasi protokol - apakah Anda memiliki tautan ke implementasi? Itu akan bagus - terima kasih.
Adam
9

Tidak ada cara untuk mencegah pembajakan sesi 100%, tetapi dengan beberapa pendekatan kita dapat mengurangi waktu bagi penyerang untuk membajak sesi.

Metode untuk mencegah pembajakan sesi:

1 - selalu gunakan sesi dengan sertifikat ssl;

2 - kirim cookie sesi hanya dengan httponly disetel ke true (mencegah javascript untuk mengakses cookie sesi)

2 - gunakan sesi regenerasi id saat login dan logout (catatan: jangan gunakan sesi regenerasi pada setiap permintaan karena jika Anda memiliki permintaan ajax berturut-turut maka Anda memiliki kesempatan untuk membuat beberapa sesi.)

3 - atur batas waktu sesi

4 - simpan agen pengguna browser dalam variabel $ _SESSION dan bandingkan dengan $ _SERVER ['HTTP_USER_AGENT'] di setiap permintaan

5 - tetapkan token cookie, dan setel waktu kedaluwarsa cookie itu ke 0 (hingga browser ditutup). Buat kembali nilai cookie untuk setiap permintaan. (Untuk permintaan ajax jangan membuat ulang cookie token). EX:

    //set a token cookie if one not exist
    if(!isset($_COOKIE['user_token'])){
                    //generate a random string for cookie value
        $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

        //set a session variable with that random string
        $_SESSION['user_token'] = $cookie_token;
        //set cookie with rand value
        setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
    }

    //set a sesison variable with request of www.example.com
    if(!isset($_SESSION['request'])){
        $_SESSION['request'] = -1;
    }
    //increment $_SESSION['request'] with 1 for each request at www.example.com
    $_SESSION['request']++;

    //verify if $_SESSION['user_token'] it's equal with $_COOKIE['user_token'] only for $_SESSION['request'] > 0
    if($_SESSION['request'] > 0){

        // if it's equal then regenerete value of token cookie if not then destroy_session
        if($_SESSION['user_token'] === $_COOKIE['user_token']){
            $cookie_token = bin2hex(mcrypt_create_iv('16' , MCRYPT_DEV_URANDOM));

            $_SESSION['user_token'] = $cookie_token;

            setcookie('user_token', $cookie_token , 0 , '/' , 'donategame.com' , true , true);
        }else{
            //code for session_destroy
        }

    }

            //prevent session hijaking with browser user agent
    if(!isset($_SESSION['user_agent'])){
        $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
    }

    if($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']){
      die('session hijaking - user agent');
    }

catatan: jangan membuat ulang cookie token dengan permintaan ajax catatan: kode di atas adalah contoh. catatan: jika pengguna logout maka token cookie harus dihancurkan serta sesi

6 - Ini bukan pendekatan yang baik untuk menggunakan ip pengguna untuk mencegah pembajakan sesi karena beberapa ip pengguna berubah dengan setiap permintaan. YANG MEMPENGARUHI PENGGUNA YANG VALID

7 - secara pribadi saya menyimpan data sesi dalam database, terserah Anda metode apa yang Anda adopsi

Jika Anda menemukan kesalahan dalam pendekatan saya, mohon perbaiki saya. Jika Anda memiliki lebih banyak cara untuk mencegah sesi hyjaking tolong beri tahu saya.

Alexandru
sumber
hai, im mencoba untuk mencegah pembajakan sesi (di ASP.NET) dan mempertimbangkan semua langkah di atas yang disarankan u. Ini adalah perkiraan bekerja tetapi ketika saya menggunakan mode InPrivateBrowsing / penyamaran pada browser sesi dibajak. Bisakah Anda menyarankan hal tambahan untuk ditambahkan dalam string sessionId?
Vishwanath Mishra
4

Pastikan Anda tidak menggunakan integer incremting untuk ID sesi. Jauh lebih baik menggunakan GUID, atau string karakter panjang yang dibuat secara acak.

Kibbee
sumber
3

Ada banyak cara untuk membuat perlindungan terhadap pembajakan sesi, namun semuanya mengurangi kepuasan pengguna atau tidak aman.

  • Pemeriksaan IP dan / atau X-FORWARDED-FOR. Ini berfungsi, dan cukup aman ... tapi bayangkan penderitaan pengguna. Mereka datang ke kantor dengan WiFi, mereka mendapatkan alamat IP baru dan kehilangan sesi. Harus masuk lagi.

  • Cek Agen Pengguna. Sama seperti di atas, versi baru browser keluar, dan Anda kehilangan satu sesi. Selain itu, ini sangat mudah untuk "diretas". Sangat mudah bagi peretas untuk mengirim string UA palsu.

  • token localStorage. Saat log-on, buat token, simpan di penyimpanan browser, dan simpan ke cookie terenkripsi (dienkripsi di sisi server). Ini tidak memiliki efek samping bagi pengguna (Penyimpanan lokal tetap ada melalui peningkatan browser). Ini tidak seaman - karena hanya keamanan melalui ketidakjelasan. Selain itu, Anda dapat menambahkan beberapa logika (enkripsi / dekripsi) ke JS untuk lebih mengaburkannya.

  • Penerbitan ulang cookie. Ini mungkin cara yang tepat untuk melakukannya. Triknya adalah dengan hanya mengizinkan satu klien untuk menggunakan cookie pada satu waktu. Jadi, pengguna aktif akan mendapatkan cookie yang diterbitkan ulang setiap jam atau kurang. Cookie lama tidak valid jika cookie baru dikeluarkan. Peretasan masih mungkin dilakukan, tetapi jauh lebih sulit untuk dilakukan - baik peretas maupun pengguna yang valid akan mendapatkan akses ditolak.

Menetas
sumber
1

Mari kita pertimbangkan bahwa selama fase login klien dan server dapat menyetujui nilai garam rahasia. Setelah itu server memberikan nilai hitungan dengan setiap pembaruan dan mengharapkan klien untuk merespons dengan hash (garam rahasia + hitungan). Pembajak potensial tidak memiliki cara apa pun untuk mendapatkan nilai garam rahasia ini dan karenanya tidak dapat menghasilkan hash berikutnya.

davej
sumber
3
Tapi bagaimana Anda ingin menyimpan garam ini di sisi klien sehingga tidak ada yang bisa mencurinya?
Dcortez
1

AFAIK objek sesi tidak dapat diakses di klien, karena disimpan di server web. Namun, id sesi disimpan sebagai Cookie dan memungkinkan server web melacak sesi pengguna.

Untuk mencegah pembajakan sesi menggunakan id sesi, Anda dapat menyimpan string hash di dalam objek sesi, dibuat dengan menggunakan kombinasi dua atribut, addr jarak jauh dan port jarak jauh, yang dapat diakses di server web di dalam objek permintaan. Atribut ini mengikat sesi pengguna ke browser tempat pengguna masuk.

Jika pengguna masuk dari browser lain atau mode penyamaran di sistem yang sama, alamat IP akan tetap sama, tetapi porta akan berbeda. Oleh karena itu, ketika aplikasi diakses, pengguna akan diberikan ID sesi yang berbeda oleh server web.

Di bawah ini adalah kode yang telah saya implementasikan dan uji dengan menyalin id sesi dari satu sesi ke sesi lainnya. Ini bekerja dengan cukup baik. Jika ada celah, beri tahu saya cara Anda mensimulasikannya.

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    HttpSession session = request.getSession();
    String sessionKey = (String) session.getAttribute("sessionkey");
    String remoteAddr = request.getRemoteAddr();
    int remotePort = request.getRemotePort();
    String sha256Hex = DigestUtils.sha256Hex(remoteAddr + remotePort);
    if (sessionKey == null || sessionKey.isEmpty()) {
        session.setAttribute("sessionkey", sha256Hex);
        // save mapping to memory to track which user attempted
        Application.userSessionMap.put(sha256Hex, remoteAddr + remotePort);
    } else if (!sha256Hex.equals(sessionKey)) {
        session.invalidate();
        response.getWriter().append(Application.userSessionMap.get(sessionKey));
        response.getWriter().append(" attempted to hijack session id ").append(request.getRequestedSessionId()); 
        response.getWriter().append("of user ").append(Application.userSessionMap.get(sha256Hex));
        return;
    }
    response.getWriter().append("Valid Session\n");
}

Saya menggunakan algoritma SHA-2 untuk melakukan hash nilai menggunakan contoh yang diberikan di SHA-256 Hashing di baeldung

Menantikan komentar Anda.

Jzf
sumber
@zaph Maaf, tapi saya tidak menambahkan jawaban untuk mendapatkan reputasi. Intinya juga bukan enkripsi SHA-2. Tetapi fakta bahwa saya dapat mendeteksi penggunaan Cookie id sesi pengguna lain ke sesi pengguna lain, yaitu pembajakan sesi seperti pada pertanyaan awal. Saya menguji solusi saya dan ternyata berhasil. Tetapi saya bukan ahli dalam hal ini, jadi saya ingin komunitas memeriksa apakah jawaban saya cukup baik. Mungkin Anda dapat melihat apa yang dilakukan cuplikan kode saya dan memutuskan apakah itu menjawab pertanyaan. Terima kasih!
Jzf
@zaph Terima kasih telah menunjukkan kesalahannya. Saya telah memperbarui jawaban saya sesuai saran Anda. Harap hapus suara tidak suka Anda jika menurut Anda jawabannya membantu.
Jzf
0

Untuk mengurangi risiko, Anda juga dapat mengaitkan IP asal dengan sesi. Dengan cara itu, penyerang harus berada dalam jaringan pribadi yang sama untuk dapat menggunakan sesi tersebut.

Memeriksa tajuk rujukan juga bisa menjadi opsi tetapi lebih mudah dipalsukan.

Julio César
sumber
7
tidak, Anda tidak dapat menggunakan IP asal, karena dapat berubah - baik melalui IP dinamis, berubah saat pengguna terputus untuk sementara, atau melalui penggunaan (implisit atau eksplisit) dari proxy farm. Selain itu, pembajak sesi yang berasal dari ISP yang sama dapat menggunakan proxy & IP yang sama sebagai pengguna yang sah ...
Olaf Kock
1
PHP-Nuke memiliki halaman yang bagus tentang pendekatan sesi mereka, dan mereka berbicara secara rinci tentang bagaimana menghubungkannya ke IP tidak bekerja dengan semua ISP phpnuke.org/…
Sembiance
4
Mengubah Ip sangat umum dengan penyedia internet seluler. Dengan Vodafone, IP saya berubah dengan SETIAP permintaan.
Blaise
1
Agak dari posting lama tapi untuk melanjutkan ini. IP seperti yang disebutkan adalah ide yang buruk. Seperti yang disebutkan, pengguna seluler cenderung menjelajah IP. Beberapa ISP di masa lalu juga memiliki IP roaming (seperti AOL) namun pendekatan ini menjadi lebih populer sekarang dengan kekurangan IP IPv4. ISP tersebut termasuk Plus net dan BT
Peter
-15

Lindungi oleh:

$ip=$_SERVER['REMOTE_ADDER'];
$_SESSEION['ip']=$ip;
Nima
sumber
12
Saya gagal untuk melihat apa yang Anda lakukan di sini.
samayo