Membersihkan Kata Sandi Pengguna

98

Bagaimana cara saya keluar atau membersihkan kata sandi yang diberikan pengguna sebelum saya mencirikannya dan menyimpannya di database saya?

Ketika pengembang PHP mempertimbangkan hashing kata sandi pengguna untuk tujuan keamanan, mereka sering cenderung memikirkan kata sandi itu seperti data lain yang disediakan pengguna. Subjek ini sering muncul dalam pertanyaan PHP terkait dengan penyimpanan kata sandi; pengembang sering kali ingin membersihkan kata sandi menggunakan fungsi seperti escape_string()(dalam berbagai iterasi) htmlspecialchars(),, addslashes()dan lainnya sebelum melakukan hashing dan menyimpannya di database.

Jay Blanchard
sumber
1
Anda dapat menggunakan encode base64
MSS
Tidak ada @MSS, Anda tidak boleh melakukannya karena base64 adalah pengkodean , bukan enkripsi atau hashing . Kata sandi harus selalu di- hash .
Jay Blanchard
1
Maksud saya sebelum hash;)
MSS
Anda tidak boleh dan tidak perlu melakukan itu sebelum melakukan hashing. Ini akan menyebabkan Anda harus menulis kode tambahan yang tidak perlu @MSS
Jay Blanchard

Jawaban:

99

Anda tidak boleh melarikan diri, memangkas, atau menggunakan mekanisme pembersihan lainnya pada kata sandi yang akan Anda hashing dengan PHP password_hash()karena sejumlah alasan, yang terbesar adalah karena melakukan pembersihan tambahan pada kata sandi memerlukan kode tambahan yang tidak perlu.

Anda akan membantah (dan Anda melihatnya di setiap posting di mana data pengguna diterima untuk digunakan di sistem Anda) bahwa kami harus membersihkan semua masukan pengguna dan Anda akan benar untuk setiap informasi lain yang kami terima dari pengguna kami. Kata sandi berbeda. Sandi yang di-hash tidak dapat menawarkan ancaman injeksi SQL karena string diubah menjadi hash sebelum disimpan dalam database.

Tindakan hashing kata sandi adalah tindakan membuat kata sandi aman untuk disimpan di database Anda. Fungsi hash tidak memberikan arti khusus pada byte mana pun, jadi tidak ada pembersihan input yang diperlukan untuk alasan keamanan

Jika Anda mengikuti mantra yang memungkinkan pengguna untuk menggunakan kata sandi / frasa yang mereka inginkan dan Anda tidak membatasi kata sandi , mengizinkan panjang apa pun, sejumlah spasi dan karakter khusus apa pun akan membuat kata sandi / frasa sandi aman apa pun yang terkandung di dalamnya kata sandi. Pada hash yang paling umum (default), PASSWORD_BCRYPTmengubah kata sandi menjadi string lebar 60 karakter yang berisi salt acak bersama dengan informasi kata sandi yang di-hash dan biaya (biaya algoritmik untuk membuat hash):

PASSWORD_BCRYPT digunakan untuk membuat hash sandi baru menggunakan algoritma CRYPT_BLOWFISH. Ini akan selalu menghasilkan hash menggunakan format crypt "$ 2y $", yang selalu memiliki lebar 60 karakter.

Persyaratan ruang untuk menyimpan hash dapat berubah karena metode pencirian yang berbeda ditambahkan ke fungsi, jadi lebih baik selalu lebih baik untuk memperbesar tipe kolom untuk hash yang disimpan, seperti VARCHAR(255)atau TEXT.

Anda dapat menggunakan kueri SQL lengkap sebagai kata sandi Anda dan itu akan di-hash, membuatnya tidak dapat dieksekusi oleh mesin SQL misalnya,

SELECT * FROM `users`;

Bisa di-hash ke $2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G

Mari kita lihat bagaimana metode sanitasi yang berbeda memengaruhi kata sandi -

Kata sandinya adalah I'm a "dessert topping" & a <floor wax>!(Ada 5 spasi di akhir kata sandi yang tidak ditampilkan di sini.)

Saat kami menerapkan metode pemangkasan berikut, kami mendapatkan beberapa hasil yang sangat berbeda:

var_dump(trim($_POST['upassword']));
var_dump(htmlentities($_POST['upassword']));
var_dump(htmlspecialchars($_POST['upassword']));
var_dump(addslashes($_POST['upassword']));
var_dump(strip_tags($_POST['upassword']));

Hasil:

string(40) "I'm a "dessert topping" & a <floor wax>!" // spaces at the end are missing
string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // double quotes, ampersand and braces have been changed
string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // same here
string(48) "I\'m a \"dessert topping\" & a <floor wax>!     " // escape characters have been added
string(34) "I'm a "dessert topping" & a !     " // looks like we have something missing

Apa yang terjadi jika kami mengirimkan ini ke password_hash()? Mereka semua mendapatkan hash, seperti yang dilakukan kueri di atas. Masalahnya muncul saat Anda mencoba memverifikasi kata sandi. Jika kita menggunakan satu atau lebih dari metode ini kita harus menggunakannya kembali sebelum membandingkannya password_verify(). Berikut ini akan gagal:

password_verify($_POST['upassword'], $hashed_password); // where $hashed_password comes from a database query

Anda harus menjalankan kata sandi yang diposting melalui metode pembersihan yang Anda pilih sebelum menggunakan hasil itu dalam verifikasi kata sandi. Ini adalah serangkaian langkah yang tidak perlu dan tidak akan membuat hash menjadi lebih baik.


