Bagaimana Anda menangani keamanan database dari aplikasi desktop?

12

Selama sekitar 10 tahun saya telah bekerja pada berbagai aplikasi klien desktop in-house dengan penyimpanan data SQL Server. Jarang saya memulai proyek ini - sebagian besar adalah pekerjaan pengambilalihan.

Satu hal yang tampak konstan di mana-mana adalah bahwa ada satu akun pengguna global SQL Server yang digunakan aplikasi ini yang memberikan izin kepada database umum, dan ya dalam beberapa situasi naif itu menggunakan saakun pengguna, yang biasanya saya coba perbaiki bila memungkinkan .

Anda tidak dapat menyembunyikan nama pengguna dan kata sandi ini secara efektif yang digunakan aplikasi untuk mengakses database. Mereka biasanya disimpan dalam iniatau configberkas, atau mungkin dipanggang ke dalam executable itu sendiri. Dalam semua kasus, mereka dapat dilihat oleh pengguna jika mereka melakukan sedikit penggalian. Dalam satu kasus kami benar-benar menggunakan configfile tetapi dienkripsi, tetapi tentu saja kunci enkripsi harus disimpan dalam executable (kami tidak naif terhadap keterbatasan ini, tetapi itu benar-benar menghentikan orang dari mencari-cari yang cukup pandai untuk melihat configfile).

Semua sistem ini memiliki sistem otentikasi pengguna yang dibangun ke dalam aplikasi, tetapi tentu saja mereka semua dikelola melalui aplikasi itu sendiri, artinya informasi pengguna disimpan dalam database. Aplikasi ini membatasi hal-hal apa saja yang dapat Anda lakukan berdasarkan tingkat akses Anda, tetapi semuanya bisa diperdebatkan jika Anda bisa terhubung ke database dan menjalankan kueri ad-hoc.

Saya tertarik untuk mengetahui apa yang dilakukan sistem lain untuk mengatasi masalah ini. Berikut adalah opsi yang saya tahu:

  1. Gunakan mekanisme keamanan SQL Server untuk mempertahankan daftar pengguna dan peran, dan membuat aplikasi desktop menambah dan menghapus pengguna melalui kueri T-SQL.
  2. Alih-alih terhubung langsung ke database, buat beberapa jenis layanan web yang berjalan di server dan masukkan logika otentikasi di sana. Buat setiap permintaan melakukan validasi keamanan.

Opsi pertama agak jelek karena Anda memisahkan pengguna dari basis data sehingga pengguna tidak lagi entitas kelas satu dan Anda tidak dapat merujuk mereka dengan hubungan kunci asing, dll.

Yang kedua sepertinya masalah kinerja utama, dan banyak pekerjaan tambahan, ditambah Anda tidak dapat dengan mudah menggunakan pemetaan ORM seperti NHibernate (saya pikir).

Adakah yang punya pengalaman dengan ini? Praktik terbaik?

Edit

Berpikir lebih banyak, bisakah SQL Server Authentication benar-benar menyelesaikan masalah ini? Misalnya, jika pengguna Anda harus dapat menyisipkan dan memperbarui catatan absen sehingga Anda dapat mengedit absen Anda, tidak mungkin server SQL dapat melarang akses ke baris lain di tabel detail absen, yang berarti Anda juga bisa membaca dan menulis absen orang lain .

Scott Whitlock
sumber
Pada topik binding; tidak menggunakan ORM seperti NHibernate adalah (saya pikir) bukan masalah. Jika Anda menggunakan layanan web sebagai contoh, Anda akan menemukan banyak cara untuk secara efisien mengikat data Anda ke XML.
jasonk
Anda seharusnya tidak menggunakan ORM Anda sebagai pemetaan langsung antara objek bisnis dan entitas DB, itu pendekatan yang buruk yang membuat antarmuka yang rapuh. Buat permintaan ke lapisan bisnis yang mendapat entitas DB mentah dan hanya mengembalikan data yang diperlukan ke klien.
gbjbaanb
@ gbjbaanb - tentu, saya akan mengubah seluruh arsitektur sore ini. :)
Scott Whitlock
Saya kira Anda bisa menunggu sampai seseorang meretas Anda sebelum mengubahnya, tetapi di sisi baiknya, setidaknya Anda tidak akan memiliki masalah meminta bos Anda untuk mendanai perancangan ulang :-)
gbjbaanb
Anda dapat mencegah pengguna memperbarui catatan orang lain - dengan menggunakan prosedur tersimpan sebagai satu-satunya cara untuk memperbarui catatan dan menggunakan pengguna yang menjalankan proc sebagai bagian dari kueri. Lihat CURRENT_USER
gbjbaanb

