Mengapa menyimpan kata sandi pengguna?

10

Saya sesekali melihat pertanyaan yang menanyakan cara menyimpan kata sandi pengguna dengan aman untuk aplikasi web (menggunakan RDBMS, saya tidak berbicara tentang Facebook atau Twitter). Jawaban yang biasa adalah "garam kata sandi, lalu hash dengan algoritma yang kuat seperti TDES atau SHA512".

Pertanyaan saya adalah: Sebagai pengguna RDBMS, mengapa saya harus repot-repot sama sekali dengan menyimpan kata sandi yang bermasalah karena sebagian besar mesin memiliki mekanisme otentikasi bawaan.

Misalnya, jika beberapa pengguna X ingin membuat kata sandi pengguna akun Y di aplikasi web saya, bagaimana cara mengeluarkan kueri berikut:

CREATE USER X WITH ENCRYPTED PASSWORD Y IN GROUP baseuser;

Kemudian dalam aplikasi saya, pengguna dapat membuka koneksi ke database menggunakan kredensial dan saya tidak perlu repot sama sekali dengan manajemen kata sandi.

Saya melihat banyak keuntungan dari metode ini:

  • Jika RDBMS memutuskan bahwa algoritma enkripsi perlu diubah, saya tidak perlu menyentuh apa pun, hanya untuk menerapkan pembaruan keamanan;
  • Mudah bagi saya untuk mengelola otorisasi pengguna. Jika pengguna dipromosikan ke peran administrator, saya hanya perlu menambahkan pengguna ke grup yang sesuai;
  • Suntikan SQL sekarang tidak ada artinya, karena saya mengelola izin untuk memungkinkan apa yang ingin saya izinkan untuk setiap pengguna dalam database (misalnya, dalam forum seperti SO, menambahkan posting baru, menjawab posting, berkomentar dan mengedit / menghapus pertanyaannya sendiri / jawaban / komentar);
  • Akun pengguna "anonim" dapat digunakan untuk koneksi yang tidak diautentikasi ke aplikasi saya;
  • Setiap pengguna adalah pemilik data yang diberikannya.

Tetapi pada hampir setiap pertanyaan yang saya lihat pada topik ini, tampaknya ada konsensus umum bahwa ini bukan cara yang harus dilakukan. Pertanyaan saya adalah: mengapa?

Catatan: Poin ketiga diizinkan oleh kebijakan di PostgreSQL, dan kebijakan keamanan di Microsoft SQL Server. Saya menyadari bahwa konsep-konsep ini adalah pendatang baru, tetapi bagaimanapun, sekarang mereka ada di sini, mengapa teknik yang saya gambarkan tidak menjadi cara standar untuk menangani akun pengguna?

Fabian Pijcke
sumber
2
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Paul White 9
Kebetulan, jawaban yang biasa salah. Anda harus memberi garam kata sandi, lalu memotongnya dengan algoritme lambat seperti bcrypt atau argon2.
Tgr

Jawaban:

27

Karena untuk banyak aplikasi, mereka tidak ingin akun pengguna individu terhubung ke database. Pengguna / kata sandi / hak / izin semuanya ditangani pada lapisan aplikasi, dan satu akun layanan khusus digunakan untuk menghubungkan ke back-end basis data.

Sebagai DBA, saya tidak ingin harus mengelola, pada tingkat basis data, 10.000 pengguna aktif dari beberapa aplikasi web yang menghadap publik berukuran sedang, atau mungkin 2+ juta pengguna dari beberapa aplikasi yang tiba-tiba populer.

Dalam arti yang sangat nyata, ini adalah perbedaan filosofi antara pengembang aplikasi dan pengembang basis data / DBA.

Banyak / sebagian besar pengembang aplikasi tidak ingin menyerahkan tanggung jawab atas aspek utama fungsionalitas aplikasi dan / atau aturan bisnis hingga ke lapisan basis data. Sebagai gantinya, mereka melihat database sebagai alat untuk hanya menyimpan dan mengambil data.

Dalam beberapa kasus, ini mungkin rabun; banyak RDBMS memiliki fitur luar biasa yang dapat membuat hidup aplikasi jauh lebih mudah (keamanan tingkat baris, indeks kolom, penyimpanan filestream, dll.).

