Apakah perlu mem-hashing kata sandi di sisi klien

132

Ketika saya ingin menempatkan sistem login, saya selalu membandingkan MD5 dari kata sandi yang diberikan dengan nilainya di tabel pengguna di sisi server.

Namun, seorang teman saya mengatakan kepada saya bahwa kata sandi "jelas" dapat diendus oleh perangkat lunak jaringan.

Jadi pertanyaan saya adalah: apakah itu ide yang bagus untuk hash password di sisi klien Apakah lebih baik daripada hashing di sisi server?

Zakaria
sumber
1
Saya sedang memikirkan hashing kata sandi di sisi klien, tetapi hanya supaya saya bisa yakin kata sandi klien tidak pernah ada sebagai teks yang jelas di sisi server, yang berarti mereka dapat merasa lebih mudah mengetahui bahwa saya tidak tahu kata sandi mereka yang sebenarnya, atau tidak bisa dengan mudah menyerah jika dikompromikan. apakah saya gila
Topan
1
Hanya untuk kelengkapan, karena kita berbicara tentang keamanan, dan MD5 disebutkan dalam OP: Seseorang harus selalu menggunakan garam ketika mengenkripsi kata sandi. Menggunakan MD5 polos dan tawar hanya sedikit lebih baik daripada menyimpan kata sandi plaintext di database Anda.
sffc
1
@Cyclone Hashing ONLY di sisi klien jelas merupakan ide yang buruk, karena jika penyerang entah bagaimana mengetahui hash, ia dapat menggunakannya untuk masuk seolah-olah ia tahu kata sandinya, melewati kode hashing sisi klien.
Teejay
5
@ Tejjay: Itu sebabnya Anda tidak mengirim hash dengan jelas. Server mengirimkan garam acak ke klien, Anda menambahkan hash kata sandi, dan hash semuanya lagi, lalu mengirimkannya kembali ke server yang melakukan perhitungan yang sama. Serangan replay gagal karena garamnya akan berbeda
MSalters
2
Bukankah seharusnya pertanyaan ini selesai di security.stackexchange.com?
efr4k

Jawaban:

115

Pada dasarnya, temanmu benar. Tetapi hanya dengan hashing kata sandi di sisi klien hanya lebih baik daripada mengirimkannya sebagai teks biasa ke server. Seseorang, yang dapat mendengarkan kata sandi teks biasa Anda tentu juga dapat mendengarkan kata sandi hash, dan menggunakan hash yang ditangkap ini sendiri untuk mengotentikasi terhadap server Anda.

Untuk masalah ini, protokol otentikasi yang lebih aman biasanya melompati sejumlah rintangan untuk memastikan, bahwa serangan replay seperti itu tidak dapat bekerja, biasanya, dengan memungkinkan klien untuk memilih banyak bit acak, yang diacak bersama dengan kata sandi , dan juga dikirimkan secara jelas ke server.

Di server:

  • menghasilkan beberapa bit secara acak
  • kirim bit ini (dalam bentuk teks) ke klien

Pada klien:

  • menghasilkan beberapa bit acak
  • kata sandi gabungan, bit acak server dan bit acak klien
  • menghasilkan hash di atas
  • mengirimkan bit acak (dalam teks yang jelas) dan hash ke server

Karena server mengetahui informasi acaknya sendiri serta bit acak klien (ia mendapatkannya sebagai teks yang jelas), pada dasarnya ia dapat melakukan transformasi yang sama. Protokol ini memastikan, bahwa tidak ada yang mendengarkan dalam percakapan ini dapat menggunakan informasi nanti untuk mengotentikasi secara salah menggunakan informasi yang direkam (kecuali algoritma yang sangat lemah digunakan ...), selama kedua belah pihak menghasilkan "bit noise" yang berbeda setiap kali, berjabat tangan dilakukan.

Sunting Semua ini rawan kesalahan dan membosankan dan agak sulit untuk diperbaiki (baca: aman). Jika memungkinkan, pertimbangkan untuk menggunakan implementasi protokol otentikasi yang telah ditulis oleh orang yang berpengetahuan (tidak seperti saya! Di atas hanya dari memori buku yang saya baca beberapa waktu lalu.) Anda benar-benar tidak ingin menulis ini sendiri biasanya.