Menggunakan versi PHP kurang dari 5,5? Anda dapat menggunakan password_hash() paket kompatibilitas .

Anda sebaiknya tidak menggunakan hash sandi MD5 .

Jay Blanchard
sumber
13
Tidak. Jika dia membuat sandi dengan spasi tambahan, yang diizinkan, dia harus menggunakannya saat login @DanBracuk
Jay Blanchard
12
Bagaimana @DanBracuk? Jika kita mengizinkan pengguna untuk mengatur kata sandi yang dia inginkan, termasuk spasi di depan / di belakang?
Jay Blanchard
16
Itulah mengapa kebanyakan hal mengharuskan Anda memasukkan kata sandi pilihan Anda dua kali. Jika pengguna menambahkan spasi secara tidak sengaja, mereka akan mengetahuinya sebelum melangkah lebih jauh. Jika pengguna melakukannya dengan sengaja maka itu bukan masalah.
Aku pernah bergulat dengan beruang.
4
@MargaretBloom, aturan praktisnya hanyalah heuristik. Terkadang kami masih perlu memikirkan semuanya, seperti untuk kata sandi. Anda mengatakan "tidak ada yang tahu bagaimana hal-hal akan berubah di masa depan", tetapi tampaknya jika ada sesuatu yang akan berubah, itulah cara kami melarikan diri dari data sebelum kami memasukkannya ke dalam database, di mana dalam kasus ini pengguna akan menemukan diri mereka terkunci ketika kata sandi mereka tidak lebih lama cocok dengan apa yang kita simpan. Apa bahayanya jika tidak lolos dari hash kata sandi vs. bahaya meloloskan diri dari hash kata sandi?
DavidS
3
Persis: Anda tentu saja akan "meloloskan diri dari hash" dalam arti terbatas dengan meneruskannya dengan benar ke kueri SQL berparameter, di mana beberapa kode di konektor SQL Anda mungkin atau mungkin tidak melakukan apa pun dengannya yang sesuai dengan "pelolosan", Anda tidak ' t tahu dan tidak peduli. Anda tidak perlu menulis kode tertentu untuk mencapainya, karena ini benar-benar rutin untuk semua kueri SQL Anda kecuali Anda sebelumnya telah membuat beberapa keputusan hidup yang buruk.
Steve Jessop
36

Sebelum melakukan hashing kata sandi, Anda harus menormalkannya seperti yang dijelaskan di bagian 4 dari RFC 7613 . Khususnya:

  1. Aturan Pemetaan Tambahan: Setiap contoh ruang non-ASCII HARUS dipetakan ke ruang ASCII (U + 0020); spasi non-ASCII adalah titik kode Unicode yang memiliki kategori umum Unicode "Zs" (dengan pengecualian U + 0020).

dan:

  1. Aturan Normalisasi: Unicode Normalization Form C (NFC) HARUS diterapkan ke semua karakter.

Ini mencoba untuk memastikan bahwa jika pengguna mengetik kata sandi yang sama tetapi menggunakan metode input yang berbeda, kata sandi tersebut masih harus diterima.

legoscia
sumber
3
@DavidS, Buku Mac Amerika Utara yang sangat berkilau (yang digunakan Joe sebelum berangkat) dan komputer kafe internet Taiwan yang tidak terinternasionalisasi dengan baik (yang coba digunakan Joe untuk diunduh adalah kartu penerbangan kembali).
Margaret Bloom
2
Kedengarannya jingoistic. :-) Terimakasih Meskipun.
DavidS
3
Hmm. Jika Anda melakukan ini, Anda juga harus memvalidasi kata sandi untuk menolak kata sandi yang berisi karakter yang belum ditetapkan. Akan sangat buruk jika pengguna menggunakan NEWFANGLED SPACE, yang tidak dikenali oleh aplikasi Anda dan oleh karena itu melakukan hashes apa adanya, lalu Anda mengupgrade Basis Data Karakter Unicode dan tiba-tiba SPACE NEWFANGLED dipetakan ke SPACE sebelum melakukan hashing, sehingga ia tidak dapat lagi memasukkan sandi yang akan di-hash oleh aplikasi Anda ke hash lama.
ruakh
4
@JayBlanchard Karena saat Anda menekan bilah spasi pada satu mesin dan saat Anda menekannya di komputer lain, Anda mungkin mendapatkan dua titik kode Unicode yang berbeda, dan keduanya akan memiliki dua pengkodean UTF-8 yang berbeda, tanpa pengguna menyadarinya. Dapat dikatakan bahwa ini adalah masalah yang ingin Anda abaikan, tetapi RFC 7613 lahir dari masalah kehidupan nyata seperti itu, ini bukan rekomendasi perbaikan.
Kembalikan Monica
1
@ruakh Setelah Anda memutuskan untuk menangani sandi dengan cara tertentu, sandi tersebut harus tetap ditangani seperti itu, atau hal-hal akan rusak untuk kasus penggunaan yang ada. Jika Anda berniat untuk mengubah metode preprocessing di masa mendatang, Anda harus menyimpannya di sepanjang representasi password yang telah diproses dan di-hash. Dengan begitu, setelah Anda menerima input, Anda memilih metode preprocessing / hashing berdasarkan apa yang Anda bandingkan.
Kembalikan Monica