Di mana Anda menyimpan string garam Anda?

250

Saya selalu menggunakan string garam per entri yang tepat saat hashing passwords untuk penyimpanan database. Untuk kebutuhan saya, menyimpan garam di DB di sebelah kata sandi hash selalu berfungsi dengan baik.

Namun, beberapa orang merekomendasikan agar garam disimpan secara terpisah dari database. Argumen mereka adalah bahwa jika database dikompromikan, penyerang masih dapat membangun tabel pelangi dengan mempertimbangkan string garam tertentu untuk memecahkan satu akun pada suatu waktu. Jika akun ini memiliki hak admin, maka ia bahkan mungkin tidak perlu memecahkan yang lain.

Dari sudut pandang keamanan, apakah layak menyimpan garam di tempat yang berbeda? Pertimbangkan aplikasi web dengan kode server dan DB pada mesin yang sama. Jika garam disimpan dalam file flat di mesin itu, kemungkinan adalah bahwa jika database dikompromikan, file garam juga akan.

Apakah ada solusi yang disarankan untuk ini?

friedo
sumber
9
Jika ada tempat di mana Anda dapat menyimpan garam yang tidak bisa didapatkan oleh si penyerang, maka Anda juga harus menyimpan kata sandi di sana. Tetapi mengapa tidak menggunakan garam yang berbeda untuk setiap kata sandi?
jrockway
8
Dia menggunakan garam berbeda untuk setiap kata sandi, jrockway.
Amber
9
Berapa besar garam Anda? Garam Anda harus cukup besar (32 bit?) Sehingga praktis tidak ada peluang bahwa tabel pelangi telah dihitung sebelumnya.
M. Dudley
@emddudley hari ini saya sudah terbiasa menggunakan integer 64-bit sebagai garam, tetapi tidak ada alasan saya tidak bisa membuatnya lebih lama.
friedo
10
Penulis PWDTK di sini sourceforge.net/projects/pwdtknet , jujur ​​saya tidak akan khawatir dan saya hanya akan menyimpan garam dalam DB yang sama dengan kata sandi. Anda harus selalu mengasumsikan garam diketahui sebagai penyerang, jadi fokus Anda harus menggunakan garam CRYPTO-RANDOM BESAR dan melakukan peregangan kunci yang cukup (iterasi dalam PBKDF2) sehingga membuat bahkan satu meja pelangi untuk satu garam yang dikenal tidak layak. Jujur apa yang Anda coba capai dengan meletakkan garam di tempat lain adalah "Keamanan oleh Ketidakjelasan" dan umumnya tidak bermanfaat ketika Anda melihat hal-hal seperti server lain yang berpotensi turun.
thashiznets

Jawaban:

259

Maksud dari tabel pelangi adalah bahwa mereka dibuat terlebih dahulu dan didistribusikan secara massal untuk menghemat waktu perhitungan bagi orang lain - dibutuhkan waktu yang lama untuk menghasilkan tabel pelangi dengan cepat seperti halnya untuk memecahkan kata sandi + kombinasi garam secara langsung (karena efektif apa yang dilakukan ketika membuat tabel pelangi adalah pra-menjalankan perhitungan untuk memaksa hash), sehingga argumen bahwa dengan mengetahui garam seseorang dapat "menghasilkan tabel pelangi" adalah palsu.

Tidak ada gunanya menyimpan garam dalam file terpisah selama itu berdasarkan per pengguna - titik dari garam hanyalah membuatnya sehingga satu tabel pelangi tidak dapat memecahkan setiap kata sandi dalam DB.