Beladau
sumber
5
Bagaimana dia bisa mengotentikasi dengan kata sandi hash dalam sistem login karena akan di hash lagi?
Zakaria
4
Jika Anda menyimpan kata sandi dalam bentuk hash di server (seperti seharusnya) maka klien harus hash kata sandi dua kali: pertama, kata sandi saja, sehingga cocok dengan pandangan server tentang dunia, dan kemudian seperti yang dijelaskan di atas untuk demi protokol.
Dirk
3
@ Malas, karena penyerang dapat mengendus kedua cara, "bit acak" akan mengendus bersama. Kemudian penyerang dapat menganalisis (baca: brute force) pasangan permintaan dan respons secara offline untuk menemukan kata sandi asli.
Pacerier
7
Namun, untuk tujuan mengirimkan kata sandi atau hash kata sandi, sering kali proses asimetris seperti Diffie-Hellman digunakan untuk membuat kunci enkripsi yang memungkinkan kedua belah pihak untuk bertukar informasi tanpa pihak pengintai dapat mendekripsi. Inilah yang dilakukan SSL, dan merupakan alasan bahwa sebagian besar situs memiliki halaman login mereka di HTTPS / SSL. SSL sudah melindungi terhadap serangan replay. Saya akan merekomendasikan meningkatkan SSL daripada membangun protokol Anda sendiri. Meskipun saya setuju dengan salting + hashing sisi klien kata sandi, tetapi mengirimkan ini melalui koneksi SSL yang sudah mapan.
AaronLS
14
Untuk lebih jelasnya: jika Anda tidak menggunakan HTTPS, tidak masalah javascript apa yang Anda jalankan pada klien; MITM akan dapat memodifikasi konten halaman Anda sebelum hits klien. HTTPS adalah satu-satunya solusi.
aidan
60

Pertama-tama, ini TIDAK meningkatkan keamanan aplikasi Anda (dengan asumsi itu adalah aplikasi web).

Gunakan SSL (Atau sebenarnya TLS, yang biasa disebut SSL), ini tidak terlalu mahal (Ukur waktu yang Anda gunakan untuk menemukan cara di sekitarnya dan gandakan dengan upah minimum, membeli sertifikat menang hampir selalu).

Mengapa ini sederhana? TLS memecahkan masalah (ketika digunakan dengan sertifikat yang dibeli, tidak ditandatangani sendiri) yang cukup besar dalam kriptografi: Bagaimana saya tahu server yang saya ajak bicara adalah server yang saya pikir saya ajak bicara? Sertifikat TLS adalah cara untuk mengatakan: "Saya, otoritas sertifikat, dipercaya oleh browser Anda, menyatakan bahwa situs web di [url] memiliki kunci publik ini, dengan kunci pribadi yang sesuai, yang (kunci pribadi) yang hanya diketahui oleh server, lihat Saya menandatangani tanda tangan saya di seluruh dokumen, jika ada yang mengubahnya, Anda dapat melihat ".

Tanpa TLS, enkripsi apa pun menjadi tidak ada gunanya, karena jika saya duduk di sebelah Anda dalam sebuah coffeeshop, saya dapat membuat laptop / smartphone Anda berpikir saya adalah server dan MiTM (Man in The Middle) Anda. Dengan TLS, laptop / smartphone Anda akan meneriakkan "SAMBUNGAN TIDAK TERPERCAYA", karena saya tidak memiliki otoritas sertifikat yang menandatangani sertifikat yang cocok dengan situs Anda. (Enkripsi vs. Otentikasi).

Penafian: pengguna cenderung mengklik kanan melalui peringatan ini: "Koneksi tidak tepercaya? Apa? Saya hanya ingin gambar anak kucing saya! Tambahkan Pengecualian Klik Konfirmasi Klik YAY! Anak kucing!"

Namun, jika Anda benar-benar tidak ingin membeli sertifikat, masih DO mengimplementasikan hash javascript sisi klien (dan menggunakan perpustakaan standford (SJCL) untuk itu, JANGAN PERNAH MELAKUKAN CRYPTO DIRI SENDIRI ).