Jawaban:

9

Saya takut menambahkan lapisan Layanan Web mungkin merupakan solusi yang tepat untuk masalah Anda.

Memisahkan klien dari implementasi basis data yang mendasar mungkin akan membantu Anda dalam jangka panjang juga.

Menambahkan lapisan layanan web tidak harus melukai kinerja ...

Memang, dengan API yang tepat, layanan web benar-benar dapat meningkatkan kinerja, dengan mengumpulkan bersama beberapa kueri basis data dalam LAN pusat data, alih-alih mengharuskan beberapa perjalanan bolak-balik ke WAN.

Dan tentu saja lapisan layanan web sering dapat diskalakan secara horizontal, dan menambahkan caching yang sesuai untuk permintaan basis data Anda, bahkan mungkin mekanisme pemberitahuan perubahan.

Lapisan server menambahkan keamanan yang tidak mungkin Anda pastikan dengan aplikasi yang berjalan pada klien jarak jauh. Apa pun yang berjalan pada klien dapat "diretas" dan tidak boleh dianggap benar-benar tepercaya. Anda hanya harus benar-benar menempatkan logika presentasi di klien, dan meng-host sesuatu yang penting pada perangkat keras yang Anda kontrol penuh.

Saya tidak tahu tentang aplikasi Anda, tetapi aplikasi web saya secara alami dipisah menjadi beberapa lapisan, dengan kode presentasi dipisahkan dari lapisan kegigihan oleh setidaknya satu tingkat logika bisnis yang membuat keduanya terpisah. Saya menemukan ini membuatnya lebih mudah untuk alasan tentang aplikasi saya, dan jauh lebih cepat untuk menambah atau memodifikasi fungsionalitas. Jika lapisan dipisahkan pula, relatif mudah untuk menjaga lapisan presentasi di klien, dan sisanya di server di bawah kendali saya.

Jadi, sementara Anda dapat menyelesaikan masalah Anda tanpa memperkenalkan lapisan "layanan web", pada saat Anda telah menulis semua prosedur tersimpan (atau yang setara) yang diperlukan untuk mengisi lubang dalam implementasi keamanan basis data standar, Anda mungkin akan lebih baik menulis aplikasi sisi server tempat Anda dapat menulis unit test yang tepat.

Bill Michell
sumber
Saya mengakui bahwa itu tidak perlu menjadi hambatan kinerja, tetapi tentu saja menambahkan lapisan tambahan untuk arsitektur, yang berarti lebih banyak pemeliharaan.
Scott Whitlock
3
Ini menambahkan lapisan, tetapi tidak harus pemeliharaan. Pertimbangkan bahwa dengan semua logika yang ditempatkan dalam layanan, bukan klien, perubahan dapat 'diluncurkan' tanpa mengharuskan pengguna untuk memperbarui aplikasi klien mereka.
GrandmasterB
5

Mirip dengan jawaban oleh jmoreno, Anda dapat menolak akses pengguna ke segala hal selain dari izin EXECUTE pada prosedur tersimpan, kemudian memanfaatkan rantai kepemilikan untuk membuat prosedur tersimpan menjalankan operasi yang diperlukan pada tabel.

Lihat di sini untuk perincian https://msdn.microsoft.com/en-us/library/bb669058(v=vs.110).aspx

Ketika pengguna memasukkan sisi nama pengguna / kata sandi klien, saya menyimpannya dan mengirim sebagai parameter untuk setiap panggilan prosedur yang tersimpan. Anda kemudian dapat memverifikasi nilai-nilai yang disimpan dalam tabel sebelum melakukan operasi yang diinginkan.

Jelas bukan kata terakhir dalam keamanan, tetapi mungkin diperlukan jika PC Anda memiliki login generik, membatasi kemampuan Anda untuk menggunakan grup AD untuk izin, atau Anda memiliki akses terbatas ke AD itu sendiri.

James K
sumber
2

Salah satu pendekatan adalah dengan menggunakan grup AD dan prosedur tersimpan untuk membatasi apa yang dapat dilakukan pengguna - misalnya DB lembar waktu Anda, dapat memperbolehkan inset, memperbarui, dan menghapus jam pengguna, tetapi tidak mengizinkan memperbarui jam orang lain. ID pengguna akan disediakan oleh mesin DB, pengguna tidak akan memiliki akses langsung ke tabel DB, hanya untuk sp yang menjalankan kueri berdasarkan id login mereka.

