Praktik Terbaik: Kata sandi penggaraman & lada?


145

Saya menemukan sebuah diskusi di mana saya belajar bahwa apa yang saya lakukan sebenarnya bukan penggaraman kata sandi tetapi membumbui mereka, dan saya sejak itu mulai melakukan keduanya dengan fungsi seperti:

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

Mengabaikan algoritma hash yang dipilih (saya ingin ini menjadi diskusi tentang garam & paprika dan bukan algoritma tertentu tapi saya menggunakan yang aman), apakah ini opsi yang aman atau haruskah saya melakukan sesuatu yang berbeda? Bagi mereka yang tidak terbiasa dengan ketentuan:

  • Sebuah garam adalah nilai yang dihasilkan secara acak biasanya disimpan dengan string dalam database yang dirancang untuk membuat tidak mungkin untuk menggunakan tabel hash untuk crack password. Karena setiap kata sandi memiliki garamnya sendiri, mereka semua harus dipaksa secara individual untuk memecahkannya; Namun, karena garam disimpan dalam database dengan hash kata sandi, kompromi database berarti kehilangan keduanya.

  • Sebuah lada adalah nilai statis situs-lebar disimpan secara terpisah dari database (biasanya keras-kode dalam kode sumber aplikasi) yang dimaksudkan untuk menjadi rahasia. Ini digunakan sehingga kompromi dari basis data tidak akan menyebabkan tabel kata sandi seluruh aplikasi menjadi kasar.

Apakah ada sesuatu yang saya lewatkan dan memberi garam & membumbui kata sandi saya pilihan terbaik untuk melindungi keamanan pengguna saya? Apakah ada kelemahan keamanan potensial untuk melakukannya dengan cara ini?

Catatan: Asumsikan untuk tujuan diskusi bahwa aplikasi & database disimpan pada mesin yang terpisah, jangan berbagi kata sandi, dll. Sehingga pelanggaran server database tidak secara otomatis berarti pelanggaran server aplikasi.


3
Tidak cukup duplikat, tetapi sangat terkait: stackoverflow.com/questions/16594613/...
ircmaxell

2

Jawaban:


307

Baik. Melihat yang saya butuhkan untuk menulis tentang ini lebih dan lebih , saya akan melakukan satu jawaban kanonik terakhir pada lada saja.

Kelebihan Terbalik Dari Paprika

Tampaknya cukup jelas bahwa paprika harus membuat fungsi hash lebih aman. Maksud saya, jika penyerang hanya mendapatkan basis data Anda, maka kata sandi pengguna Anda harus aman, bukan? Tampak logis, bukan?

Itu sebabnya banyak orang percaya bahwa paprika adalah ide yang bagus. Masuk akal".

Realitas Paprika

Di bidang keamanan dan kriptografi, "masuk akal" tidak cukup. Sesuatu harus dapat dibuktikan dan masuk akal agar dapat dianggap aman. Selain itu, harus dapat diimplementasikan dengan cara yang dapat dipertahankan. Sistem yang paling aman yang tidak dapat dipertahankan dianggap tidak aman (karena jika ada bagian dari keamanan yang rusak, seluruh sistem berantakan).

Dan paprika tidak cocok dengan model yang dapat dibuktikan atau dipelihara ...

Masalah Teoritis Dengan Paprika