Mengapa? Penggunaan kembali kata sandi! Saya dapat mencuri cookie sesi Anda (yang memungkinkan saya untuk berpura-pura ke server Anda bahwa saya adalah Anda) tanpa HTTPS dengan mudah (lihat firesheep). Namun jika Anda menambahkan javascript ke halaman login Anda yang, sebelum mengirim, hash kata sandi Anda (gunakan SHA256, atau bahkan lebih baik, gunakan SHA256, kirim mereka kunci publik yang Anda buat dan kemudian enkripsi hash password dengan itu, Anda tidak dapat menggunakan garam dengan ini), dan kemudian mengirimkan kata sandi hash / terenkripsi ke server. REHASH hash di server Anda dengan garam dan bandingkan dengan apa yang disimpan dalam database Anda (simpan kata sandi seperti ini:

(SHA256(SHA256(password)+salt))

(simpan garam sebagai plaintext dalam database juga)). Dan kirim kata sandi Anda seperti ini:

RSA_With_Public_Key(SHA256(password))

dan periksa kata sandi Anda seperti ini:

if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok

Karena, JIKA seseorang mengendus klien Anda, mereka akan dapat masuk sebagai klien Anda (pembajakan sesi) tetapi mereka TIDAK AKAN PERNAH melihat kata sandi plaintext (kecuali jika mereka mengubah javascript Anda, namun, peretas starbucks mungkin tidak akan tahu caranya / tertarik) dalam hal ini.) Jadi mereka akan mendapatkan akses ke aplikasi web Anda, tetapi tidak ke email / facebook / etc mereka. (di mana pengguna Anda kemungkinan akan menggunakan kata sandi yang sama). (Alamat email akan menjadi nama login mereka atau akan ditemukan di profil / pengaturan mereka di aplikasi web Anda).

FriendlyCryptoNeighbor
sumber
Saya pikir ini adalah jawaban yang baik tetapi mungkin perlu beberapa informasi lebih lanjut tentang cara memberi garam dengan benar dan bahwa lebih baik menggunakan fungsi hashing "lambat" sebelum menyimpan kata sandi di server (seperti bcrypt).
Neyt
24

Anda mungkin OK untuk tidak khawatir tentang ini - seperti Dirk menyebutkan bahkan jika Anda hash kata sandi pengguna jahat dapat berada di jaringan dan melihat hash dikirim, dan cukup mengirim hash yang sama sendiri.

Ini sedikit lebih baik, karena mencegah pengguna jahat mengetahui apa kata sandinya, tetapi karena mereka masih bisa masuk (atau berpotensi merekonstruksi kata sandi asli ), itu tidak membantu.

Secara umum, jika Anda khawatir tentang keamanan kata sandi dan data pengguna Anda (dan memang seharusnya begitu!), Anda ingin menggunakan server SSL yang aman. Jika ini bukan masalah bagi Anda untuk alasan apa pun Anda mungkin juga tidak repot dengan hashing; itu hanya keamanan melalui ketidakjelasan .


Sunting Agustus 2014: Google mendorong semakin banyak situs web untuk beralih ke HTTPS di mana-mana , karena mengamankan komunikasi itu sendiri adalah satu-satunya cara untuk mencegah serangan mengendus jaringan. Upaya mengaburkan data yang dikirimkan hanya akan menghalangi, tidak berhenti, penyerang yang berdedikasi, dan dapat memberi pengembang rasa aman palsu yang berbahaya.

dimo414
sumber
Saya pikir pendapat Anda bahwa hashing sisi klien hanya "sedikit lebih baik" adalah benar jika Anda hanya fokus pada mendapatkan xkata sandi pengguna dan mengakses satu layanan. Jika Anda mempertimbangkan efek kolektif, saya akan mengatakan itu "jauh lebih baik"; karena mencegah membangun database pencarian besar dari kata sandi yang digunakan untuk memaksa hash asin di berbagai layanan. IMO. Lihat apa yang dilakukan AWS Cognito di klien untuk referensi.
f1lt3r
17

Sebenarnya saya tidak setuju bahwa hashing sisi klien lebih aman dalam kasus ini. Saya pikir itu kurang aman.