Amber
sumber
17
Sepakat. Model ancaman yang Anda lindungi terhadap dengan menyimpan garam secara terpisah adalah pengguna yang entah bagaimana dapat mengakses garam di DB melalui cara jahat, tetapi bukan hash (dalam DB). Dan orang itu akan mulai menghitung tabel pelangi di muka, dengan asumsi dia akan dapat menemukan hash nanti. Bukan tidak mungkin, tetapi juga tidak sepadan dengan upaya rekayasa untuk bertahan di jalur serangan tunggal ini.
Tom Ritter
Posting yang bagus, saya bertanya-tanya hal yang sama. Saya tidak pernah memikirkan garam per pengguna. Saya berpikir bahwa satu garam akan bekerja untuk semua pengguna. Bagaimana dengan garam yang disimpan sebagai file XML yang dimuat oleh App Server? atau mungkin entah bagaimana hardcoded menjadi servlet?
jigzat
9
@Jigzat - Penggaraman tidak ada gunanya jika Anda tidak memiliki garam terpisah untuk setiap pengguna. Tujuan dari garam adalah untuk membuat memecah hash sebagai tugas terpisah untuk setiap kata sandi pengguna; jika garamnya sama untuk mereka semua maka itu tidak terjadi.
Amber
3
@TomRitter itu bukan satu-satunya kasus. Anda menganggap bahwa semua kata sandi itu rumit. beberapa penyerang mungkin mengambil garam dan hash dan hanya memeriksa 10.000 kata sandi yang paling umum. dengan begitu mereka akan mendapatkan jumlah orang yang layak. Namun, jika mereka tidak memiliki akses ke garam, itu mirip dengan pengguna yang memiliki kata sandi yang lebih aman. sekarang, seberapa besar kemungkinan bahwa basis data garam akan tetap aman sementara basis data kata sandi dicuri untuk diperdebatkan, tapi itu masalah tersendiri.
chacham15
@ Amm, saya percaya TomRitter benar. Menyimpan garam secara terpisah berarti perbedaan antara memaksa penyerang untuk menggunakan serangan brute force versus serangan kamus yang lebih mudah. Jika Anda tahu garamnya, Anda bisa menambahkannya saat menjalankan serangan kamus pabrik. Jika Anda dapat 100% mempertahankan garam, Anda bisa menggunakan garam yang sama dan memaksa penyerang untuk memaksa semuanya (bahkan untuk pengguna yang menggunakan "kata sandi" sebagai kata sandi mereka). Tetapi bisakah Anda mempertahankan garam Anda .... mungkin tidak. Jadi mungkin juga mengurangi titik kegagalan dengan menyimpannya di sebelah hash dan menegakkan aturan kata sandi yang lebih kuat.
Ultratrunks
35

Saya akan memberikan pandangan yang sedikit berbeda tentang ini.

Saya selalu menyimpan garam yang dicampur dengan hash-password asin.

Sebagai contoh, saya akan meletakkan bagian pertama dari garam sebelum kata sandi asin, dan bagian terakhir dari garam setelah kata sandi asin. Aplikasi ini menyadari desain ini sehingga dapat mengambil data ini, dan mendapatkan garam dan hash kata sandi asin.

Alasan saya untuk pendekatan ini:

Jika kata sandi / hash data dikompromikan dan jatuh ke tangan seorang penyerang, penyerang tidak akan tahu apa garamnya dari melihat data. Dengan cara ini penyerang tidak bisa secara praktis melakukan serangan brute-force untuk mendapatkan kata sandi yang cocok dengan hash, karena ia tidak tahu hash untuk memulai dan tidak memiliki cara untuk mengetahui bagian mana dari data yang merupakan bagian dari garam, atau bagian dari hash kata sandi asin ( kecuali dia tahu logika otentikasi aplikasi Anda ).

Jika hash kata sandi asin disimpan apa adanya, maka serangan brute-force dapat dilakukan untuk mendapatkan kata sandi yang ketika asin dan hash menghasilkan data yang sama dengan hash kata sandi asin.

Namun, misalnya, bahkan jika hash kata sandi asin disimpan apa adanya, tetapi ditangguhkan dengan byte acak tunggal, selama penyerang tidak menyadari bahwa byte pertama ini harus dibuang, ini juga akan meningkatkan kesulitan serangan. Aplikasi Anda akan tahu untuk membuang byte pertama data saat digunakan untuk mengautentikasi pengguna Anda.

Kesimpulan untuk ini ..

1) Jangan pernah menyimpan data yang digunakan aplikasi otentikasi Anda dalam bentuk persisnya.

2) Jika memungkinkan, jaga kerahasiaan logika otentikasi Anda untuk keamanan tambahan.

Selangkah lebih maju ..

Jika Anda tidak dapat merahasiakan logika otentikasi aplikasi Anda - banyak orang tahu bagaimana data Anda disimpan dalam database. Dan misalkan Anda telah memutuskan untuk menyimpan hash kata sandi asin yang dicampur bersama dengan garam, dengan sebagian garam mendahului hash kata sandi asin, dan sisa garam menambahkannya.

Saat membuat garam acak, Anda juga bisa secara acak menentukan proporsi garam yang akan Anda simpan sebelum / setelah hash kata sandi asin.

Misalnya, Anda menghasilkan garam acak sebesar 512 byte. Anda menambahkan garam ke kata sandi Anda, dan mendapatkan hash SHA-512 dari kata sandi asin Anda. Anda juga menghasilkan bilangan bulat acak 200. Anda kemudian menyimpan 200 byte pertama dari garam, diikuti oleh hash kata sandi asin, diikuti oleh sisa garam.

