Alternatif untuk mengirim sandi teks biasa saat masuk
Catatan: Saya sudah membaca Bolehkah mengirim sandi teks biasa melalui HTTPS? dan keamanan https - haruskah kata sandi di-hash sisi server atau sisi klien? , tetapi ini tentang metode penggantian tertentu (lihat di bawah).
Setelah membaca artikel tentang metode otentikasi baru di blog Cloudflare , saya melihat POST
permintaan yang dikirim saat mengautentikasi dengan "Alat Pengembang> Jaringan". Banyak situs web populer (Reddit, HN, dll.) Masih mengirimkan kata sandi dalam bentuk teks biasa dalam POST
permintaan ( diamankan SSL) (lihat gambar di bawah).
Apakah metode login ini masih standar industri?
Apakah alternatif berikut lebih aman daripada mengirim sandi teks biasa melalui HTTPS?
signup: klien menghasilkan acak
salt
, dan mengirimkan tupel(username, salt, hash(plain_password + salt))
melaluiPOST
permintaan. Kemudian sandi teks biasa tidak pernah mencapai server.login berikutnya: server harus mengirim
salt
kembali ke setiap klien yang mencoba untuk login dengan diberikanusername
, sehingga klien dapat hash dengan garam yang sama. Jadi ini berarti bahwa server mengungkapkansalt
kepada siapa pun yang mencoba masuk dengan nama pengguna tertentu.manfaat: server menyimpan kata sandi + hash (yang standar) tetapi juga server tidak pernah, pernah, melihat kata sandi teks biasa sekali pun (jadi jika server disusupi, risikonya terbatas)
Catatan:
karena
H = hash(plain_password + salt)
sekarang berperilaku sedikit seperti baruplaintext
(lihat jawaban ke-2 dari Zero Knowledge Password Proof: mengapa hashing kata sandi di sisi klien bukan ZKP? ), maka server dapat disimpan(username, salt, server_salt, hash(H + server_salt))
dalam database, bukan(username, salt, H)
.untuk mengurangi risiko serangan replay, server juga dapat mengirim yang unik
nonce
, bersama dengansalt
untuk setiap login, yang kedaluwarsa setelah satu upaya logintujuan utama di sini adalah bahwa server tidak pernah memiliki akses ke sandi teks biasa atau hash sederhana (yang sering kali dapat dibalik dengan tabel pelangi tunggal untuk seluruh situs). Saya baik-baik saja dengan risiko bahwa penyerang harus menghitung satu tabel pelangi per pengguna .
Contoh serangan yang ingin saya kurangi: jika server memiliki akses ke kata sandi teks biasa dan disusupi (misalnya, Spectre / Meltdown vuln.) Maka kata sandi teks biasa pengguna (mungkin digunakan kembali di situs web lain) dapat dicuri, sebelum di-salted -hashed dan disimpan ke database.
Jawaban
Saya tidak melihat bagaimana proposal Anda lebih baik daripada pendekatan hashing sisi klien yang ada, tetapi menurut saya ini lebih kompleks untuk diterapkan daripada yang lain. Sayangnya Anda tidak menjelaskan risiko khusus yang Anda coba akses, jadi saya hanya berasumsi ancaman khas yang biasa terlihat.
Penyerang Man in the Middle
Dalam kasus ini diasumsikan bahwa beberapa orang di tengah memiliki akses ke lalu lintas, misalnya karena itu mengganggu beberapa intersepsi TLS lalu lintas tepercaya di firewall perusahaan atau mendapatkan CA tepercaya seperti dalam kasus superfish .
Dalam skenario ini, penyerang mendapatkan akses H
yang sama seperti sebelumnya plain_password
. Karena H
semua yang diperlukan untuk otentikasi, penyerang berhasil dan pendekatan Anda tidak menambahkan perlindungan tambahan di sini .
Menyembunyikan kata sandi yang lemah dan penggunaan ulang kata sandi
Argumen umum untuk hashing sisi klien adalah untuk tidak mengekspos sandi yang lemah atau digunakan kembali ke server, tetapi mengautentikasi dengan sandi turunan yang kompleks. Pendekatan Anda melakukan ini dengan melakukan hashing plain_password
dengan beberapa pengguna yang dibuat secara acak salt
dan kemudian mengirim H
dan salt
ke server pada pengaturan kata sandi.
Sementara ini berfungsi, setiap otentikasi sekarang memerlukan langkah tambahan : pertama ia perlu mengambil garam yang sebelumnya digunakan untuk pengguna dari pengguna dan kemudian dapat menggunakan ini salt
untuk melakukan hash plain_password
. Langkah tambahan ini membuat otentikasi lebih kompleks karena pertama-tama ia perlu memeriksa pengguna dengan server dan kemudian dapat memeriksa kata sandi. Selain itu implementasi sepele ini membuka kebocoran informasi karena memungkinkan untuk memeriksa apakah pengguna ada di tempat pertama (garam dikembalikan atau tidak) tanpa otentikasi lebih lanjut.
Kebocoran informasi ini dapat ditutup oleh server yang mengembalikan beberapa garam tidak peduli apakah pengguna ada atau tidak. Tentu saja ini tidak bisa hanya menjadi garam acak karena jika tidak, penyerang bisa saja memeriksa dua kali pengguna yang sama dan menyimpulkan bahwa pengguna tidak ada jika garam yang dikembalikan berbeda. Jadi garam sebenarnya harus diperbaiki untuk pengguna yang tidak ada, yaitu berasal dari nama pengguna.
Dan ini juga menunjukkan jalur untuk menyederhanakan pendekatan Anda : alih-alih membuat salt acak oleh pengguna, menyimpannya di server dan mengambilnya lagi nanti, seseorang bisa dengan mudah mendapatkan salt dari nama pengguna di sisi klien . Sederhana salt=hash(username+domain)
akan cukup untuk menghasilkan garam yang unik per domain dan dengan demikian membuat keduanya salt
dan H
berbeda meskipun username
dan plain_password
dapat digunakan kembali pada domain yang berbeda. Dan bertentangan dengan pendekatan Anda, tidak ada perjalanan tambahan ke server yang diperlukan untuk mengambil terlebih dahulu salt yang sebelumnya digunakan untuk pengguna.
Singkatnya: pendekatan yang disederhanakan ini pada dasarnya mengirim hash(plain_password+username+domain)
alih-alih kata sandi asli. Domain ditambahkan untuk memastikan bahwa meskipun username
dan plain_password
digunakan kembali di beberapa situs, sandi turunan tidak digunakan kembali.
Inilah masalah yang ingin diselesaikan oleh protokol seperti PAKE dan SRP . Dengan PAKE / SRP, klien dan server saling mengotentikasi satu sama lain berdasarkan sandi yang diketahui klien (dan turunan sandi yang diketahui server).
Klien mendemonstrasikan ke server bahwa ia mengetahui kata sandi, tanpa klien mengirim kata sandi (atau data yang setara dengan kata sandi) ke server. Di akhir proses, klien dan server berbagi rahasia bersama.
Server tidak menyimpan kata sandi (atau data yang setara dengan kata sandi) dan tidak rentan terhadap serangan kamus. Seorang penyadap atau man-in-the-middle yang dapat melihat teks biasa yang dikirim melalui kabel tidak dapat memperoleh informasi yang cukup untuk mendapatkan kata sandi. Ini secara efektif mencegah serangan man-in-the-middle menggunakan sertifikat palsu, dan mencegah situs 'phishing' mencuri sandi pengguna.
Untuk artikel bagus tentang bagaimana 1password mengimplementasikan SRP, lihat https://blog.1password.com/developers-how-we-use-srp-and-you-can-too/
Selain jawaban Steffen Ullrich :
Jika selama login pengguna mengirimkan hash saja, maka penyerang tidak perlu mengetahui kata sandinya. Ini cukup untuk mencuri database kata sandi. Kemudian selama permintaan login, penyerang hanya akan mengirim hash dari database. Server tidak akan membedakan jika klien menggunakan kata sandi dan melakukan hash, atau jika klien (penyerang) hanya mengirim hash.
Artikel tentang alamat OPAQUE juga masalah ini: Mencuri database password tidak akan membantu penyerang. Seseorang perlu mengetahui kata sandi pengguna biasa.
Jika penyerang menyusupi server Anda, mereka tidak hanya mengontrol perangkat lunak yang berjalan di server Anda, tetapi juga perangkat lunak yang berjalan di klien.
Tidak peduli skema otentikasi yang Anda rancang dengan indah, penyerang dapat mengubahnya sebelum dikirim ke browser.
Anda sekarang memiliki masalah telur ayam: Anda tidak dapat mengamankan kata sandi jika penyerang mengontrol cara mengumpulkan dan mengirimnya ke server Anda.
Jika Anda khawatir tentang pelanggaran data, metode Anda akan berfungsi sebagai perlindungan, tetapi begitu juga sisi server hashing kata sandi yang tepat.
Jika Anda khawatir tentang serangan MITM, TLS akan menyelesaikannya.
Jika Anda khawatir tentang serangan MITM atas TLS, maka, seperti yang ingin saya katakan, pertahanan yang baik terhadapnya selalu dimulai dengan manual Krav Maga. Seorang penyerang yang memiliki sumber daya yang cukup untuk merusak TLS secara konsisten tidak memiliki masalah untuk mendapatkan apa yang mereka inginkan dari individu yang tidak terlatih dengan baik dan khusus (ya, saya berbicara tentang penyiksaan, pemerasan, penculikan dan pembunuhan).
Jika Anda khawatir tentang aktor ancaman yang hanya dapat membaca data yang diterima oleh server, maka pendekatan Anda (sebagaimana dikoreksi oleh Steffen) akan bekerja melawan mereka. Namun, ini adalah keadaan yang aneh dan jarang, sering kali muncul dari server yang salah dikonfigurasi dan praktik pengembangan yang buruk (yaitu mengirim kredensial melalui permintaan GET dan menyimpan log akses secara publik). Lebih mudah untuk memperbaiki kesalahan ini daripada membuat protokol hanya untuk mengatasinya.
Perhatikan bahwa kedua kerentanan yang Anda sebutkan (sebenarnya itu hanya satu, karena Meltdown secara teknis adalah varian dari Spectre) pada akhirnya akan menghasilkan eskalasi hak istimewa lokal, memberi penyerang kendali penuh atas server web Anda. Sekali lagi menyoroti betapa jarangnya skenario di mana penyerang memiliki akses hanya baca ke data yang diterima oleh server web Anda.
Jadi, alasan banyak situs besar tidak menggunakannya, itu karena ia tidak menambahkan apa-apa kecuali dalam keadaan tertentu yang kemungkinan besar merupakan kesalahan konfigurasi. Perlu juga dicatat bahwa jika penyerang dapat membaca data apa yang sedang bertransisi di server Anda, Anda berada jauh di sisi yang kalah dalam permainan. Pikiran saya, memiliki perlindungan berlapis itu baik, tetapi tujuan utama Anda bukanlah membuatnya terjadi di tempat pertama. Dan berfokus pada hal itu juga akan menghindarkan Anda dari menciptakan skema baru.
Bagaimanapun, seperti yang ditunjukkan Steffen, skema yang Anda usulkan bisa berfungsi kembali seperti model serangan yang aneh. Saya masih akan menggunakan hash(hash(domain + username) + password)
daripada hash(domain + username + password)
hanya untuk mengatur kemungkinan jarak jauh yang domain + username + password
masih merupakan kata dalam kamus.
Seperti yang ditunjukkan mti2935, SRP adalah alternatif yang lebih menarik. Otentikasi berbasis sertifikat (yaitu yang ditangani oleh browser) adalah opsi lain (yang menurut saya lebih baik daripada melakukannya secara manual dalam skrip JS yang berpotensi tercemar, seperti yang Anda usulkan di komentar).