Sekarang kita telah mengatur panggung, mari kita lihat apa yang salah dengan paprika.

  • Memberi makan satu hash ke hash lainnya bisa berbahaya.

    Dalam contoh Anda, Anda lakukan hash_function($salt . hash_function($pepper . $password)).

    Kita tahu dari pengalaman masa lalu bahwa "hanya memberi makan" satu hasil hash ke fungsi hash lain dapat mengurangi keamanan keseluruhan. Alasannya adalah bahwa kedua fungsi hash dapat menjadi target serangan.

    Itu sebabnya algoritma seperti PBKDF2 menggunakan operasi khusus untuk menggabungkannya (hmac dalam kasus itu).

    Intinya adalah bahwa sementara itu bukan masalah besar, itu juga bukan hal yang sepele untuk hanya dibuang. Sistem Crypto dirancang untuk menghindari kasus "harus bekerja", dan sebaliknya berfokus pada kasus "dirancang untuk bekerja".

    Walaupun ini mungkin tampak murni teoretis, sebenarnya tidak. Misalnya, Bcrypt tidak dapat menerima kata sandi yang sewenang-wenang . Jadi lewat bcrypt(hash(pw), salt)memang bisa menghasilkan hash yang jauh lebih lemah daripada bcrypt(pw, salt)jika hash()mengembalikan string biner.

  • Bekerja Melawan Desain

    Cara bcrypt (dan algoritma hashing kata sandi lainnya) dirancang untuk bekerja dengan garam. Konsep lada tidak pernah diperkenalkan. Ini mungkin tampak sepele, tetapi tidak. Alasannya adalah bahwa garam bukanlah rahasia. Itu hanya nilai yang bisa diketahui penyerang. Sebaliknya, lada adalah definisi kriptografi.

    Algoritma hashing kata sandi saat ini (bcrypt, pbkdf2, dll) semuanya dirancang untuk hanya mengambil satu nilai rahasia (kata sandi). Menambahkan rahasia lain ke dalam algoritma belum dipelajari sama sekali.

    Itu tidak berarti itu tidak aman. Itu berarti kita tidak tahu apakah itu aman. Dan rekomendasi umum dengan keamanan dan kriptografi adalah bahwa jika kita tidak tahu, itu tidak benar.

    Jadi sampai algoritma dirancang dan diperiksa oleh cryptographers untuk digunakan dengan nilai rahasia (paprika), algoritma saat ini tidak boleh digunakan dengan mereka.

  • Kompleksitas Adalah Musuh Keamanan

    Percaya atau tidak, Kompleksitas Adalah Musuh Keamanan . Membuat algoritma yang terlihat rumit mungkin aman, atau mungkin juga tidak. Tetapi peluangnya cukup signifikan sehingga tidak aman.

Masalah Penting Dengan Paprika

  • Itu Tidak Dapat Dipertahankan

    Implementasi paprika Anda menghalangi kemampuan untuk memutar kunci lada. Karena lada digunakan pada input ke fungsi satu arah, Anda tidak akan pernah bisa mengubah lada untuk seumur hidup nilainya. Ini berarti bahwa Anda harus membuat beberapa hacks yang kurang baik untuk mendukung rotasi kunci.

    Ini sangat penting karena diperlukan setiap kali Anda menyimpan rahasia kriptografi. Tidak memiliki mekanisme untuk memutar kunci (secara berkala, dan setelah pelanggaran) adalah kerentanan keamanan yang sangat besar.

    Dan pendekatan lada Anda saat ini akan mengharuskan setiap pengguna untuk membuat kata sandi mereka sepenuhnya tidak valid oleh rotasi, atau menunggu sampai login berikutnya untuk memutar (yang mungkin tidak pernah) ...

    Yang pada dasarnya membuat pendekatan Anda tidak dapat dilakukan dengan segera.

  • Ini Membutuhkan Anda Untuk Menggulung Crypto Anda Sendiri

    Karena tidak ada algoritma saat ini yang mendukung konsep lada, itu mengharuskan Anda untuk membuat algoritma atau membuat yang baru untuk mendukung lada. Dan jika Anda tidak dapat segera melihat mengapa itu hal yang sangat buruk:

    Siapa pun, dari amatir yang paling tidak mengerti sampai yang terbaik, dapat membuat algoritma yang tidak dapat ia hancurkan.

    JANGAN PERNAH memutar crypto Anda sendiri ...

Cara yang Lebih Baik

