Bagaimana jika JWT dicuri?

201

Saya mencoba menerapkan otentikasi tanpa kewarganegaraan dengan JWT untuk API SISA saya.

AFAIK, JWT pada dasarnya adalah string terenkripsi yang dilewatkan sebagai header HTTP selama panggilan REST.

Tapi bagaimana jika ada penyadap yang melihat permintaan dan mencuri token ? Lalu dia akan bisa memalsukan permintaan dengan identitas saya?

Sebenarnya, masalah ini berlaku untuk semua otentikasi berbasis token .

Bagaimana cara mencegahnya? Saluran aman seperti HTTPS?

smwikipedia
sumber
1
Inilah sebabnya mengapa token seringkali hanya valid untuk periode waktu yang singkat. Dan ya, Anda harus menggunakan HTTPS jika Anda khawatir tentang kerahasiaan data Anda.
Jonathon Reinhart
4
@JonathonReinhart Tetapi jika token segera kedaluwarsa, klien saya harus mendapatkan token baru dengan mengautentikasi ulang dirinya sendiri dari waktu ke waktu. Bukankah ini membosankan?
smwikipedia
@ JonathonReinhart Saya pikir saya mengerti mengapa token berumur pendek. Karena itu, server tidak perlu melacak kedaluwarsa dari token dan dengan demikian memberi jalan bagi skalabilitas. Semacam itu trade-offantara having finer control of token expirationdan having better scalability.
smwikipedia
2
Bisakah ini juga membantu? - "Mekanisme keamanan umum untuk mendeteksi pencurian token adalah untuk melacak asal alamat IP permintaan." - dijelaskan secara rinci di bagian terakhir di sini - firebase.google.com/docs/auth/admin/manage-sessions
Ula
3
Secara teoritis, tidak mungkin untuk mencegah pencurian token. Yang terbaik yang bisa kita lakukan adalah mendeteksi bahwa itu telah terjadi dan kemudian mencabut sesi ASAP. Metode terbaik untuk deteksi adalah dengan menggunakan token penyegaran berputar (seperti yang disarankan oleh RFC 6819). Berikut adalah blog yang menjelaskan ini secara rinci: supertokens.io/blog/…
Rishabh Poddar

Jawaban:

284

Saya penulis perpustakaan simpul yang menangani otentikasi cukup mendalam, express-stormpath , jadi saya akan berpadu dengan beberapa informasi di sini.

Pertama, JWT biasanya TIDAK dienkripsi. Meskipun ada cara untuk mengenkripsi JWT (lihat: JWEs ), ini tidak umum dalam praktik karena banyak alasan.

Selanjutnya, segala bentuk otentikasi (menggunakan JWT atau tidak), terkena serangan MitM (man-in-the-middle). Serangan-serangan ini terjadi ketika seorang penyerang dapat MELIHAT lalu lintas JARINGAN saat Anda membuat permintaan melalui internet. Inilah yang dapat dilihat ISP Anda, NSA, dll.

Inilah yang membantu SSL mencegah: dengan mengenkripsi lalu lintas NETWORK Anda dari komputer Anda -> beberapa server saat mengautentikasi, pihak ketiga yang memantau lalu lintas jaringan Anda TIDAK dapat melihat token, kata sandi, atau hal-hal seperti itu kecuali mereka entah bagaimana dapat melakukannya untuk mendapatkan salinan kunci SSL pribadi server (tidak mungkin). Ini adalah alasan SSL WAJIB untuk semua bentuk otentikasi.

Katakanlah, bagaimanapun, bahwa seseorang dapat mengeksploitasi SSL Anda dan dapat melihat token Anda: jawaban untuk pertanyaan Anda adalah YA , penyerang akan dapat menggunakan token itu untuk menyamar sebagai Anda dan membuat permintaan ke server Anda.

Sekarang, di sinilah protokol masuk

JWT hanyalah satu standar untuk token otentikasi. Mereka dapat digunakan untuk apa saja. Alasan JWT agak keren adalah karena Anda dapat menanamkan informasi tambahan di dalamnya, dan Anda dapat memvalidasi bahwa tidak ada yang mengacaukannya (menandatangani).

NAMUN, JWT sendiri tidak ada hubungannya dengan 'keamanan'. Untuk semua maksud dan tujuan, JWT kurang lebih sama dengan kunci API: hanya string acak yang Anda gunakan untuk mengautentikasi terhadap beberapa server di suatu tempat.

Yang membuat pertanyaan Anda lebih menarik adalah protokol yang digunakan (kemungkinan besar OAuth2).

Cara OAuth2 bekerja adalah bahwa ia dirancang untuk memberikan token TEMPORARY kepada klien (seperti JWT!) Untuk otentikasi untuk PERIODE WAKTU SINGKAT SAJA SAJA!

