it-swarm-id.com

Kata Sandi Hashing: tambahkan garam + lada atau cukup garam?

Harap Catatan: Saya menyadari bahwa metode yang tepat untuk hashing penyimpanan kata sandi yang aman adalah scrypt atau bcrypt. Pertanyaan ini bukan untuk implementasi dalam perangkat lunak aktual, ini untuk pemahaman saya sendiri.

Terkait


Latar Belakang
Sejauh yang saya tahu, metode yang direkomendasikan/disetujui untuk menyimpan verifier kata sandi adalah menyimpan:

$verifier = $salt + hash( $salt + $password )

Dimana:

  • hash() adalah algoritma hashing kriptografi
  • $salt Adalah nilai entropi acak, merata, terdistribusi tinggi
  • $password Adalah kata sandi yang dimasukkan oleh pengguna

Beberapa orang menyarankan untuk menambahkan kunci rahasia ke dalam lada (kadang-kadang disebut merica ). Di mana lada adalah konstanta rahasia, entropi tinggi, khusus sistem.

Alasannya tampaknya bahwa bahkan jika penyerang mendapatkan verifier kata sandi, ada kemungkinan dia tidak tahu nilai lada. Jadi pemasangan serangan yang sukses menjadi lebih sulit.

Jadi, pertanyaan saya adalah:
Apakah menambahkan nilai lada sebagai tambahan garam saat mem-password kata sandi meningkatkan keamanan secara keseluruhan?

Atau apakah keamanan yang dirasakan meningkat berdasarkan asumsi yang salah?

Pembaruan Cepat
Saya tahu tujuan dari $salt (Saya menulis cukup jawaban panjang pada StackOverflow tentang hal itu) kunci $pepper Tambahan adalah kunci tidak meningkatkan apa yang dilakukan garam.
Pertanyaannya adalah, apakah $pepper Menambahkan keamanan lainnya daripada apa yang dilakukan garam?

234
Jacco

Dalam beberapa keadaan, paprika dapat membantu.

Sebagai contoh umum, katakanlah Anda sedang membangun aplikasi web. Ini terdiri dari kode webapp (berjalan dalam beberapa kerangka kerja webapp, ASP.NET MVC, Pyramid on Python, tidak masalah) dan Database SQL untuk penyimpanan. Webapp dan SQL DB berjalan di server fisik yang berbeda.

Serangan paling umum terhadap basis data adalah Serangan Injeksi SQL yang berhasil. Serangan semacam ini tidak serta merta mendapatkan akses ke kode webapp Anda, karena webapp berjalan pada server & ID pengguna yang berbeda.

Anda perlu menyimpan kata sandi secara aman di dalam basis data, dan menghasilkan sesuatu dalam bentuk:

$hashed_password = hash( $salt . $password )

di mana $salt disimpan dalam plaintext dalam database, bersama dengan representasi $hashed_password dan dipilih secara acak untuk setiap kata sandi baru atau yang diubah.