Jadi, dari semua masalah yang dirinci di atas, ada dua cara untuk menangani situasi tersebut.

  • Cukup Gunakan Algoritma Saat Mereka Ada

    Jika Anda menggunakan bcrypt atau scrypt dengan benar (dengan biaya tinggi), semua kata sandi kamus terlemah harus secara statistik aman. Catatan saat ini untuk hashing bcrypt dengan biaya 5 adalah 71k hash per detik. Pada tingkat itu bahkan password acak 6 karakter akan memakan waktu bertahun-tahun untuk dipecahkan. Dan mengingat biaya minimum yang disarankan adalah 10, yang mengurangi hash per detik dengan faktor 32. Jadi kita akan berbicara hanya sekitar 2.200 hash per detik. Pada tingkat itu, bahkan beberapa frase kamus atau modifikasi mungkin aman.

    Selain itu, kita harus memeriksa kelas-kelas kata sandi yang lemah di pintu dan tidak memperbolehkannya masuk. Karena pemecahan kata sandi semakin canggih, demikian juga persyaratan kualitas kata sandi. Ini masih permainan statistik, tetapi dengan teknik penyimpanan yang tepat, dan kata sandi yang kuat, semua orang bisa dibilang sangat aman ...

  • Enkripsi Hash Output Sebelum Penyimpanan

    Ada di dunia keamanan suatu algoritma yang dirancang untuk menangani semua yang kami katakan di atas. Ini adalah cipher blok. Itu bagus, karena itu reversibel, jadi kita bisa memutar kunci (yay! Rawatan!). Ini bagus karena digunakan sesuai desain. Ini bagus karena tidak memberikan informasi kepada pengguna.

    Mari kita lihat garis itu lagi. Katakanlah penyerang mengetahui algoritme Anda (yang diperlukan untuk keamanan, jika tidak, keamanan melalui ketidakjelasan). Dengan pendekatan lada tradisional, penyerang dapat membuat kata sandi penjaga, dan karena dia tahu garam dan hasilnya, dia bisa dengan kasar memaksa lada. Ok, itu pukulan panjang, tapi itu mungkin. Dengan sandi, penyerang tidak mendapatkan apa-apa. Dan karena garamnya acak, kata sandi penjaga bahkan tidak akan membantunya. Jadi yang terbaik bagi mereka adalah menyerang formulir yang dienkripsi. Yang berarti mereka pertama-tama harus menyerang hash terenkripsi Anda untuk memulihkan kunci enkripsi, dan kemudian menyerang hash. Tetapi ada banyak penelitian tentang serangan cipher, jadi kami ingin mengandalkan itu.

TL / DR

Jangan gunakan paprika. Ada sejumlah masalah dengan mereka, dan ada dua cara yang lebih baik: tidak menggunakan rahasia sisi server (ya, tidak apa-apa) dan mengenkripsi hash output menggunakan blok cipher sebelum penyimpanan.


6
Terima kasih telah memasukkan bagian terakhir mengenkripsi nilai hash, ini adalah jawaban yang sepenuhnya dapat saya setujui. Jika enkripsi akan menjadi bagian dari kata sandi api Anda , tidak akan ada alasan untuk tidak menggunakannya, jadi mungkin ... (saya akan senang menulis dokumentasi untuk itu)
martinstoeckli

2
@martinstoeckli: Saya tidak akan setuju untuk menambahkan langkah enkripsi ke API hashing yang disederhanakan. Alasannya adalah bahwa penyimpanan rahasia (kunci) jauh lebih sulit daripada yang disadari orang, dan cukup mudah untuk menembak diri sendiri di kaki. Untuk 99,9% pengguna di luar sana, bcrypt mentah lebih dari cukup untuk semua kecuali kata sandi yang paling sederhana ...
ircmaxell

7
@ircmaxell - Di sisi lain, Anda tidak akan kehilangan apa pun. Dalam kasus terburuk, ketika kunci diketahui, penyerang masih harus memecahkan hash BCrypt (situasi yang sama seperti tanpa enkripsi). Ini tidak sama dengan menyimpan kunci untuk mengenkripsi data, ini tentang menambahkan rahasia sisi server. Bahkan kunci hardcoded akan melindungi kata sandi yang lemah itu, selama penyerang tidak memiliki kendali atas server / kode. Situasi ini tidak jarang: selain dari injeksi SQL, juga membuang cadangan, server yang dibuang ... dapat menyebabkan situasi ini. Banyak pengguna PHP bekerja di server yang dihosting.
martinstoeckli

2
@martinstoeckli Saya harus setuju dengan ircmaxwell di sini, saya tidak berpikir enkripsi itu milik api kata sandi. Meskipun, dapat dicatat bahwa untuk keamanan maksimum mengenkripsi hash Anda adalah ketentuan tambahan yang dapat digunakan.
foochow