Idenya adalah bahwa jika token Anda dicuri, penyerang hanya dapat menggunakannya untuk waktu yang singkat.

Dengan OAuth2, Anda harus mengautentikasi ulang diri Anda sendiri dengan server sesekali dengan memberikan nama pengguna / kata sandi ATAU kredensial API dan kemudian mendapatkan token kembali sebagai imbalan.

Karena proses ini terjadi sesekali, token Anda akan sering berubah, membuatnya lebih sulit bagi penyerang untuk terus-menerus menyamar sebagai Anda tanpa melalui masalah besar.

Semoga ini membantu ^^

rdegges
sumber
3
Penulis artikel berikut berpendapat bahwa kelemahan JWT adalah bahwa satu-satunya cara untuk memulihkan dari JWT yang dicuri adalah dengan menghasilkan pasangan kunci baru dan secara efektif mengeluarkan semua pengguna. Sedangkan dengan id sesi disimpan di DB, situs web hanya dapat menghapus sesi dari pengguna yang terpengaruh dan mengeluarkannya dari semua perangkat. Saya tidak yakin bagaimana OAuth2 cocok dengan gambar di sini atau apakah itu membantu mengurangi kerugian yang disajikan. medium.com/@rahulgolwalkar/…
Marcel
4
Penulis salah. Ada berbagai pola desain yang dapat Anda gunakan untuk membatalkan token. Tetapi secara umum: menggunakan JWT untuk segala jenis tujuan otentikasi adalah ide yang buruk. Jauh lebih efisien untuk menggunakan cookie sesi dengan ide sesi yang tertanam di dalamnya yang ditandatangani secara kriptografis.
rdegges
1
@ delegasi tolong beri tahu saya bagaimana JWT adalah ide yang buruk untuk otentikasi? dan bagaimana saya bisa menggunakan cookie sesi yang Anda sebutkan dalam komentar Anda di atas?
noman tufail
6
Ini terlalu lama untuk mengetik satu respons. Jika Anda ingin mempelajari lebih lanjut, saya telah memberikan ceramah rinci tentang masalah ini. Anda dapat memeriksa slide saya secara online: speakerdeck.com/rdegges/jwts-suck-and-are-stupid
rdegges
2
Secara teoritis, tidak mungkin untuk mencegah pencurian token. Yang terbaik yang bisa kita lakukan adalah mendeteksi bahwa itu telah terjadi dan kemudian mencabut sesi ASAP. Metode terbaik untuk deteksi adalah dengan menggunakan token penyegaran berputar (seperti yang disarankan oleh RFC 6819). Berikut adalah blog yang menjelaskan ini secara rinci: supertokens.io/blog/…
Rishabh Poddar
31

Saya tahu ini adalah pertanyaan lama tapi saya pikir saya bisa menjatuhkan $ 0,50 saya di sini, mungkin seseorang dapat meningkatkan atau memberikan argumen untuk benar-benar menolak pendekatan saya. Saya menggunakan JWT dalam API yang tenang lebih dari HTTPS (ofc).

Agar ini berfungsi, Anda harus selalu mengeluarkan token yang berumur pendek (tergantung pada kebanyakan kasus, di aplikasi saya, saya sebenarnya menetapkan expklaim menjadi 30 menit, dan ttlhingga 3 hari, sehingga Anda dapat menyegarkan token ini selama ttlmasih token valid dan token belum dimasukkan daftar hitam )

Untuk itu authentication service, untuk membatalkan token, saya suka menggunakan lapisan cache dalam memori ( redis dalam kasus saya) sebagai a JWT blacklist/ ban-listdi depan, tergantung pada beberapa kriteria: (Saya tahu itu melanggar filosofi tenang, tetapi dokumen yang disimpan adalah benar-benar berumur pendek, karena saya daftar hitam untuk sisa waktu mereka untuk hidup - ttlklaim-)

Catatan: token daftar hitam tidak dapat di-refresh secara otomatis

  • Jika user.passwordatau user.emailtelah diperbarui (memerlukan konfirmasi kata sandi), layanan auth mengembalikan token yang di-refresh dan membatalkan (blacklist) yang sebelumnya, jadi jika klien Anda mendeteksi bahwa identitas pengguna entah bagaimana telah dikompromikan, Anda dapat meminta pengguna itu untuk mengubah kata sandi . Jika Anda tidak ingin menggunakan daftar hitam untuk itu, Anda bisa (tapi saya tidak mendorong Anda untuk) memvalidasi iatklaim (dikeluarkan pada) terhadap user.updated_atbidang (jika jwt.iat < user.updated_atJWT tidak valid).
  • Pengguna sengaja keluar.