Aspek paling penting dari setiap skema hashing kata sandi adalah bahwa hash adalah lambat ( fungsi hash aman secara kriptografis, lihat https://security.stackexchange.com/a/31846/10727 untuk lebih banyak pengetahuan latar belakang.

Pertanyaannya kemudian, mengingat hampir tidak ada upaya untuk menambahkan nilai konstan ke kode aplikasi, dan bahwa kode aplikasi biasanya tidak dikompromikan selama Serangan Injeksi SQL, apakah yang berikut ini jauh lebih baik daripada yang di atas?

$hashed_password = hash( $pepper . $salt . $password )

di mana $salt disimpan dalam plaintext dalam database, dan $pepper adalah konstanta yang disimpan dalam plaintext dalam kode aplikasi (atau konfigurasi jika kode tersebut digunakan pada beberapa server atau sumbernya publik).

Menambahkan $pepper Ini mudah - Anda hanya membuat konstanta dalam kode Anda, memasukkan nilai acak kriptografi yang aman besar (misalnya 32byte dari/dev/urandom hex atau base64 yang disandikan) ke dalamnya, dan menggunakannya konstan dalam fungsi hashing kata sandi. Jika Anda memiliki pengguna yang sudah ada, Anda memerlukan strategi migrasi, misalnya pengulangan kata sandi pada login berikutnya dan menyimpan nomor versi dari strategi hashing kata sandi di samping hash.

Menjawab:

Menggunakan $pepper tidak menambah kekuatan hash kata sandi if kompromi dari basis data tidak menyiratkan kompromi dari aplikasi. Tanpa pengetahuan tentang lada, kata sandi tetap benar-benar aman. Karena garam khusus kata sandi Anda bahkan tidak dapat mengetahui apakah dua kata sandi dalam database sama atau tidak.

Alasannya adalah bahwa hash($pepper . $salt . $password) secara efektif membangun fungsi acak semu dengan $pepper Sebagai kunci dan $salt.$password Sebagai input (untuk waras hash kandidat seperti PBKDF2 dengan SHA * , bcrypt atau scrypt). Dua dari jaminan fungsi acak pseudo adalah bahwa Anda tidak dapat menyimpulkan input dari output di bawah kunci rahasia dan tidak pula output dari input tanpa sepengetahuan kunci. Ini terdengar sangat mirip dengan properti satu arah dari fungsi hash, tetapi perbedaannya terletak pada kenyataan bahwa dengan nilai entropi rendah seperti kata sandi, Anda dapat menghitung semua nilai yang mungkin secara efektif dan menghitung gambar di bawah fungsi hash publik dan dengan demikian menemukan nilai yang memiliki gambar cocok dengan pra-gambar. Dengan fungsi pseudo acak Anda tidak dapat melakukannya tanpa kunci (mis. Tanpa lada) karena Anda bahkan tidak dapat menghitung gambar dari nilai tunggal tanpa kunci.

Peran penting $salt Dalam pengaturan ini mulai berlaku jika Anda memiliki akses ke basis data dalam waktu lama dan Anda masih dapat bekerja dengan aplikasi dari luar. Tanpa $salt Anda dapat mengatur kata sandi akun yang Anda kontrol ke nilai yang diketahui $passwordKnown Dan membandingkan hash dengan kata sandi kata sandi yang tidak dikenal $passwordSecret. Sebagai hash($pepper . $passwordKnown)==hash($pepper . $passwordSecret) if dan hanya jika $passwordKnown==$passwordSecret Anda dapat membandingkan kata sandi yang tidak diketahui dengan nilai yang dipilih (sebagai teknis saya menganggap resistensi tabrakan dari fungsi hash). Tetapi dengan garam Anda mendapatkan hash($pepper . $salt1 . $passwordKnown)==hash($pepper . $salt2 . $passwordSecret) jika dan hanya jika $salt1 . $passwordKnown == $salt2 . $passwordSecret Dan sebagai $salt1 Dan $salt2 Dipilih secara acak untuk $passwordKnown Dan masing-masing $passwordSecret Garam tidak akan pernah sama (dengan asumsi nilai acak yang cukup besar seperti 256bit) dan Anda tidak dapat lagi membandingkan kata sandi satu sama lain.

195
Jesper M

(Catatan: menggunakan garam hanya setengah dari pekerjaan; Anda juga perlu membuat fungsi hash lambat - sehingga menyerang satu kata sandi entropi rendah masih sulit. Kelambatan biasanya dicapai melalui beberapa iterasi, atau hashing rangkaian dari 10.000 salinan garam dan kata sandi.)

Apa yang dilakukan "lada" Anda adalah ia mengubah hash menjadi MAC . Membuat MAC yang baik dan aman dari fungsi hash tidak mudah, jadi Anda sebaiknya menggunakan HMAC daripada konstruksi buatan sendiri (cara teoretis menempatkan itu adalah bahwa fungsi hash yang tahan benturan tidak selalu bisa dibedakan dari Oracle acak).

Dengan MAC, Anda dapat mendapatkan beberapa keamanan dalam arti berikut: mungkin, akses baca basis data oleh penyerang tidak lagi menjadi masalah nyata. Kunci MAC ("lada") dapat berkonsentrasi kebutuhan kerahasiaan. Namun, ini bergantung pada MAC yang juga merupakan fungsi satu arah, yang merupakan properti yang akan Anda dapatkan dari banyak konstruksi MAC (termasuk HMAC) tetapi tidak benar-benar dijamin secara kriptografis (ada seluk-beluk).

"Lada" menyiratkan bahwa Anda memiliki kunci untuk dikelola, termasuk penyimpanan aman dengan cara yang menolak untuk reboot. Kunci kecil dan pas di RAM, tetapi, karena persyaratan penyimpanan, tidak jelas apakah itu benar-benar meningkatkan keamanan. Seorang penyerang yang dapat membaca seluruh database biasanya juga dapat membaca seluruh harddisk, termasuk file "yang dilindungi". Ukuran kecil kunci dapat memungkinkan beberapa pengaturan lanjutan, mis. kunci disimpan pada kartu pintar yang digunakan saat boot tetapi tidak dibiarkan terhubung setelah itu. Singkatnya, apakah merica sepadan dengan usaha sepenuhnya tergantung pada konteks - secara umum, saya akan merekomendasikan menentangnya, untuk menghindari kompleksitas tambahan.

90
Thomas Pornin

Saya ingin menunjukkan apa yang benar-benar dapat dilakukan oleh lada.

Kapan lada membantu?

Seperti yang lain telah ditunjukkan, menambahkan lada hanya merupakan keuntungan, selama penyerang memiliki akses ke nilai hash dalam database, tetapi tidak memiliki kontrol atas server, dan karena itu tidak tidak tahu lada. Ini khas untuk injeksi SQL, mungkin salah satu serangan yang lebih sering digunakan, karena sangat mudah dilakukan.

Apa yang meningkatkan lada?

$hashValue = bcrypt('12345', $cost, $salt);

Kata sandi ini dapat Anda peroleh dengan mudah dengan serangan kamus, meskipun Anda menggunakan fungsi derivasi kunci dengan benar. Masukkan kata sandi yang paling sering digunakan ke dalam kamus dan paksa dengan kata sandi yang lemah ini. Sangat mungkin kami menemukan kata sandi dalam banyak kasus.

$hashValue = bcrypt('12345anm8e3M-83*2cQ1mlZaU', $cost, $salt);

Dengan lada, kata sandi yang lemah bertambah panjang, sekarang berisi karakter khusus, dan yang lebih penting, Anda tidak akan menemukannya di kamus. Jadi, selama lada tetap rahasia, itu memang mencegah serangan kamus, dalam hal ini dapat melindungi kata sandi yang lemah.

Edit:

Ada cara yang lebih baik untuk menambahkan kunci sisi server, daripada menggunakannya sebagai lada. Dengan merica, seorang penyerang harus mendapatkan hak istimewa tambahan di server untuk mendapatkan kunci. Keuntungan yang sama kita dapatkan dengan menghitung hash pertama, dan kemudian mengenkripsi hash dengan kunci sisi server (enkripsi dua arah). Ini memberi kita opsi untuk bertukar kunci kapan pun diperlukan.

$hash = bcrypt($passwort, $salt);
$encryptedHash = encrypt($hash, $serverSideKey);
26
martinstoeckli

Makalah tentang penemuan penggaraman dan iterasi, untuk kata sandi Unix ( Keamanan Kata Sandi: A Case History, Morris & Thompson, 1978 ), juga menggambarkan padanan lada:

Delapan karakter pertama kata sandi pengguna digunakan sebagai kunci untuk DES; maka algoritma tersebut digunakan untuk mengenkripsi konstanta. Meskipun konstanta ini adalah nol pada saat ini, ia mudah diakses dan dapat dibuat bergantung pada instalasi.

Saya belum pernah mendengarnya digunakan. Apakah ada orang lain?

9
nealmcb

Hanya BTW, Panduan Nend Digital Idendity (Draft) baru sangat merekomendasikan untuk menggunakan Pepper juga:

https://pages.nist.gov/800-63-3/sp800-63b.html#sec5

5.1.1.2 Verifikasi Rahasia Dihafal:

... Fungsi hash yang dikunci (mis., HMAC [FIPS198-1]), dengan kunci disimpan secara terpisah dari autentikator hash (mis., Dalam modul keamanan perangkat keras) HARUS digunakan untuk lebih jauh menolak serangan kamus terhadap autentikasi hash yang tersimpan.

7
eckes

Pertimbangkan skenario ini:

Saya akan masuk ke situs web X menggunakan injeksi SQL untuk mengambil daftar pengguna, dengan hash dan garam kata sandi mereka. Misalkan situs web X juga menggunakan lada global.

Yang harus saya lakukan hanyalah mendaftarkan pengguna di situs web X dengan nama pengguna dan kata sandi yang saya kenal sebelum injeksi SQL. Saya kemudian akan tahu, untuk catatan tertentu dalam database, hash kata sandi, kata sandi teks biasa, garam (disimpan sebagai teks biasa) dan akan sepele bagi saya untuk memecahkan lada global berdasarkan rekaman yang satu ini .

Jadi sungguh, lada akan menjadi cara untuk memperlambat penyerang untuk waktu overhead yang sepele. Mereka tidak perlu dengan paksa memaksakan kata sandi + garam + lada, sebagaimana dimaksud, hanya lada.

Di atas adalah bentuk serangan plaintext yang dipilih. Selama penyerang mengetahui algoritma (hash ()), output ($ hashed_password), dan semua kecuali salah satu dari input ("konstanta" $ garam & $ kata sandi dan "variabel" $ lada), mereka dapat "menyelesaikannya untuk x "Seperti persamaan aljabar linier (h = s + p + x == hsp = x), tetapi dengan kekuatan kasar tentu saja. Membuat lada lebih panjang dari 56 byte (448 bit), batas bcrypt, meningkatkan biaya waktu dan sebagus bcrypt tetapi masih mungkin tidak sebaik scrypt. Jadi, selama lada cukup lama, itu merupakan peningkatan.

4
Alex R

Tidak terlalu akrab dengan bagaimana server dapat menyembunyikan konstanta lada global, tetapi pendapat saya adalah cepat atau lambat seorang peretas yang telah menembus server akan mencari cara untuk menangkap nilai lada. Untuk membuat nilai lada benar-benar aman akan membutuhkan perangkat keras khusus. Salah satu cara untuk melakukan ini adalah dengan menggunakan papan FPGA yang terpasang di server. FPGA akan berisi kode yang digunakan untuk melakukan hash termasuk nilai lada dan semua perhitungan hash terjadi di dalam FPGA. Dengan FPGA, pemrograman dapat menjadi fungsi satu arah. Lada dapat diprogram dalam tetapi tidak ada instruksi yang dapat dikirim untuk membacanya kembali. Lada akan disimpan di selembar kertas yang terkunci di brankas. Jika lada adalah 128+ bit yang dihasilkan secara acak, tidak akan ada cara praktis untuk menentukannya.
Tidak yakin seberapa praktis ini karena akan meningkatkan biaya perangkat keras server.

1
Brian Sparks