Saat mengautentikasi input kata sandi pengguna, aplikasi Anda akan melewati string, dan menganggap 1 byte pertama dari data adalah 1 byte pertama dari garam, diikuti oleh hash asin. Pass ini akan gagal. Aplikasi akan melanjutkan dengan menggunakan 2 byte pertama dari data sebagai 2 byte pertama dari garam, dan ulangi sampai hasil positif ditemukan setelah menggunakan 200 byte pertama sebagai 200 byte pertama dari garam. Jika kata sandi salah, aplikasi akan terus mencoba semua permutasi sampai tidak ada yang ditemukan.

Kelebihan dari pendekatan ini:

Keamanan yang ditingkatkan - bahkan jika logika otentikasi Anda diketahui, logika yang tepat tidak diketahui pada saat kompilasi. Praktis mustahil untuk melakukan serangan brute-force, bahkan dengan pengetahuan tentang logika yang tepat. Peningkatan panjang garam akan meningkatkan keamanan lebih lanjut.

Kontra dari pendekatan ini:

Karena logika yang tepat disimpulkan pada saat run-time, pendekatan ini sangat intensif CPU. Semakin lama panjang garam, semakin intensif pendekatan CPU ini.

Otentikasi kata sandi yang salah akan melibatkan biaya CPU tertinggi. Ini bisa menjadi kontra-produktif untuk permintaan yang sah, tetapi meningkatkan keamanan terhadap penyerang.

Pendekatan ini dapat diimplementasikan dengan berbagai cara, dan dapat dibuat lebih aman dengan menggunakan garam lebar variabel dan / atau hash kata sandi asin.

Ibraheem
sumber
9
Dengan pendekatan Anda, Anda hanya menambahkan rahasia untuk proses hashing Anda (algoritma yang menggunakan garam). Rahasia ini dapat Anda tambahkan dengan lebih mudah dengan menambahkan lada ke garam, saya mencoba menunjukkan ini dalam tutorial saya . Fungsi hash modern seperti BCrypt akan menerapkan garam sendiri, menggunakan garam asli di setiap iterasi, jadi Anda tetap tidak memiliki kendali atas ini.
martinstoeckli
@martinstoeckli Meskipun Anda benar bahwa BCrypt menerapkan garam sendiri, penyimpanan garam + hash terserah Anda sebagai pengembang. Jadi, Anda bisa dengan mudah menambahkan merica ke dalam garam + hash dan bertahan di basis data. Kemudian, pada pengambilan berikutnya, Anda membaca nilai dari database, menghapus nilai lada, dan meneruskan nilai yang tersisa ke BCrypt.
PeterToTheThird
2
@PeterToTheThird - Ini akan meniadakan keuntungan lada. Lada menambahkan rahasia sisi server, dan hanya berfungsi asalkan tetap rahasia (berlawanan dengan garam). Serangan tipikal adalah SQL-injection, ketika seseorang mendapatkan akses ke database tetapi tidak ke kode, lada yang disimpan dalam database akan sia-sia. Sebagian besar implementasi BCrypt akan menambahkan garam secara otomatis ke nilai hash yang dihasilkan, sehingga nilai ini sudah mengandung garam, faktor biaya, algoritme, dan hash. String ini dapat disimpan dalam bidang tunggal dengan panjang 60 karakter.
martinstoeckli
Untuk menambahkan, saat menggunakan fungsi "penguatan kunci" seperti BCrypt, Anda tidak memiliki kendali atas penggunaan garam. Namun, jika Anda ingin menggunakan lada, Anda hanya perlu menambahkan lada ke garam, dan menggunakannya sebagai "garam lada" sebagai pengganti input "garam" ke fungsi hashing. "Lada" kemudian adalah bagian data yang cocok yang tidak disimpan dalam database, tetapi tertanam dalam kode otentikasi, atau disimpan di lokasi aman lainnya. Saya mendekati masalah dari perspektif umum, menggunakan SHA-512 sebagai fungsi contoh, tetapi BCrypt dll juga dapat digunakan dengan cara yang sama.
Ibraheem
2
@martinstoeckli - ya, implementasi sebenarnya tergantung pada fungsi hash mana yang Anda gunakan. Jelas Anda perlu mempertimbangkan parameter dan output dari fungsi hash saat menerapkan logika otentikasi Anda. Pada akhirnya, lada hanyalah variabel lain yang dimasukkan ke dalam fungsi hashing Anda, yang tidak disimpan di lokasi yang sama dengan garam dan hash.
Ibraheem
23