Inti menyimpan hash kata sandi di basis data Anda sebagai lawan dari kata sandi asli (atau bahkan kata sandi terenkripsi) adalah bahwa secara matematis tidak mungkin untuk mendapatkan kata sandi asli dari hash (walaupun secara teori dimungkinkan untuk mendapatkan tabrakan masukan hash, kesulitan yang tergantung pada kekuatan keamanan dari algoritma hashing). Vektor kemungkinan serangan di sini adalah bahwa jika penyerang potensial entah bagaimana membahayakan basis data penyimpanan kata sandi Anda, ia masih tidak akan dapat memperoleh kata sandi asli dari pengguna Anda.

Jika mekanisme otentikasi Anda mengirim hash kata sandi, maka dalam skenario pelanggaran keamanan ini, penyerang tidak perlu mengetahui kata sandi asli - mereka hanya mengirim hash yang mereka miliki dan hei presto, mereka memiliki akses ke akun pengguna tertentu, dan dengan ekstensi, seluruh sistem Anda. Ini benar-benar mengalahkan titik menyimpan kata sandi hash di tempat pertama!

Cara yang benar-benar aman untuk melakukannya adalah dengan mengirimkan klien kunci publik satu kali bagi mereka untuk mengenkripsi kata sandi, kemudian Anda mendekripsi dan hash kembali di sisi server.

Ngomong-ngomong, pertanyaan semacam ini mungkin akan mendapatkan lebih banyak tanggapan pakar tentang Keamanan StackExchange.

Adam Burley
sumber
3
Sepenuhnya setuju dengan ini. Agar pendekatan pihak klien bekerja, seseorang juga harus mengirim garam kepada klien, yang akan membatalkan seluruh tujuan pengasinan!
James Wright
@ JamesWright: Intinya mengirim garam acak untuk setiap penggunaan, yang mencegah penggunaan kembali pesan login secara ilegal. (Suatu bentuk serangan replay). Mengirim garam yang sama setiap kali memang tidak ada gunanya.
MSalters
Yang perlu Anda lakukan adalah menggunakan "nonce" ( en.wikipedia.org/wiki/Cryptographic_nonce ). Dengan begitu, server juga mengontrol garam dan membuat ini aman. Hashing pada sisi klien juga penting agar kode JS yang disuntikkan tidak dapat dengan mudah menemukannya nanti. Lebih lanjut di sini: stackoverflow.com/a/21716654/43615
Thomas Tempelmann
Untuk menggunakan garam + nonce dalam proses otentikasi login, lihat jawaban ini: stackoverflow.com/a/24978909/43615
Thomas Tempelmann
Jelas jika Anda hash di sisi klien, Anda harus hash lagi di sisi server untuk mencegah titik yang Anda buat. Seperti yang orang lain tunjukkan, untuk privasi Anda menginginkan enkripsi sisi klien.
Daniel Methner
5

Perhatikan bahwa menjaga keamanan kata sandi dari pihak ketiga tidak cukup.

Segera setelah privasi terlibat (dan kapan pun tidak, hari ini?), Anda tidak ingin mengetahui kata sandi. Anda tidak dapat menyalahgunakan atau membocorkan apa yang tidak Anda miliki , sehingga Anda dan klien Anda dapat tidur lebih nyenyak jika Anda tidak pernah melihat kata sandi yang jelas.

Oleh karena itu, hashing / mengenkripsi sisi klien masuk akal.

Raphael
sumber
Sepakat! Banyak orang kehilangan titik ini. Jika saya mengunduh basis data kata sandi Anda dari kata sandi hash asin, dan saya dapat memecahkan hanya satu menggunakan basis data pencarian hash, maka kemungkinan saya bisa memecahkan semuanya. Setelah saya memiliki 50 ribu kata sandi asli, saya sekarang memiliki kunci untuk xpengguna pada nlayanan yang hanya mengenkripsi di server. Jika setiap layanan secara unik melakukan hash kata sandi sebelum meninggalkan klien, basis data besar kata sandi lintas-layanan menjadi jauh lebih kecil. Periksa lalu lintas masuk AWS Anda, lihat apa yang mereka lakukan. Itu kemungkinan Watson tersayang.
f1lt3r
3

