Bagaimana perakitan CLR yang dibuat dengan PERMISSION_SET =SAFE dapat mengakses sumber daya sistem eksternal, memanggil kode yang tidak dikelola, dan memperoleh hak istimewa sysadmin?
Ini karena perubahan keamanan yang dibuat di .NET Framework, mulai dari versi 4.5 (saya percaya).
Dokumentasi MSDN untuk Code Access Security Basics menyatakan:
.NET Framework menyediakan mekanisme untuk penegakan berbagai tingkat kepercayaan pada kode berbeda yang berjalan di aplikasi yang sama yang disebut Keamanan Akses Kode (CAS). Keamanan Akses Kode di .NET Framework tidak boleh digunakan sebagai mekanisme untuk menegakkan batas keamanan berdasarkan asal kode atau aspek identitas lainnya. Kami memperbarui panduan kami untuk mencerminkan bahwa Keamanan Akses Kode dan Kode Keamanan-Transparan tidak akan didukung sebagai batas keamanan dengan kode yang sebagian tepercaya, terutama kode yang tidak diketahui asalnya. Kami menyarankan agar tidak memuat dan mengeksekusi kode yang tidak diketahui asalnya tanpa menerapkan langkah-langkah keamanan alternatif.
Dan kemudian arahkan ke halaman untuk Perubahan Keamanan di .NET Framework yang menyatakan:
Perubahan paling penting pada keamanan di .NET Framework 4.5 adalah dalam penamaan yang kuat.
Yang kemudian menunjuk ke dokumentasi untuk Enhanced Strong Naming yang menyatakan:
Kunci nama yang kuat terdiri dari kunci tanda tangan dan kunci identitas. Majelis ditandatangani dengan kunci tanda tangan dan diidentifikasi oleh kunci identitas. Sebelum .NET Framework 4.5, kedua kunci ini identik. Dimulai dengan .NET Framework 4.5, kunci identitas tetap sama seperti di versi .NET Framework sebelumnya, tetapi kunci tanda tangan ditingkatkan dengan algoritme hash yang lebih kuat. Selain itu, kunci tanda tangan ditandatangani dengan kunci identitas untuk membuat tanda tangan kontra.
JUGA, dokumentasi untuk Pedoman Pengodean Aman menyatakan:
Keamanan Akses Kode dan Keamanan-Transparan Kode tidak akan didukung sebagai batas keamanan dengan kode yang sebagian tepercaya. Kami menyarankan agar tidak memuat dan mengeksekusi kode yang tidak diketahui asalnya tanpa menerapkan langkah-langkah keamanan alternatif...
Jadi, model keamanan untuk .NET berubah bertahun-tahun yang lalu, tetapi SQL Server (hingga SQL Server 2017) telah diizinkan untuk terus menggunakan model keamanan lama. Tampaknya, mulai dari SQL Server 2017, keputusan dibuat untuk tidak lagi mendukung model keamanan lama.
Saya menduga bahwa mengizinkan model keamanan lama adalah:
-
mencegah SQL Server (setidaknya fungsionalitas / komponen terkait CLR) agar tidak didasarkan pada versi .NET Framework yang lebih baru, dan
-
bertanggung jawab atas penghapusan tiba-tiba SQLCLR sebagai fitur yang didukung dari Azure SQL Database (dukungan telah ditambahkan pada akhir 2014 dengan peluncuran v12, tetapi kemudian dihapus seluruhnya pada 15 April 2016).
Jadi, ya, ini agak menyebalkan. Artinya (setidaknya untuk saat ini) adalah bahwa seseorang harus pertama buat Sertifikat atau Kunci Asimetris (yang telah digunakan untuk menandatangani Majelis apa pun yang akan dimuat) ke dalam [master]
untuk kemudian membuat Login dari dan kemudian memberikan UNSAFE ASSEMBLY
untuk Login itu. Ini adalah urutan kejadian yang sama yang perlu dilakukan saat memuat EXTERNAL_ACCESS
dan UNSAFE
Perakitan, tetapi sekarang, sayangnya, perlu dilakukan bahkan untuk SAFE
Majelis.
Saat ini tidak ada mekanisme untuk menangani ini dengan cara yang sepenuhnya portabel (yaitu tidak bergantung pada file eksternal) dan tidak dapat ditangani oleh Visual Studio / SSDT tanpa intervensi manual. Ini agak sudah terjadi, tetapi setidaknya dimungkinkan untuk membuat pengaturan untuk menangani ini dengan cara yang sepenuhnya portabel (yaitu sepenuhnya terkandung dalam skrip .sql):silakan lihat Stairway to SQLCLR Level 7:Pengembangan dan Keamanan untuk detailnya (ini adalah artikel yang saya tulis).
Dimungkinkan untuk membuat Sertifikat dari byte hex (yaitu FROM BINARY = 0x...
) tetapi itu tidak berfungsi dengan Visual Studio (yang bergantung pada MSBuild) / SSDT karena menggunakan Sertifikat memerlukan penggunaan signtool
dan MSBuild menggunakan sn
.
Agar ini dapat diterapkan sedemikian rupa sehingga proses penerbitan Visual Studio / MSBuild / SSDT berfungsi (yang pada gilirannya berarti bahwa siapa pun akan dapat membuat skrip .sql mandiri yang mampu membuat Kunci Asimetris tanpa bergantung pada file eksternal), CREATE ASYMMETRIC KEY
perintah perlu ditingkatkan untuk memungkinkan dibuat dari string biner. Saya telah membuat saran ini di Microsoft Connect – Izinkan Kunci Asimetris dibuat dari string byte hex biner seperti CREATE CERTIFICATE – jadi mohon dukung :-).
Atau (untuk saat ini, sampai MS diharapkan dapat membuat metode yang lebih baik, seperti saran Kunci Asimetris saya), Anda dapat mencoba salah satu dari dua teknik yang saya jelaskan di posting blog berikut (keduanya bekerja sepenuhnya dengan SSDT):
- SQLCLR vs. SQL Server 2017, Bagian 2:“Keamanan ketat CLR” – Solusi 1
- SQLCLR vs. SQL Server 2017, Bagian 3:“Keamanan ketat CLR” – Solusi 2
Sebagai terakhir resor, Anda dapat mempertimbangkan pendekatan berikut:
-
SEMENTARA atur
[master]
Basis data keTRUSTWORTHY ON
Untuk langkah selanjutnya (yaitu
CREATE ASSEMBLY
) untuk dijalankan dengan sukses, Login yang merupakan pemilik database (yaitu SID yang sama yang digunakan oleh[dbo]
Pengguna[master]
) harus memilikiUNSAFE ASSEMBLY
izin. Jika[master]
dimiliki olehsa
atau sysadmin lainnya, maka ia memiliki semua izin dan persyaratan ini telah dipenuhi. Tapi, jika[master]
dimiliki oleh login dengan hak istimewa rendah ("praktik terbaik"), maka Anda harus menjalankan pernyataan berikut agarCREATE ASSEMBLY
untuk bekerja saatTRUSTWORTHY
adalahON
:EXEC (N'USE [master]; GRANT UNSAFE ASSEMBLY TO [{DB_Owner_Login}];');
- Buat Majelis di
[master]
- Buat Kunci Asimetris dari Majelis
- Jatuhkan Majelis
- setel
[master]
Basis data keTRUSTWORTHY OFF
- Buat Login dari Kunci Asimetris
- Berikan
UNSAFE ASSEMBLY
ke Login itu (ini menggantikan kebutuhan DB tempat Majelis dimuat untuk disetel keTRUSTWORTHY ON
dan untuk pemiliknya Login untuk memilikiUNSAFE ASSEMBLY
izin).
Harap perhatikan bahwa saya tidak sertakan fitur "Perakitan Tepercaya" baru sebagai opsi di sini. Alasan tidak disebutkannya adalah karena memiliki lebih banyak kekurangan daripada manfaat, belum lagi itu sama sekali tidak perlu sejak awal mengingat bahwa fungsi yang ada sudah menangani situasi yang dimaksudkan untuk ditangani oleh "Majelis Tepercaya". Untuk detail lengkap tentang itu dan demo cara yang tepat untuk menangani Majelis yang ada dan tidak ditandatangani, silakan lihat:SQLCLR vs. SQL Server 2017, Bagian 4:“Majelis Tepercaya” – Kekecewaan.