Anda memelihara aplikasi yang sudah ada dengan basis pengguna yang mapan. Seiring waktu diputuskan bahwa teknik hashing kata sandi saat ini sudah usang dan perlu ditingkatkan. Lebih lanjut, untuk alasan UX, Anda tidak ingin pengguna yang ada dipaksa untuk memperbarui kata sandi mereka. Seluruh pembaruan hashing kata sandi harus terjadi di belakang layar.
Asumsikan model database 'sederhana' untuk pengguna yang berisi:
- ID
- Kata sandi
Bagaimana cara seseorang menyelesaikan masalah seperti itu?
Pikiran saya saat ini adalah:
- buat metode hashing baru di kelas yang sesuai
- perbarui tabel pengguna dalam basis data untuk menampung bidang kata sandi tambahan
- Setelah pengguna berhasil masuk menggunakan hash kata sandi yang kedaluwarsa, isilah bidang kata sandi yang kedua dengan hash yang diperbarui
Ini membuat saya dengan masalah yang saya tidak dapat membedakan secara wajar antara pengguna yang memiliki dan mereka yang belum memperbarui hash kata sandi mereka dan dengan demikian akan dipaksa untuk memeriksa keduanya. Ini tampaknya sangat buruk.
Lebih jauh lagi ini pada dasarnya berarti bahwa teknik hashing lama dapat dipaksa untuk tetap tanpa batas waktu sampai setiap pengguna telah memperbarui kata sandi mereka. Hanya pada saat itu saya bisa mulai menghapus cek hashing lama dan menghapus bidang database berlebihan.
Saya terutama mencari beberapa tips desain di sini, karena 'solusi' saya saat ini kotor, tidak lengkap dan apa yang tidak, tetapi jika kode aktual diperlukan untuk menggambarkan solusi yang mungkin, jangan ragu untuk menggunakan bahasa apa pun.
sumber
Jawaban:
Saya akan menyarankan menambahkan bidang baru, "hash_method", dengan mungkin 1 untuk menandakan metode lama dan 2 untuk menandakan metode baru.
Berbicara dengan wajar, jika Anda peduli tentang hal semacam ini dan aplikasi Anda relatif berumur panjang (yang ternyata sudah ada), ini mungkin akan terjadi lagi karena kriptografi dan keamanan informasi adalah bidang yang berkembang, agak tak terduga. Ada saat ketika menjalankan sederhana melalui MD5 adalah standar, jika hashing digunakan sama sekali! Maka orang mungkin berpikir mereka harus menggunakan SHA1, dan sekarang ada garam, garam global + garam acak individu, SHA3, berbagai metode pembuatan nomor acak crypto-ready ... ini tidak akan hanya 'berhenti', jadi Anda mungkin bisa perbaiki dengan baik dengan cara yang dapat diperpanjang, berulang.
Jadi, katakanlah sekarang Anda memiliki sesuatu seperti (dalam pseudo-javascript untuk kesederhanaan, saya harap):
Sekarang menyadari ada metode yang lebih baik, Anda hanya perlu memberikan refactoring kecil:
Tidak ada agen atau pemrogram rahasia yang dirugikan dalam menghasilkan jawaban ini.
sumber
newHash(oldHash, salt)
ataunewHash(password, salt)
Jika Anda cukup peduli meluncurkan skema hashing baru untuk semua pengguna secepat mungkin (misalnya karena yang lama benar-benar tidak aman), sebenarnya ada cara untuk "migrasi" instan dari setiap kata sandi.
Idenya pada dasarnya adalah hash hash . Daripada menunggu pengguna memberikan kata sandi yang ada (
p
) saat login berikutnya, Anda segera menggunakan algoritma hashing baru (H2
) pada hash yang sudah dihasilkan oleh algoritma lama (H1
):Setelah melakukan konversi itu, Anda masih dapat melakukan verifikasi kata sandi dengan sempurna; Anda hanya perlu menghitung
H2(H1(p'))
alih-alih yang sebelumnyaH1(p')
setiap kali pengguna mencoba masuk dengan kata sandip'
.Dalam teori, teknik ini dapat diterapkan ke beberapa migrasi (
H3
,H4
, dll). Dalam praktiknya, Anda ingin menyingkirkan fungsi hash lama, baik untuk alasan kinerja maupun keterbacaan. Untungnya, ini cukup mudah: setelah login yang berhasil berikutnya, cukup hitung hash baru dari kata sandi pengguna dan ganti hash-of-a-hash yang ada dengannya:Anda juga akan memerlukan kolom tambahan untuk mengingat hash apa yang Anda simpan: salah satu kata sandi atau hash lama. Jika terjadi kebocoran basis data, kolom ini seharusnya tidak membuat pekerjaan cracker lebih mudah; terlepas dari nilainya, penyerang masih harus membalikkan
H2
algoritma aman daripada yang lamaH1
.sumber
Solusi Anda (kolom tambahan dalam database) dapat diterima. Satu-satunya masalah dengan itu adalah yang sudah Anda sebutkan: bahwa hashing lama masih digunakan untuk pengguna yang belum diautentikasi sejak perubahan.
Untuk menghindari situasi ini, Anda dapat menunggu pengguna yang paling aktif untuk beralih ke algoritma hashing baru, lalu:
Hapus akun pengguna yang sudah lama tidak mengautentikasi. Tidak ada yang salah dalam menghapus akun pengguna yang tidak pernah mengunjungi situs web selama tiga tahun.
Kirim email ke pengguna yang tersisa di antara mereka yang belum mengautentikasi untuk sementara waktu, memberi tahu bahwa mereka mungkin tertarik pada sesuatu yang baru. Ini akan membantu mengurangi jumlah akun yang menggunakan hashing yang lebih lama.
Hati-hati: jika Anda memiliki opsi tanpa spam yang dapat diperiksa oleh pengguna di situs web Anda, jangan kirim email ke pengguna yang memeriksanya.
Akhirnya, beberapa minggu setelah langkah 2, hancurkan kata sandi untuk pengguna yang masih menggunakan teknik lama. Kapan dan jika mereka mencoba untuk mengotentikasi, mereka akan melihat bahwa kata sandi mereka tidak valid; jika mereka masih tertarik dengan layanan Anda, mereka bisa mengatur ulangnya.
sumber
Anda mungkin tidak akan pernah memiliki lebih dari beberapa tipe hash, sehingga Anda dapat menyelesaikan ini tanpa memperluas basis data Anda.
Jika metode memiliki panjang hash yang berbeda, dan panjang hash masing-masing metode adalah konstan (katakanlah, beralih dari md5 ke hmac-sha1), Anda dapat mengetahui metode dari panjang hash. Jika panjangnya sama, Anda bisa menghitung hash menggunakan metode baru terlebih dahulu, lalu metode lama jika tes pertama gagal. Jika Anda memiliki bidang (tidak ditampilkan) yang memberitahukan kapan pengguna terakhir diperbarui / dibuat, Anda dapat menggunakannya sebagai indikator untuk metode mana yang digunakan.
sumber
Saya melakukan sesuatu seperti ini dan ada cara untuk mengetahui apakah hash baru DAN membuatnya lebih aman. Saya kira lebih aman adalah hal yang baik untuk Anda jika Anda meluangkan waktu untuk memperbarui hash Anda ;-)
Tambahkan kolom baru ke tabel DB Anda yang disebut "garam" dan, gunakan sebagai garam yang dihasilkan secara acak per pengguna. (Cukup banyak mencegah serangan meja pelangi)
Dengan begitu, jika kata sandi saya "pass123" dan garam acak adalah 3333 kata sandi baru saya akan menjadi hash "pass1233333".
Jika pengguna memiliki garam, Anda tahu itu adalah hash baru. Jika garam pengguna adalah nol, Anda tahu itu adalah hash lama.
sumber
Tidak peduli seberapa bagus strategi migrasi Anda, jika database telah dicuri (dan Anda tidak dapat membuktikan secara negatif bahwa ini tidak pernah terjadi), maka kata sandi yang disimpan dengan fungsi hash yang tidak aman mungkin sudah dikompromikan. Satu-satunya mitigasi untuk ini adalah mengharuskan pengguna untuk mengubah kata sandi mereka.
Ini bukan masalah yang bisa diselesaikan (hanya) dengan menulis kode. Solusinya adalah memberi tahu pengguna dan pelanggan tentang risiko yang telah mereka hadapi. Setelah Anda bersedia terbuka tentang hal itu, Anda dapat melakukan migrasi hanya dengan mengatur ulang kata sandi setiap pengguna, karena itu adalah solusi termudah dan paling aman. Semua alternatif benar-benar menyembunyikan fakta bahwa Anda mengacau.
sumber