Itu tergantung, Anda dapat menggunakan hashing sisi klien, tetapi garam sisi server tidak akan mungkin.

lihat tautan Enkripsi kata sandi di sisi klien

SmAxlL
sumber
1

Saya telah melakukan banyak pekerjaan pada ini baru-baru ini, IRL ada dua masalah dengan hash / enkripsi simetris sisi klien dengan benar-benar membunuh ide: 1. Anda harus mendapatkan garam kembali ke server SOMEHOW ... dan untuk mengenkripsi di sisi klien Anda memerlukan kata sandi ... yang mengalahkan tujuan. 2. Anda mengekspos implementasi hashing Anda (bukan kesepakatan BESAR karena sebagian besar situs menggunakan salah satu dari 3 atau 4 alga hashing) yang membuat serangan lebih mudah (karena hanya perlu mencoba satu daripada n).

Yang akhirnya saya tuju adalah enkripsi asimetris pada klien menggunakan OpenPGP.js atau serupa ... Ini bergantung pada kunci yang diimpor atau sisi klien yang dihasilkan pada klien dan server yang mengirimkan kunci publik itu. Hanya kunci publik klien yang dapat dikirim kembali ke server. Ini melindungi terhadap serangan MIM dan seaman perangkat (Saat ini saya menyimpan kunci pribadi klien secara default di localStore, ini demo).

Keuntungan utama dari ini adalah bahwa saya tidak pernah memiliki data pengguna disimpan / bahkan dalam memori tidak dienkripsi di server / penyimpanan data saya (dan kunci pribadi server saya secara fisik terpisah)

Dasar dari ini adalah untuk memberikan orang cara untuk berkomunikasi dengan aman di mana HTTPS dibatasi (misalnya, Iran / Korea Utara ...) dan juga hanya eksperimen yang menyenangkan.

Saya JAUH dari yang pertama memikirkan hal ini, http://www.mailvelope.com/ menggunakan ini

ScottGal
sumber
1

Jika seseorang dapat melihat data masuk dan keluar di koneksi Anda maka otentikasi tidak akan menyelamatkan Anda. Sebaliknya saya akan melakukan hal berikut untuk hal-hal super rahasia.

Kata sandi diucapkan di sisi klien sebelum dikirim ke server. (Server menyimpan nilai hash dan salin lain dari hash yang dikirim dari browser).

Jadi serangan orang tengah dapat memungkinkan mereka untuk mengirim nilai hash yang sama untuk login seperti mereka, tetapi kata sandi pengguna tidak akan diketahui. Ini akan menghentikan mereka mencoba layanan lain dengan kredensial yang sama untuk masuk ke tempat lain.

Data pengguna juga dienkripsi di sisi browser.

Ah, jadi serangan perantara akan mendapatkan data terenkripsi, tetapi tidak akan dapat mendekripsi tanpa kata sandi yang sebenarnya digunakan untuk login. (kata sandi pengguna yang disimpan di DOM di browser saat mereka masuk). Jadi pengguna sebenarnya akan melihat konten yang didekripsi tetapi perantara tidak bisa. Ini juga berarti NSA atau agensi lain tidak akan dapat meminta Anda / perusahaan / penyedia hosting untuk mendekripsi data ini karena tidak mungkin bagi mereka untuk melakukannya juga.

Beberapa contoh kecil dari kedua metode ini ada di blog saya http://glynrob.com/javascript/client-side-hashing-and-encryption/

GlynRob
sumber
1

Baru-baru ini baik GitHub dan Twitter mengumumkan kata sandi itu di mana disimpan dalam log internal. Saya pernah mengalami hal ini secara tidak sengaja dalam laporan bug dan log lain yang menemukan jalannya ke splunk, dll. Untuk twitter jika kata sandi Trump ada di log, itu bisa menjadi masalah besar bagi admin untuk "melihat", karena situs lain mungkin tidak sebanyak masalah besar karena administrator tidak akan banyak menggunakan untuk itu. Apa pun admin, kami tidak suka melihat kata sandi.