Tetapi beberapa fitur keren ini hanya tersedia dalam versi yang lebih baru, dan organisasi tidak selalu cepat untuk meningkatkan lingkungan yang ada (lihat tabel ini dari 2014 ).

Dan dalam kasus lain, penanganan hal-hal tersebut pada lapisan aplikasi lebih disukai (dan bukan hanya untuk portabilitas platform basis data, saya terus terang berpikir bahwa klaim itu berlebihan).

BradC
sumber
2
Ada 'perang suci' yang ada dalam apakah logika bisnis masuk dalam aplikasi atau dalam database. Jika Anda telah membangun aplikasi di mana semua logika bisnis (khususnya keamanan) ada di database (menggunakan prosedur tersimpan, tampilan dll.), Maka mungkin ada argumen untuk memanfaatkan mekanisme keamanan database karena tidak ada yang dapat terhubung secara langsung dan menyiasati Anda keamanan. Saya sepenuhnya setuju bahwa Anda harus menghindari 'membangun kembali' mekanisme keamanan (mis. Login / pasword) di tabel khusus. Mengapa melakukan itu ketika Anda sudah memiliki keamanan direktori / O365 aktif.
Nick.McDermaid
1
@ Nick.McDermaid Saya ingin memastikan bahwa saya mencampur logika bisnis antara DB dan aplikasi secara adil untuk membantu menghilangkan potensi pengembang masa depan untuk mengetahui apa yang sedang terjadi, itu juga membantu saya menjaga keamanan pekerjaan saya karena tidak ada yang gila cukup ingin mengelolanya.
Der Kommissar
Lempar layanan web dan server aplikasi kucing jantan di sana dan Anda dapat bekerja untuk IBM
Nick.McDermaid
8

Garis pemisah semakin sedikit mengembang pada saat itu, tetapi saya akan menganggap pengguna dan izin pada tingkat basis data sebagai bagian dari skema bukan bagian dari data, dan secara umum aplikasi tidak memiliki tempat untuk memodifikasi skema (ada, seperti biasa, pengecualian untuk aturan ini).

Saya lebih suka tidak memberikan aplikasi yang mereka butuhkan untuk mengelola objek skema (login, pengguna dan izin) ketika pengguna baru diperlukan dan yang lama pergi, karena jika aplikasi itu diretas penyerang maka memiliki akses ke izin tersebut membuatnya lebih mudah untuk membuka basis data lebih lanjut. Dalam MS SQL Server kecuali jika Anda menggunakan login database yang sepenuhnya berisi adalah objek tingkat server sehingga Anda perlu membagikan hak di luar database aplikasi tunggal membuatnya lebih berisiko.

Terlebih lagi, bahkan jika Anda memiliki akun per-aplikasi-pengguna di tingkat basis data Anda, Anda masih memerlukan akun pengguna tingkat aplikasi untuk menangani permintaan yang tidak diautentikasi - yaitu jika aplikasi membutuhkan informasi dari database sebelum pengguna aplikasi berhasil diotentikasi (mungkin untuk menampilkan informasi status pada layar pembuka / masuk?).

Juga jika portabilitas antara mesin basis data adalah tujuan (mungkin aplikasi Anda ingin dapat berjalan di mysql dan postgres?) Maka aplikasi Anda perlu untuk mengabstraksi fungsi manajemen pengguna / login untuk setiap mesin karena mereka tidak standar di antara mereka. - jika Anda akan melakukan upaya itu maka Anda mungkin juga menerapkan kata sandi sendiri dan mendapatkan opsi manajemen yang Anda inginkan alih-alih menerima fitur-set umum terendah yang ditawarkan mesin.