Saya punya pertanyaan tentang enkripsi output sebelum penyimpanan. Jika saya tidak salah, kunci enkripsi umumnya digunakan untuk mengenkripsi pesan secara unik, atau sementara. Namun jika Anda memiliki 200.000 kata sandi pengguna yang semuanya dienkripsi dengan kunci yang sama dan disimpan bersama, bukankah itu membuatnya lebih mudah untuk menyerang kunci? Anda sekarang memiliki 200.000 pesan, dibandingkan dengan hanya 1 atau 2.
AgmLauncher

24

Kepalan kita harus berbicara tentang manfaat lada :

  • Lada dapat melindungi kata sandi yang lemah dari serangan kamus, dalam kasus khusus, di mana penyerang memiliki akses baca ke database (berisi hash) tetapi tidak memiliki akses ke kode sumber dengan lada.

Skenario tipikal adalah injeksi SQL, membuang cadangan, server terbuang ... Situasi ini tidak biasa seperti kedengarannya, dan seringkali tidak di bawah kendali Anda (hosting server). Jika Anda menggunakan ...

  • Garam unik per kata sandi
  • Algoritma hashing lambat seperti BCrypt

... kata sandi yang kuat terlindungi dengan baik. Hampir mustahil untuk memaksakan kata sandi yang kuat di bawah kondisi itu, bahkan ketika garamnya diketahui. Masalahnya adalah kata sandi yang lemah, yang merupakan bagian dari kamus brute-force atau turunan dari mereka. Serangan kamus akan mengungkapkannya dengan sangat cepat, karena Anda hanya menguji kata sandi yang paling umum.

Pertanyaan kedua adalah bagaimana cara merica ?

Cara yang sering disarankan untuk menerapkan lada, adalah dengan menggabungkan kata sandi dan lada sebelum meneruskannya ke fungsi hash:

$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);

Namun ada cara lain yang lebih baik:

$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);

Ini tidak hanya memungkinkan untuk menambahkan rahasia sisi server, tetapi juga memungkinkan untuk menukar $ serverSideKey, jika ini diperlukan. Metode ini melibatkan sedikit lebih banyak pekerjaan, tetapi jika kode itu pernah ada (perpustakaan) tidak ada alasan untuk tidak menggunakannya.


Jadi Anda bisa mengatakan lada memang menambah keamanan hanya dengan garam, singkatnya? Terima kasih atas bantuan tentang cara menerapkan.
Glitch Desire

1
@LightningDust - Ya, untuk kata sandi yang lemah, selama lada tetap rahasia. Ini mengurangi beberapa jenis ancaman yang didefinisikan dengan baik.
martinstoeckli

@martinstoeckli jelas cara yang bagus untuk mengimplementasikan ini. Senang melihat bahwa seseorang dengan pengalaman keamanan mendukung metode ini. Apakah AES_ENCRYPT($passwordHash, $serverSideKey)panggilan MySQL juga menjadi cara yang tepat untuk mengimplementasikan ini?
foochow

1
@Foo_Chow - Saya tidak tahu implementasi fungsi MySQL, tetapi tampaknya mereka menggunakan mode EBC, untuk menghindari vektor-IV. Bersama dengan plaintext yang dikenal (nilai hash selalu dimulai dengan karakter yang sama), ini bisa menjadi masalah. Di beranda saya menerbitkan contoh implementasi, yang menangani enkripsi ini.
martinstoeckli

@martinstoeckli menarik, tidak terlalu akrab dengan konsep; namun sepertinya IV akan diinginkan untuk hasil yang paling kuat. Tampaknya tidak menambah banyak biaya tambahan untuk manfaat tambahan.
foochow

2

Maksud dari garam dan merica adalah untuk meningkatkan biaya pencarian kata sandi yang telah dihitung sebelumnya, yang disebut tabel pelangi.

Secara umum berusaha menemukan tabrakan untuk hash tunggal itu sulit (dengan asumsi hash aman). Namun, dengan hash pendek, dimungkinkan untuk menggunakan komputer untuk menghasilkan semua hash yang mungkin menjadi pencarian ke hard disk. Ini disebut Tabel Pelangi. Jika Anda membuat tabel pelangi, Anda dapat pergi ke dunia dan dengan cepat menemukan kata sandi yang masuk akal untuk semua hash (tidak tawar yang tidak ditaburi).