Tentu saja ini tidak selalu layak, tetapi bisa saja. Pendekatan terbaik akan tergantung pada kebutuhan dan sumber daya Anda.

jmoreno
sumber
Ini adalah sesuatu yang tidak saya pertimbangkan. Saya tidak yakin itu sangat cocok, tetapi itu akan berhasil.
Scott Whitlock
1

Apa yang Anda beri petunjuk sebagai 'layanan web' disebut arsitektur n-tier . Ini umumnya cara untuk pergi dalam kasus di mana masalah keamanan atau konfigurasi kemungkinan (misalnya, distribusi aplikasi di banyak kantor). Tidak harus berbasis web. Banyak yang bekerja dengan protokol lain.

Anda membuat server aplikasi untuk bertindak sebagai perantara antara klien dan database (dan sumber daya lainnya). Server aplikasi menangani otentikasi berbasis aplikasi Anda dan melakukan tindakan atas nama klien. Faktanya, idealnya Anda tidak akan melakukan SQL di klien Anda - alih-alih Anda memanggil metode di server aplikasi. Server aplikasi akan menangani semua manipulasi data.

Ada sejumlah manfaat dari pendekatan ini. Anda tidak perlu mengonfigurasi koneksi database dan driver pada klien. Anda tidak menyimpan pengguna basis data, kata sandi, & server. Konfigurasi klien bahkan tidak perlu - cukup tunjukkan dalam kode ke url atau alamat yang benar. Juga, dengan 'logika' di server aplikasi, Anda tidak perlu mengulang sendiri ketika mengembangkan aplikasi lain - server aplikasi yang sama dapat digunakan kembali oleh berbagai jenis klien.

GrandmasterB
sumber
Bahkan lebih baik, jika (atau ketika) seseorang meretas desktop Anda (atau server web dalam setara berbasis web) penyerang mungkin memiliki akses penuh ke OS, tetapi mereka masih tidak memiliki akses ke DB. Maka mereka tidak dapat menjalankan "pilih * dari pengguna" yang disalurkan ke file yang mereka ambil, memecahkannya dengan santai dan membiarkan CEO Anda menjelaskan kepada media mengapa sistem keamanan Anda dikompromikan. Jika Anda juga menggunakan sprocs pada DB yang hanya memungkinkan akses eksekusi, maka penyerang juga dapat meretas aplikasi Anda dan mereka masih tidak bisa mendapatkan seluruh basis data pengguna Anda.
gbjbaanb
1

Teknologi telah sedikit berubah. Jika Anda mengautentikasi setiap pengguna ke basis data itu sendiri, dan menggunakan peran basis data, kini Anda dapat menggunakan apa yang disebut Tampilan yang Dapat Diupdate untuk menyelesaikan masalah ini, setidaknya dalam SQL Server.

Inilah tampilan yang bisa diperbarui seperti untuk tabel yang disebut di SomeTablemana setiap baris dalam tabel itu ditautkan ke karyawan. Karyawan harus dapat melihat baris yang terkait dengannya, dan anggota peran SDM harus dapat melihat semua baris, misalnya:

CREATE VIEW [dbo].[vwSomeTable]
AS
    SELECT SomeTable.*
    FROM SomeTable
        INNER JOIN Employee ON SomeTable.Employee_ID = Employee.Employee_ID
    WHERE Employee.Username = USER_NAME() OR IS_MEMBER('HR_Role')=1

GO

Maka yang Anda lakukan adalah memberikan izin baca (dan mungkin menulis) pada tampilan ( vwSomeTable) untuk semua pengguna, dan tidak memberikan izin di atas meja (SomeTable ).

Anda dapat menguji ini seperti ini:

EXECUTE AS USER = 'Some_Regular_Username'
SELECT * FROM vwSomeTable

... yang seharusnya mengembalikan baris mereka. Atau:

EXECUTE AS USER = 'Some_HR_Username'
SELECT * FROM vwSomeTable

... yang akan mengembalikan semua baris. Perhatikan bahwa Anda akan memerlukan izin eksekusi (peniruan) untuk melakukan tes ini.

Tampilan dapat diperbarui, sehingga bahkan pengguna biasa dapat melakukan ini, selama baris tersebut ditautkan ke Employeebaris mereka :

UPDATE vwSomeTable
SET SomeColumn = 5
WHERE SomeTable_ID = 'TheID'
Scott Whitlock
sumber
0