David Spillett
sumber
1
Ok, jadi "aplikasi seharusnya tidak mengubah skema" menurut saya poin bagus pertama terhadap teknik yang saya sarankan. Namun akun anonim yang dapat membuat pengguna baru hanya perlu dapat membuat pengguna baru dengan akses paling dasar. Hanya administrator yang dapat mempromosikan pengguna dan menjatuhkan pengguna, yang saya kira adalah yang diinginkan dalam aplikasi :-) Data umum dapat dilihat oleh pengguna anonim, sehingga koneksi ini dapat digunakan untuk konten di mana otentikasi tidak diperlukan. Portabilitas juga merupakan poin yang baik, namun saya pikir perintah pengguna sekarang merupakan bagian dari standar (tidak yakin, itu bukan tahun yang lalu)
Fabian Pijcke
Omong-omong dengan pengaturan ini jika seorang hacker mendapatkan akses ke database sebagai pengguna anonim, ia akan dapat membuat pengguna sebanyak yang ia inginkan, tetapi ini bukan masalah keamanan, ia juga pasti bisa mengasapi database menggunakan salah satu akun yang dibuat, itu akan menjengkelkan tapi sekali lagi tidak ada masalah keamanan (dan dia bisa melakukannya dengan menggunakan antarmuka standar juga, itu akan menjadi cara yang lebih lambat: p)
Fabian Pijcke
3
Saya setuju bahwa dari sudut pandang keamanan tingkat basis data pengguna akan lebih baik. Namun itu pada dasarnya tidak mungkin untuk dikelola dengan misalnya toko online di mana Anda mungkin memiliki 50 juta pengguna terdaftar. Masing-masing harus menjadi pengguna basis data. Plus: ini biasanya tidak cocok dengan aplikasi web menggunakan kumpulan koneksi.
a_horse_with_no_name
6

Menyatakan kembali pertanyaan

Mengapa menyimpan kata sandi pengguna?

Jawaban paling sederhana adalah Anda harus melakukannya. Anda masih menyimpan kata sandi dalam metode alternatif Anda. Hanya saja Anda menggunakan sistem bawaan basis data untuk mengelola penyimpanan. Jadi metode Anda hanya sebagus basis data Anda. Itu mungkin masih lebih baik daripada apa pun yang Anda lakukan sebaliknya, tetapi itu tidak menghindari penyimpanan. Ini benar-benar hanya menghindari penyimpanan kode.

Mungkin juga tidak lebih baik. Jika saya kompromi database dan mendapatkan salinan file, saya bisa mengakses tabel secara langsung. Jadi tidak ada gunanya menggunakan sistem manajemen kata sandi yang brilian. Karena jika seseorang dapat mengakses tabel tingkat sistem yang berisi kata sandi atau kata sandi hash, mereka juga dapat mengakses file secara langsung. Mengapa repot-repot memecahkan kata sandi ketika Anda sudah memiliki data? Ini tidak seperti Anda dapat mengenkripsi data dengan mudah. Setiap pengguna harus dapat mengaksesnya. Jadi enkripsi tingkat pengguna tidak akan bekerja dengan baik.

Tapi apa yang sebenarnya Anda tanyakan adalah

Mengapa menggunakan skema otentikasi tingkat aplikasi ketika database sudah memilikinya?

Keamanan

Mengabaikan kemungkinan Anda bisa menulis versi yang lebih aman, yang lain menyarankan sejumlah alasan. Saya biasanya setuju. Tapi ada satu lagi yang belum ada yang disebutkan. Anda membahayakan keamanan database Anda.

Dalam sistem ini, setiap pengguna aplikasi Anda memiliki pengguna basis data dan kata sandi. Tentu, ini adalah pengguna terbatas, tetapi masih pengguna yang dapat terhubung ke database. Bahkan jika Anda menggunakan keamanan tingkat baris, Anda masih mengizinkan pengguna akhir untuk mengetahui info koneksi basis data. Jika pernah ada exploit di mana pengguna bisa mendapatkan akses level tabel, Anda telah membuka database Anda untuk menyerang. Dan beberapa eksploitasi telah melampaui itu untuk akses administrator.

Di lapisan bawang keamanan, sistem normal adalah:

  • Basis data, yang hanya memungkinkan koneksi dari mesin tertentu.
  • Basis data, hanya memungkinkan koneksi sebagai kombinasi pengguna / kata sandi tertentu.
  • Server dengan izin basis data yang memungkinkan koneksi dari aplikasi.
  • Aplikasi dijalankan di server.
  • Aplikasi memiliki info koneksi basis data dengan hak istimewa terbatas.
  • Aplikasi mengautentikasi pengguna sebelum mengizinkan mereka untuk memodifikasi database (kecuali mungkin untuk membuat akun baru).