Inti dari merica adalah membuat tabel pelangi yang diperlukan untuk meretas daftar kata sandi Anda menjadi unik. Dengan demikian membuang lebih banyak waktu pada penyerang untuk membangun meja pelangi.

Namun, intinya adalah membuat tabel pelangi untuk setiap pengguna menjadi unik bagi pengguna, yang semakin meningkatkan kompleksitas serangan.

Sungguh titik keamanan komputer hampir tidak pernah membuatnya (secara matematis) tidak mungkin, hanya secara matematis dan fisik tidak praktis (misalnya dalam sistem yang aman akan mengambil semua entropi di alam semesta (dan banyak lagi) untuk menghitung kata sandi satu pengguna).


Jadi apakah garam + lada menawarkan keamanan lebih dari sekadar garam? Atau lebih baik saya menjatuhkan lada dan menjalankan lebih banyak iterasi scrypt?
Glitch Desire

2
Hal utama tentang tabel pelangi adalah Anda tidak membuat satu untuk serangan tertentu, Anda mengunduh yang sudah ada sebelumnya. Ada tabel pelangi yang panjang tersedia untuk algoritma hash populer hanya google jauhnya!
Richard

1
@ LightningDust Saya tidak bisa memikirkan alasan apa pun sendiri. Namun Richard di utas lainnya menghasilkan satu. Anda dapat menyembunyikan lada di kode sumber Anda, yang berarti tempat lain yang perlu diakses oleh penyerang Anda, hanya untuk mendapatkan meja pelangi bersama.
Aron

@Ron - Yah itulah yang saya pikir, karena kami memiliki server aplikasi yang terpisah dari server basis data (yaitu, jika Anda masuk rootke server db kami, Anda masih tidak memiliki akses ke server aplikasi kami), yang menyembunyikan lada di kode sumber (di file config kami) akan memberikan keamanan tambahan.
Glitch Desire

1

Tidak dapat melihat menyimpan nilai yang dikodekan dalam kode sumber Anda memiliki relevansi keamanan apa pun. Ini keamanan melalui ketidakjelasan.

Jika seorang hacker mendapatkan basis data Anda, ia akan dapat mulai dengan kasar memaksa kata sandi pengguna Anda. Tidak perlu waktu lama bagi peretas untuk mengidentifikasi lada Anda jika ia berhasil memecahkan beberapa kata sandi.


1
Itu akan membuat tabel pelangi yang sudah dikomputasi untuk tabel kata sandi yang tidak tawar tidak berguna. Singkatnya, bahkan jika penyerang tahu lada Anda, ia perlu membuat meja pelangi baru.
Aron

3
Ini memperkuat hash berdasarkan data yang tidak tersedia di database, yang merupakan hal yang baik. Hal-hal dalam database dapat berpotensi terungkap dalam kerentanan - kecil kemungkinannya nilai dalam kode akan diakses dengan cara yang sama.
Richard

Garam adalah fungsi satu arah, bahkan dengan berhasil memaksa kata sandi hanya akan memberi Anda kata sandi itu, dan tidak akan membantu Anda untuk mendapatkan nilai lada itu sendiri.
Glitch Desire

1
@LightningDust Saya pikir maksud Anda "Hash adalah fungsi trapdoor". Ya tidak mungkin untuk mengetahui garam dan / atau lada Anda dari hash yang aman (pada kenyataannya itulah definisi hash yang aman).
Aron

6
@Aron Security Through Obscurity dapat menjadi teknik yang valid digunakan sebagai lapisan pertahanan. Intinya adalah bahwa itu tidak boleh diandalkan sebagai pertahanan, tetapi sebaliknya digunakan untuk "memperlambat penyerang". Jika bukan itu masalahnya, sesuatu seperti honeypot tidak akan digunakan. Sebagai gantinya, kita dapat secara efektif menggunakan keamanan melalui ketidakjelasan untuk membantu memperlambat penyerang, selama kita tidak bergantung padanya untuk keamanan aplikasi kita.
ircmaxell
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.