Seringkali, mereka diawali dengan hash dan disimpan di bidang yang sama.

Tidak perlu menyimpannya secara terpisah - intinya adalah menggunakan garam acak untuk setiap kata sandi sehingga tabel pelangi tunggal tidak dapat digunakan terhadap seluruh rangkaian hash kata sandi Anda. Dengan garam acak, penyerang harus memaksa setiap hash secara terpisah (atau menghitung tabel pelangi untuk semua kemungkinan garam - jauh lebih banyak pekerjaan).

Jika Anda memiliki lokasi penyimpanan yang lebih aman, masuk akal untuk menyimpan hash di sana.

tak seorangpun
sumber
4
Tapi apa yang terjadi jika semua kata sandi hash bocor termasuk garam yang cocok? Bukankah itu sama tidak amannya?
mghaoui
10
@mghaoui Tetapi jika Anda ingin tahu "kata sandi" Anda masih harus membuat Tabel Pelangi untuk masing-masing dan setiap garam, kecuali beberapa garamnya sama.
Franklin
4

Berdasarkan buku Aplikasi Aplikasi Web ASP.NET MVC 4 karya William Penberthy:

  1. Mendapatkan akses ke garam yang disimpan dalam basis data terpisah membutuhkan peretas untuk meretas dua basis data yang berbeda untuk mendapatkan akses ke garam dan kata sandi asin. Menyimpannya dalam tabel yang sama dengan kata sandi, atau bahkan tabel lain dari database yang sama, akan berarti bahwa ketika peretas mendapatkan akses ke database, mereka akan memiliki akses ke garam dan hash kata sandi. Karena keamanan mencakup proses membuat peretasan ke dalam sistem terlalu mahal atau memakan waktu untuk sia-sia, menggandakan jumlah akses yang harus diperoleh peretas harus membuat sistem lebih aman.
  2. Kemudahan penggunaan adalah alasan utama untuk menjaga garam di database yang sama dengan kata sandi hash. Anda tidak perlu memastikan bahwa dua database selalu tersedia pada saat yang sama, dan selalu sinkron. Keuntungan memiliki garam adalah minimal jika setiap pengguna memiliki garam acak karena walaupun hal itu dapat membuat pencarian kata sandi seseorang lebih mudah, jumlah kekuatan yang diperlukan untuk memecahkan kata sandi sistem secara keseluruhan akan tinggi. Dalam tingkat diskusi ini, itulah yang benar-benar diharapkan: untuk melindungi kata sandi. Jika peretas memperoleh salinan basis data, data aplikasi Anda sudah disusupi. Pada titik ini, masalahnya adalah mengurangi risiko pengguna karena potensi kata sandi bersama.
  3. Persyaratan untuk memelihara dua tautan yang terpisah, basis data sangat luas. Memang, itu menambah persepsi keamanan, tetapi satu-satunya keuntungan yang diberikannya adalah melindungi kata sandi, satu elemen data. Jika setiap bidang dalam basis data dienkripsi secara individual, dan garam yang sama ini digunakan untuk itu, akan lebih masuk akal untuk menyimpannya secara terpisah dari data karena keamanan dasar sistem Anda ditingkatkan.
DaNeSh
sumber
Jika aplikasi dapat mengotentikasi ke kedua database, bukankah pada dasarnya sama dengan jika itu adalah satu database, jika penyerang telah mengkompromikan kode aplikasi?
John Ernest
0

Maksud sebuah garam adalah membuat semua tabel pelangi tidak berguna dan membutuhkan set baru untuk dibuat. Hanya butuh waktu lama untuk menebak seutas tali untuk membuat meja pelangi. Misalnya hash SHA-256 "password" adalah 5e88 4898 da28 0471 51d0 e56f 8dc6 2927 7360 3d0d 6aab bdd6 2a11 ef72 1d15 42d8. Setelah garam ditambahkan, seperti "badpassword" string baru yang akan di-hash adalah "passwordbadpassword" yang, karena efek longsoran, secara dramatis mengubah output, menjadi 457b f8b5 37f1 802e f9c8 2e46 b8d3 f8b5 721b 7cbb d485 f0bb e523 bfbe 73e6 58d6.

Biasanya, garam hanya disimpan dalam basis data yang sama dengan kata sandi, juga karena jika satu basis data diretas, kemungkinan yang lain juga.

Eric Jin
sumber