Dalam sistem ini:

  • Pengguna akhir mengetahui kombinasi pengguna / kata sandi yang akan bekerja pada database, diakui dengan hak istimewa yang sangat rendah.
  • Hanya perlu membuat server atau secara meyakinkan berpura-pura menjadi server resmi.

Kami telah kehilangan seluruh tingkat keamanan aplikasi. Dan kami telah secara sukarela menyerahkan bagian dari lapisan basis data. Jadi kita hanya perlu dua eksploitasi:

  1. Spoof atau kompromi server resmi.
  2. Tingkatkan akses akun privilege terbatas.

Jika kita dapat melakukan dua hal itu, kita memiliki akses ke database. Jadi kita beralih dari tiga lapisan menjadi dua. (Lapisan ketiga dalam sistem normal adalah bahwa Anda memerlukan pengguna yang valid untuk terhubung ke database.)

Anda akan melakukan banyak pengelolaan akun ini. Bagaimana jika Anda melakukan kesalahan? Alih-alih membatasi pengguna X hanya pada baris tertentu, Anda memberi mereka semua akses ke tabel kritis. Hal-hal semacam itu biasanya dilakukan secara manual dan hanya ada sedikit, sehingga mudah diaudit. Tetapi dalam sistem Anda, Anda bisa melakukan ribuan atau jutaan atau bahkan milyaran akun pengguna, masing-masing dengan akses istimewa mereka sendiri.

Dalam hal ini, apakah sistem basis data skala untuk jutaan atau milyaran pengguna? Jika ya, bagaimana dengan jumlah peraturan? Jika setiap pengguna mengambil seratus atau lebih aturan tentang apa yang dapat dan tidak dapat mereka akses, apakah itu meningkatkan hingga satu miliar pengguna? Anda mengambil sistem skala yang biasanya kecil dan menjadikannya skala besar. Itu tidak akan selalu berhasil. Anda mungkin menemukan keterbatasan sistem saat Anda tumbuh.

mdfst13
sumber
5

Apa yang Anda uraikan akan menangani otentikasi, tetapi bukan otorisasi (data apa yang dapat diakses pengguna) atau hanya dalam kasus penggunaan yang paling sederhana.

Untuk melanjutkan contoh Anda dengan stackexechange: Bagaimana Anda membuat posting yang dihapus hanya dapat dilihat oleh pengguna tingkat tinggi? Jadi untuk aturan akses, Anda masih perlu logika dalam kode. Alih-alih berbagi logika akses antara aturan basis data, dan aturan akses aplikatif, sebagian besar pengembang lebih suka memiliki semuanya di tempat yang sama.

Anda juga akan membutuhkan tabel untuk menyimpan info pengguna: pengguna bukan hanya nama pengguna + kata sandi. Dia punya email, reputasi, dan sebagainya. Jadi Anda masih memerlukan tabel pengguna, yang harus Anda pastikan sudah sinkron dengan tabel pengguna basis data, asalkan Anda dapat mengaksesnya.

Dengan solusi Anda, Anda bisa menghilangkan kolom kata sandi, yang tidak terlalu sulit untuk diisi: ada perpustakaan dan dokumentasi yang baik tentang cara menangani / kata sandi hash.

Poin lain: bagaimana Anda membuat kumpulan koneksi? Saya hanya tahu jdbc (java <-> db), dan Anda perlu memberikan nama pengguna + kata sandi untuk mendapatkan koneksi, yang kemudian dapat Anda kumpulkan.

Saya memikirkan beberapa hal lain yang akan lebih sulit / lebih berbelit untuk diterapkan daripada dengan cara yang telah ditetapkan:

  • menangani pemulihan kata sandi
  • 2 tahun setelah implementasi awal, manajer produk Anda meminta Anda untuk menambahkan dukungan untuk skema oauth, atau mengizinkan autor faktor ganda