Akhirnya Anda memvalidasi token secara normal seperti yang dilakukan semua orang.

Catatan 2: daripada menggunakan token itu sendiri (yang sangat panjang) sebagai kunci cache, saya sarankan membuat dan menggunakan token UUID untuk jtiklaim. Mana yang baik dan saya pikir (tidak yakin karena baru saja muncul di pikiran saya) Anda dapat menggunakan UUID yang sama dengan token CSRF juga, dengan mengembalikan secure/ non-http-onlycookie dengan itu dan menerapkan X-XSRF-TOKENheader dengan benar menggunakan js. Dengan cara ini Anda menghindari pekerjaan komputasi menciptakan token lain untuk pemeriksaan CSRF.

Frondor
sumber
9
Tidak ada kata terlambat untuk menyumbangkan ide Anda. Terima kasih untuk balasan Anda.
smwikipedia
2
Jika Anda menyimpan daftar hitam di server yang perlu diperiksa untuk setiap permintaan, mengapa tidak menggunakan sesi lama saja?
Franklin Yu
@FranklinYu Daftar hitam jauh lebih murah daripada toko sesi penuh. Karena Anda menyimpan objek nilai kunci berumur pendek (tergantung pada sisa waktu untuk hidup, yang seharusnya cukup singkat), dan itu terjadi hanya untuk tindakan keluar dan tindakan yang membatalkan token, jadi tidak semua token adalah disimpan ofc.
Frondor
2
Bagaimana bisa murah? Pertama-tama, jika Anda masih menyimpan apa pun di sisi server, Anda tidak menikmati manfaat "skalabilitas" yang diklaim oleh JWT karena masih ada server daftar hitam pusat yang perlu diajak bicara oleh semua server aplikasi sebelum melakukan sesuatu. Jika Anda hanya perlu menyimpan daftar hitam 1k karena kedaluwarsa cepat, Anda dapat melakukan hal yang sama untuk sesi dan karenanya hanya perlu menyimpan sesi 1k.
Franklin Yu
3
Saya suka pendekatan ini. Anda sebenarnya tidak perlu memeriksa daftar hitam pada setiap permintaan, hanya pada permintaan yang terjadi setelah JWT berakhir (yang dapat Anda baca dari token itu sendiri) dan hingga periode TTL sesudahnya. Dalam "use case" standar ", itu harus terjadi, paling banyak, sekali seumur hidup dari token yang diberikan. Setelah di-refresh, Anda mungkin dapat menolak permintaan refresh di masa mendatang. Terima kasih @Frondor
John Ackerman
7

Maaf agak terlambat dalam hal ini, tetapi memiliki masalah yang sama dan sekarang ingin berkontribusi sesuatu yang sama.

1) rdegges menambahkan poin yang sangat baik, bahwa JWT tidak ada hubungannya dengan "keamanan" dan hanya memvalidasi, jika ada yang mengacaukan payload atau tidak (penandatanganan); ssl membantu mencegah dari pelanggaran.

2) Sekarang, jika ssl juga entah bagaimana terganggu, penyadap apa pun dapat mencuri token pembawa kami (JWT) dan menyamar sebagai pengguna asli, langkah selanjutnya yang bisa dilakukan adalah, untuk mencari "bukti kepemilikan" JWT dari klien. .

3) Sekarang, dengan pendekatan ini, presenter JWT memiliki kunci Proof-Of-Possession (POP) tertentu, yang penerima dapat secara kriptografis mengkonfirmasi apakah permintaan tersebut berasal dari pengguna asli yang sama atau tidak.

Saya merujuk artikel Proof of Possesion untuk ini dan saya yakin dengan apporach.

Saya akan senang, jika bisa berkontribusi apa pun.

Cheers (y)

yanky_cranky
sumber
0

Tidak bisakah kita menambahkan ip host awal yang telah meminta untuk menghasilkan token JWT ini sebagai bagian dari klaim? Sekarang ketika JWT dicuri dan digunakan dari mesin yang berbeda, ketika server memvalidasi token ini, kami dapat memverifikasi apakah mesin yang diminta sesuai dengan yang ditetapkan sebagai bagian dari klaim. Ini tidak akan cocok dan karenanya token dapat ditolak. Juga jika pengguna mencoba memanipulasi token dengan mengatur ipnya sendiri ke token, token akan ditolak ketika token diubah.

Venkatesh Vs
sumber
Itu adalah salah satu solusi yang mungkin tetapi untuk klien di balik firewall tipikal untuk alamat IP yang akan diambil dari kumpulan alamat dan yang dapat berubah setiap saat.
SpeedOfSpin