Menggunakan otentikasi berbasis sertifikat adalah cara "benar" menerapkan akun sql bersama. Tujuannya adalah menghilangkan penggunaan kata sandi untuk hal semacam ini.

Memperbarui:

Saya kira salah paham pertanyaannya. Saya pikir itu ada hubungannya dengan mencoba menemukan alternatif untuk menempatkan nama pengguna dan kata sandi db baik dalam konfigurasi aplikasi, atau didukung ke dalam aplikasi itu sendiri.

Anda dapat menghilangkan masalah mengelola kata sandi dalam aplikasi dengan menggunakan sertifikat sisi klien. Sertifikat itu sendiri tidak cukup, Anda harus memiliki sistem distribusi dan manajemen yang mampu beroperasi seperti pencabutan sertifikat.

Referensi: http://en.wikipedia.org/wiki/Public-key_infrastructure

dietbuddha
sumber
Bisakah Anda memberikan lebih banyak info tentang ini? Kedengarannya seperti ortogonal dengan maksud pertanyaan asli saya, tetapi menarik.
Scott Whitlock
0

Membangun solusi keamanan desktop baru, kami memilih solusi layanan web yang akan saya coba jelaskan di bawah.

Kami menyusun executable aplikasi desktop di lingkungan yang terpisah dari pengembang. Dan menghitung HASH dari executable yang direkam ke database.

Satu layanan web yang menyediakan semua informasi yang diperlukan untuk menjalankan aplikasi, kata sandi DB, informasi string koneksi, izin pengguna, dll ...

kami menggunakan satu DB log in per aplikasi dan mencatat rincian pengguna dalam database dalam variabel sesi untuk dapat mengaudit catatan.

DLL menangani semua komunikasi dari aplikasi desktop ke layanan web, yang hanya dapat diakses dengan token build ke dalam DLL.

Untuk bisa mendapatkan aplikasi DB kata sandi dari layanan web, DLL menghitung penelepon DLL HASH dalam runtime dan diteruskan sebagai parameter ke layanan web yang memvalidasi token DLL dan runtime yang dapat dieksekusi menghitung HASH ke yang direkam ketika digunakan (aplikasi hanya tersedia dalam satu instalasi jaringan bersama)

Dengan cara itu kita jatuh itu adalah solusi yang baik untuk masalah keamanan kita di mana paling peduli dan sangat menyadari beberapa kekurangan desain. Apakah hampir menyelesaikan implementasi ini dan sejauh ini kami senang dengan hasilnya.

Sunting: Anda dapat mengganti ide hash dengan menggunakan tanda tangan digital dan sertifikat X.509.

Vitor Arbex
sumber
1
Tampaknya cukup jelas di mana lubang keamanan yang mencolok itu. DLL yang Anda bicarakan ada di sistem klien dan tidak ada cara bagi kode server Anda untuk memverifikasi bahwa itu berbicara ke salinan DLL yang sah atau yang diretas / jahat / palsu. Anda baru saja menciptakan banyak pekerjaan untuk diri sendiri tanpa menambahkan banyak, jika ada, keamanan ekstra. Semua yang dibutuhkan oleh orang jahat adalah token dan algoritme, yang keduanya ada di DLL untuk siapa saja yang ingin melihatnya.
Scott Whitlock
@ScottWhitlock, Ya, saya setuju. kami sedang melihat ke dalam mengaburkan DLL, dan lalu lintas pergi melalui HTTPS. Kami berusaha meningkatkannya, saya sangat suka masukan apa pun tentang cara memperbaikinya. Tetapi solusi itu sudah memecahkan banyak masalah yang dimiliki sistem saat ini, termasuk kata sandi teks biasa yang disimpan dalam file jaringan. Layanan web juga memungkinkan penggunaan kembali banyak kode yang dapat diakses oleh salah satu bahasa klien yang kami gunakan di sini, termasuk klien Delphi dan Clipper (Harbor)!
Vitor Arbex
Di sistem Anda, pengguna masuk dan mungkin disahkan oleh layanan web. Dengan asumsi menggunakan HTTPS, bukankah itu cukup baik? Anda tidak harus mempercayai perangkat lunak klien, karena Anda tahu bahwa pengguna adalah yang mereka katakan, dan Anda mengontrol layanan web, jadi pastikan bahwa layanan web hanya membagikan informasi yang diizinkan untuk dilihat oleh pengguna yang diberikan. Bahkan jika mereka merekayasa balik klien dan menulis sendiri, kerusakan apa yang bisa mereka lakukan? Hanya layanan web Anda yang tahu kata sandi DB, dan itu harus aman.
Scott Whitlock