Thierry
sumber
Sesuatu seperti CREATE POLICY deleted_posts_high_rep ON posts FOR SELECT TO baseuser USING ((SELECT rep FROM users WHERE name = current_user()) > 10000)menjawab pertanyaan pertama Anda. Saya tidak pernah mengatakan saya tidak membutuhkan tabel pengguna lagi, dan memastikan sinkronisasi dengan tabel pengguna db agak rumit tapi mungkin. Poin utama dari teknik yang dibahas adalah keamanan. Sedangkan untuk koneksi pool, saya bekerja dengan OCaml dan saya harus mengatakan saya tidak mengerti mengapa saya membutuhkan koneksi pool. Saat ini saya menggunakan peta hash yang mengaitkan nilai cookie dengan fungsi 0-ary yang mengembalikan koneksi :-)
Fabian Pijcke
5
Kumpulan koneksi diterapkan untuk meningkatkan kinerja: dengan mereka, Anda tidak perlu membuat koneksi untuk setiap permintaan pengguna (sehingga Anda menghemat cpu / io / latency untuk membuat tautan tcp + semua koneksi dan bertukar auth dengan database). Adapun definisi kebijakan: database Anda akan terus-menerus memeriksa hak akses pada setiap akses ke data, bahkan ketika Anda sudah memeriksanya sekali. Juga 'akses ditolak atau dilarang' tidak sama dengan 'OK, tidak ada hasil'. Tidak yakin petugas keamanan lebih suka versi OK.
Thierry
3
Fabian, koneksi pool adalah fundamental pada skala apa pun, itu benar-benar default yang Anda bahkan tidak akan mempertimbangkan untuk tidak menggunakannya. Berikut adalah beberapa tolok ukur hanya untuk memberi Anda gambaran betapa pentingnya: peningkatan kinerja 600x dengan pooling koneksi ( vladmihalcea.com/2014/04/17/the-anatomy-of-connection-pooling ) dan lebih dari 4.000x peningkatan kinerja dengan pooling koneksi ( progress.com/tutorials/jdbc/… ). Ini beberapa urutan perbedaan besarnya, ini bukan "bagus untuk dimiliki", aplikasi akan berhenti tanpa itu.
Ivan McA
1
Angka yang menarik. Dan memang, saya belum pernah melihat aplikasi yang tidak menggunakan kolam koneksi. Tetapi saya tidak tahu (dan berharap) mereka untuk membuat banyak kecepatan. Aspek lain yang Anda dapatkan dengan kumpulan koneksi adalah kontrol sumber daya: berkat mereka, peningkatan besar dalam klien yang mencoba untuk terhubung sekaligus akan membuat aplikasi Anda lambat, tetapi database Anda tidak akan terlalu banyak terpengaruh (jika kolam dikonfigurasi dengan baik) .
Thierry
Ok, saya hanya mencari informasi lebih lanjut tentang kumpulan koneksi, dan saya setuju bahwa ini adalah poin yang sangat valid segera setelah situs web harus menangani lebih dari seratus koneksi per detik, yang tidak terlalu tinggi. Tampaknya setiap koneksi di PostgreSQL memakan sekitar 10MiB RAM! Saya tidak pernah berpikir itu sebanyak itu.
Fabian Pijcke
1

Satu hal lagi: banyak [1] aplikasi web memungkinkan Anda mendaftar dan membuat akun pengguna secara online melalui aplikasi itu sendiri. Yang berarti pengguna anonim Anda (yang seharusnya memiliki hak istimewa paling sedikit di anggap orang) harus memiliki hak untuk membuat pengguna dan memberikan hak istimewa!

OKE, dimungkinkan untuk membatasi hak istimewa apa yang dapat diberikannya, dan memberi pengguna tingkat tinggi lebih banyak opsi hibah (meskipun saya tidak sadar itu - bukan "memberi hak istimewa" satu hak istimewa tunggal sering). Tapi tetap saja, itu berarti meletakkan sesuatu dengan hak istimewa online untuk di-hack semua orang. Saya cukup yakin DBA saya tidak akan menyukai saya jika saya melakukan itu :)

Saya tahu pada satu tingkat masalah ini memang ada, tetapi Anda memiliki lapisan pertahanan, terutama untuk menghapus data, jika Anda tidak mengizinkan aplikasi web untuk mengelola pengguna DB.

Juga, ini akan mencegah penggunaan koneksi DB yang dikumpulkan atau digunakan kembali.

[1] Kebanyakan saya akan mengatakan, tetapi bukan angka untuk mendukungnya

Adam
sumber