Jadi pertanyaannya adalah benar-benar jika hashing harus terjadi pada sisi klien untuk keamanan, tetapi bagaimana kita bisa melindungi kata sandi sebelum akhirnya di-hash dan dibandingkan oleh sisi server sehingga tidak bisa login entah bagaimana.

Enkripsi bukanlah ide yang buruk karena pengembang setidaknya harus melewati beberapa rintangan, dan jika Anda menemukan kata sandi masuk ke log, Anda dapat mengubah kunci enkripsi, menghancurkan yang asli, dan data menjadi tidak berguna. Lebih baik lagi memutar tombol setiap malam dan itu bisa mengurangi jendela sangat.

Anda juga bisa hash hash dalam catatan pengguna Anda. Kata sandi yang bocor akan menjadi kata sandi teks biasa. Server akan menyimpan versi hash. Tentu hash menjadi kata sandi, tetapi kecuali jika Anda memiliki memori fotografis, Anda tidak akan mengingat 60 karakter bcyrpt. Garam dengan nama pengguna. Jika Anda bisa mengumpulkan sesuatu tentang pengguna selama proses login (sambil tidak mengungkapkan bahwa catatan pengguna ada), Anda dapat menambahkan garam dengan itu juga menciptakan hash yang lebih kuat yang tidak dapat dibagi antara situs. Tidak ada orang di tengah yang bisa memotong dan menempel hash yang ditangkap di antara situs.

Gabungkan dengan cookie yang tidak dikirimkan kembali ke server dan Anda mungkin menemukan sesuatu. Pada permintaan pertama, kirimkan cookie ke klien dengan kunci, lalu pastikan cookie itu tidak kembali ke layanan login sehingga kecil kemungkinannya untuk dicatat. Simpan kunci di toko sesi, dan kemudian hapus segera setelah login terjadi atau ketika sesi berakhir ... ini mengharuskan Anda JWT guys, tetapi mungkin hanya menggunakan layanan nosql untuk itu.

Jadi, seorang admin menemukan salah satu dari kata sandi hash dan terenkripsi ini dalam splunk atau alat pelaporan bug. Seharusnya tidak berguna bagi mereka karena mereka tidak dapat menemukan kunci enkripsi lagi, dan bahkan jika mereka melakukannya, mereka harus memaksa hash. Selain itu, pengguna akhir tidak mengirim plaintext apa pun di sepanjang baris sehingga siapa pun di tengah setidaknya memiliki waktu yang lebih sulit dan Anda tidak bisa langsung masuk ke situs lain dan masuk.

Eric Twilegar
sumber
Perhatian saya tepat. Jika server entah bagaimana log secara tidak sengaja karena implementasi yang buruk atau niat jahat, maka mungkin akun pengguna lain dapat dikompromikan jika mereka menggunakan kembali kata sandi.
Dan
0

Pertimbangkan ini: -

Klien mengirimkan permintaan ke server "Saya memiliki kata sandi untuk memvalidasi".

Server mengirim klien string acak satu kali saja. R $

Klien menyematkan kata sandi pengguna dalam string ini (berdasarkan pada setiap (variabel) aturan yang ingin Anda terapkan).

Klien mengirimkan string ke server dan jika kata sandi OK, server mencatat pengguna.

Jika server menerima permintaan login lain menggunakan R $, pengguna keluar dan akun dibekukan, sedang menunggu penyelidikan.

Jelas sekali semua tindakan pengamanan (normal) lainnya akan dilakukan.

butuh
sumber
0

Gagasan hashing sisi klien ini adalah untuk melindungi pengguna, bukan situs Anda. Seperti yang telah disebutkan berulang kali, teks biasa atau kata sandi hash keduanya memiliki akses ke situs Anda secara merata. Anda tidak mendapatkan manfaat keamanan.

Tetapi pengguna Anda yang sebenarnya, teks biasa, kata sandi seharusnya hanya diketahui oleh mereka. Mengetahui apa yang mereka pilih sebagai kata sandi adalah informasi yang dapat digunakan untuk melawan mereka di situs dan sistem lain. Anda menjadi situs yang berfokus pada pelanggan dengan melindungi mereka dari pilihan kata sandi yang ditemukan oleh server dev atau oleh pihak ketiga.

tidak ada
sumber