Masaüstü uygulamasından veritabanı güvenliğini nasıl ele alırsınız?


12

Yaklaşık 10 yıldır SQL Server veri depolarıyla çeşitli şirket içi masaüstü istemci uygulamaları üzerinde çalıştım. Nadiren bu projelere başladım - çoğu devralma işi.

Her yerde sabit görünen bir şey, bu uygulamanın ortak veritabanına izin veren tek bir global SQL Server kullanıcı hesabı olmasıydı ve evet, bazı naif durumlarda sa, genellikle mümkün olduğunda düzeltmeye çalıştığım kullanıcı hesabını kullandı. .

Uygulamanın veritabanına erişmek için kullandığı bu kullanıcı adını ve şifreyi gerçekten etkili bir şekilde gizleyemezsiniz. Genellikle bir dosyada iniveya configdosyada saklanırlar veya büyük olasılıkla yürütülebilir dosyada pişirilirler. Her durumda, biraz kazma yaparlarsa kullanıcı tarafından görülebilirler. Bir durumda aslında bir configdosya kullandık ama şifreledik, ancak elbette şifreleme anahtarının yürütülebilir dosyada saklanması gerekiyordu (bunun sınırlamalarına naif değildik, ancak insanların yeterince bilgili olanları alay etmesini etkili bir şekilde durdurdu. configdosyalara bakmak için ).

Tüm bu sistemlerin uygulamada yerleşik bir kullanıcı kimlik doğrulama sistemi vardı, ancak elbette hepsi uygulamanın kendisi aracılığıyla yönetildi, yani kullanıcı bilgileri veritabanında saklandı. Uygulama, erişim seviyenize bağlı olarak yapabileceğiniz şeyleri kısıtladı, ancak veritabanına bağlanıp geçici sorgular çalıştırabiliyorsanız her şey tartışmalı.

Bu sorunun üstesinden gelmek için diğer sistemlerin ne yaptığını bilmek istiyorum. İşte bildiğim seçenekler:

  1. Bir kullanıcı ve roller listesini korumak için SQL Server'ın güvenlik mekanizmasını kullanın ve masaüstü uygulamasının T-SQL sorguları aracılığıyla kullanıcı ekleyip kaldırmasını sağlayın.
  2. Doğrudan veritabanına bağlanmak yerine, sunucuda çalışan bir tür web hizmeti oluşturun ve kimlik doğrulama mantığını buraya yerleştirin. Her isteğin güvenlik doğrulaması yapmasını sağlayın.

İlk seçenekler biraz çirkin, çünkü kullanıcıları veritabanından ayırıyorsunuz, böylece kullanıcılar artık birinci sınıf varlıklar değil ve yabancı anahtar ilişkileriyle referans veremezsiniz.

İkincisi, büyük bir performans sorunu ve çok fazla iş gibi görünüyor, ayrıca NHibernate gibi ORM haritacılarını kolayca kullanamazsınız (sanırım).

Herkes bu konuda deneyim var mı? En iyi uygulamalar?

Düzenle

Biraz daha düşünmek, SQL Server Kimlik Doğrulaması aslında bu sorunu çözebilir mi? Örneğin, kullanıcı size zaman çizelgesi düzenleyebilmek için takıp güncelleme zaman çizelgesi kayıtları gerekir, sen okuma ve yazma anlam SQL server zaman çizelgesi detayları tablodaki diğer satırları erişimine izin vermeyebilir yolu yok başka çok insanların zaman çizelgeleri.


Bağlamalar konusunda; NHibernate gibi ORM kullanmak değil (bence) olmayan bir konudur. Web hizmetlerini örnek olarak kullanıyorsanız, verilerinizi XML'ye verimli bir şekilde bağlamak için birçok yol bulacaksınız.
jasonk

ORM'nizi iş nesneleri ve DB varlıkları arasında doğrudan bir eşleme olarak kullanmamalısınız, bu da kırılgan arayüzler için kötü bir yaklaşımdır. Ham DB varlıklarını alan ve istemciye yalnızca gerekli verileri döndüren bir iş katmanından istekte bulunun.
gbjbaanb

@gbjbaanb - elbette, bu öğleden sonra tüm mimariyi değiştireceğim. :)
Scott Whitlock

Sanırım birisi değiştirmeden önce sizi hackleyene kadar bekleyebilirdiniz, ama parlak tarafta, en azından o zaman patronunuzu yeniden mimarlığı finanse etmekte sorun yaşamayacaksınız :-)
gbjbaanb

Kayıtları güncellemenin tek yolu olarak saklı bir yordam kullanarak ve sorgunun bir parçası olarak proc çalıştıran kullanıcıyı kullanarak bir kullanıcının başka birinin kayıtlarını güncelleştirmesini engelleyebilirsiniz. Bkz örnein
gbjbaanb

Yanıtlar:


9

Korkarım bir Web Hizmeti katmanı eklemek muhtemelen sorun için doğru çözümdür.

İstemciyi temel veritabanı uygulamasından ayırmak, muhtemelen uzun vadede size yardımcı olacaktır.

Web hizmeti katmanı eklemek, performansa zarar vermek zorunda değildir ...

Gerçekten de, uygun bir API ile bir web hizmeti, WAN üzerinden çoklu gidiş-dönüşler yapmak yerine, veri merkezi LANında birden çok veritabanı sorgusunu bir araya getirerek performansı gerçekten artırabilir.

Ve elbette bir web hizmeti katmanı genellikle yatay olarak ölçeklendirilebilir ve veritabanı sorgularınıza, hatta belki de bir değişiklik bildirim mekanizmasına uygun önbellekleme ekleyebilir.

Bir sunucu katmanı, uzak bir istemcide çalışan uygulamalarla sağlayamayacağınız güvenliği ekler. Bir istemci üzerinde çalışan herhangi bir şey "saldırıya uğrayabilir" ve hiçbir şekilde güvenilir olarak değerlendirilmemelidir. Sunum mantığını gerçekten istemciye koymalı ve tam kontrol sahibi olduğunuz donanım üzerinde önemli olan her şeyi barındırmalısınız.

Uygulamalarınızı bilmiyorum, ancak web uygulamalarım doğal olarak birkaç katmana ayrılıyor, sunum kodu kalıcılık katmanından ikisini ayıran en az bir seviye iş mantığı ile ayrılıyor. Bunun, uygulamam hakkında mantık yürütmeyi çok daha kolay hale getirdiğini ve işlevsellik eklemek veya değiştirmek için çok daha hızlı olduğunu düşünüyorum. Katmanlar yine de ayrılırsa, sunu katmanını istemcide ve geri kalanını da kontrolüm altındaki bir sunucuda tutmak nispeten kolaydır.

Bu nedenle, sorunlarınızı bir "web hizmeti" katmanı tanımadan çözebilmenize rağmen, standart veritabanı güvenliği uygulamasındaki delikleri doldurmak için gerekli tüm saklı yordamları (veya eşdeğerini) yazdığınız zaman, muhtemelen yazma konusunda daha iyi olursunuz. uygun birim testleri yazabileceğiniz bir sunucu tarafı uygulaması.


Performans darboğazı olması gerekmediğine inanıyorum, ancak mimariye kesinlikle ekstra bir katman katıyor, bu da çok daha fazla bakım anlamına geliyor.
Scott Whitlock

3
Bir katman ekler, ancak bakım gerektirmez. İstemciye değil, hizmete yerleştirilen tüm mantıkla, değişikliklerin kullanıcıların istemci uygulamalarını güncellemesine gerek kalmadan 'dağıtılabileceğini' düşünün.
GrandmasterB

5

Jmoreno'nun cevabına benzer şekilde, bir kullanıcının saklı yordamlar üzerindeki EXECUTE izinleri dışında her şeye erişimini reddedebilir, daha sonra saklı yordamın tablolarda gerekli işlemleri gerçekleştirmesi için sahiplik zincirinden yararlanabilirsiniz.

Ayrıntılar için buraya bakın https://msdn.microsoft.com/en-us/library/bb669058(v=vs.110).aspx

Kullanıcı kullanıcı adı / şifre istemcisi tarafına girdiğinde, bunları saklıyorum ve saklanan her prosedür çağrısına parametre olarak gönderiyorum. Ardından, istenen işlemi gerçekleştirmeden önce bunları bir tabloda depolanan değerlerle karşılaştırabilirsiniz.

Kesinlikle güvenlikteki son sözcük değildir, ancak PC'leriniz genel girişlere sahipse, izinler için AD gruplarını kullanma yeteneğinizi sınırlarsa veya AD'nin kendisine sınırlı erişiminiz varsa gerekli olabilir.


2

Bir yaklaşım, kullanıcının yapabileceklerini sınırlamak için AD gruplarını ve saklı yordamları kullanmaktır - örneğin zaman çizelgesi DB'niz, kullanıcı saatlerinin eklenmesi, güncellenmesi ve silinmesine izin verebilir, ancak başkalarının saatlerinin güncellenmesine izin veremez. Kullanıcının kimliği DB motoru tarafından sağlanacak, kullanıcının DB tablolarına doğrudan girişleri olmayacaktır, sadece giriş kimliğine dayalı sorguları çalıştıran sp'lere.

Tabii ki bu her zaman mümkün değil, ama olabilir. En iyi yaklaşım gereksinimlerinize ve kaynaklarınıza bağlı olacaktır.


Bu düşünmediğim bir şey. Mükemmel bir uyum olduğundan emin değilim, ama işe yarayacaktı.
Scott Whitlock

1

'Web hizmeti' olarak bahsettiğiniz şeye n-katmanlı mimari denir . Genellikle güvenlik veya yapılandırma sorunlarının muhtemel olduğu durumlarda (örneğin, bir uygulamanın birçok ofis arasında dağıtılması) gidilmesi gereken yoldur. Yine de 'web tabanlı' olması gerekmez. Birçoğu diğer protokollerle çalışır.

İstemci ile veritabanı (ve diğer kaynaklar) arasında aracı görevi görecek bir uygulama sunucusu oluşturursunuz. Uygulama sunucusu, uygulama tabanlı kimlik doğrulamanızı işler ve istemci adına eylemler gerçekleştirir. Aslında, ideal olarak istemcinizde herhangi bir SQL yapmazsınız - uygulama sunucusundaki yöntemleri çağırırsınız. Uygulama sunucusu tüm veri işlemlerini gerçekleştirir.

Yaklaşımın bir takım faydaları var. İstemcilerdeki veritabanı bağlantılarını ve sürücüleri yapılandırmanıza gerek yoktur. Veritabanı kullanıcılarını, şifreleri ve sunucuları saklamıyorsunuz. İstemcilerin yapılandırılması bile gerekli değildir; kodda doğru URL'ye veya adrese yönlendirmeniz yeterlidir. Ayrıca, uygulama sunucusundaki 'mantık' ile, diğer uygulamaları geliştirirken kendinizi tekrarlamanız gerekmez - aynı uygulama sunucusu farklı türdeki istemciler tarafından tekrar kullanılabilir.


Daha da iyisi, bir kişi masaüstlerinizi (veya web sunucusuna web tabanlı bir eşdeğeri) hacklediğinde (veya web sunucusunda), saldırganın işletim sistemine tam erişimi olabilir, ancak yine de DB'ye erişimi yoktur. Ve böylece, alıp götürdükleri, boş zamanlarında çatladıkları ve CEO'nuzun medyaya güvenli sisteminizin neden tehlikeye atıldığını açıklamasına izin veren "kullanıcılardan * seç" komutunu çalıştıramazlar. Ayrıca DB'de yalnızca yürütme erişimine izin veren sprocs kullanıyorsanız, saldırgan uygulamanızın sunucusunu da hackleyebilir ve yine de tüm kullanıcı veritabanınızı alamaz.
gbjbaanb

1

Teknoloji biraz değişti. Her kullanıcının veritabanının kimliğini doğrular ve veritabanı rollerini kullanırsanız, en azından SQL Server'da bu sorunu çözmek için artık Güncellenebilir Görünüm'ü kullanabilirsiniz.

İşte SomeTablebu tablodaki her satırın bir çalışanla bağlantılı olduğu bir tablo için güncellenebilir bir görünüm gibi görünebilir . Çalışan kendisiyle bağlantılı satırları görebilmeli ve İK rolünün üyeleri tüm satırları görebilmelidir, örneğin:

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

Ardından , tüm kullanıcılara görünüm ( vwSomeTable) üzerinde okuma (ve yazma) izinleri vermek ve tablo ( SomeTable) üzerinde hiçbir izin vermektir .

Bunu şu şekilde test edebilirsiniz:

EXECUTE AS USER = 'Some_Regular_Username'
SELECT * FROM vwSomeTable

... sadece satır (lar) ını döndürmelidir. Veya:

EXECUTE AS USER = 'Some_HR_Username'
SELECT * FROM vwSomeTable

... tüm satırları döndürür. Bu testi yapmak için yürütme (kimliğe bürünme) olarak izin vermeniz gerektiğini unutmayın.

Görünümler güncellenebilir, böylece sıralı kullanıcı bile satır kendi Employeesatırına bağlı olduğu sürece bunu yapabilir :

UPDATE vwSomeTable
SET SomeColumn = 5
WHERE SomeTable_ID = 'TheID'

0

Sertifika tabanlı kimlik doğrulamasını kullanmak, paylaşılan bir sql hesabını uygulamanın "doğru" yoludur. Amaç, bu tür şeyler için şifre kullanımını ortadan kaldırmaktır.

Güncelleme:

Sanırım soruyu yanlış anladım. Ben bir uygulama yapılandırmada db kullanıcı adı ve parola koymak için bir alternatif bulmaya çalışmakla ilgili olduğunu düşündüm, ya da uygulamanın kendisine yedeklenmiş.

Bunun yerine istemci tarafı sertifikaları kullanarak uygulamalardaki parolaları yönetme sorununu ortadan kaldırabilirsiniz. Sertifikanın kendisi yeterli değil, sertifika iptali gibi işlem yapabilen bir dağıtım ve yönetim sistemine sahip olmalısınız.

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


Bu konuda biraz daha bilgi verebilir misiniz? Orijinal sorumun amacına dik olabilir gibi görünüyor, ama ilginç.
Scott Whitlock

0

Yeni bir masaüstü güvenlik çözümü oluşturarak, aşağıda açıklamaya çalışacağım web hizmeti çözümünü seçtik.

Masaüstü uygulama yürütülebilir dosyalarını geliştiricilerden ayrı bir ortamda derliyoruz. Ve veritabanına kaydedilen bu yürütülebilir dosyadan bir HASH hesaplayın.

Uygulamanın çalışması için gereken tüm bilgileri, DB parolasını, bağlantı dizesi bilgilerini, kullanıcı izinlerini vb. Sağlayan tek bir web hizmeti.

Uygulama başına tekli DB günlüğü kullanırız ve kayıtları denetleyebilmek için kullanıcı bilgilerini oturum değişkenlerine kaydederiz.

Bir DLL, masaüstü uygulamasından web hizmetine tüm iletişimi gerçekleştirir, bu da yalnızca DLL'de bir token derlemesi ile erişilebilir.

Uygulama DB parolasını web hizmetinden alabilmek için DLL, DLL çağrıcılarını HASH'ı çalışma zamanında hesaplar ve DLL belirtecini doğrulayan web hizmetine ve çalıştırılabilir çalışma zamanı HASH'ı dağıtıldığında kaydedilene bir parametre olarak iletir (uygulama yalnızca tek bir ağ paylaşılan yüklemede kullanılabilir).

Bu şekilde düştüğümüzde, en çok ilgilendiğimiz ve birkaç tasarım kusurunun farkında olduğumuz güvenlik sorununa iyi bir çözümdür. Bu uygulamayı neredeyse bitiriyoruz ve şimdiye kadar sonuçlardan memnunuz.

Düzenleme: Karma fikri dijital imzalar ve X.509 sertifikaları kullanarak değiştirebilirsiniz.


1
Göze batan güvenlik deliğinin nerede olduğu oldukça açık görünüyor. Bahsettiğiniz DLL, istemcinin sistemindedir ve sunucu kodunuzun DLL'nin meşru bir kopyası veya saldırıya uğramış / kötü amaçlı / sahte bir kodla konuştuğunu doğrulamanın bir yolu yoktur. Çok fazla ekstra güvenlik eklemeden kendiniz için çok fazla iş yarattınız. Kötü niyetli bir kişinin ihtiyacı olan her ikisi de bakmak isteyen herkes için DLL'de bulunan jeton ve algoritmadır.
Scott Whitlock

@ScottWhitlock, Evet, katılıyorum. DLL ve HTTPS üzerinden giden trafiği gizlemeye çalışıyoruz. Bunu geliştirmeye çalışıyoruz, gerçekten nasıl geliştirileceğine dair herhangi bir girdi istiyorum. Ancak bu çözüm, ağ dosyalarında saklanan düz metin parolaları da dahil olmak üzere, mevcut sistemin sahip olduğu birçok sorunu zaten çözmektedir. Ayrıca web hizmeti, Delphi ve Clipper (Harbor) istemcileri de dahil olmak üzere burada kullandığımız istemci dillerinden herhangi biri tarafından erişilebilen bir çok kodun yeniden kullanılmasına izin verir!
Vitor Arbex

Sisteminizde, kullanıcı oturum açar ve muhtemelen web hizmeti tarafından doğrulanır. HTTPS kullanıldığında, bu yeterince iyi değil mi? Kullanıcının söylediği kişi olduğunu bildiğinizden ve web hizmetini denetlediğinizden, istemci yazılımına güvenmeniz gerekmez, bu nedenle web hizmetinin yalnızca verilen kullanıcının görmeye yetkili olduğu bilgileri verdiğinden emin olun. İstemciyi tersine değiştirip kendi yazmış olsalar bile, ne gibi zararlar verebilirler? Yalnızca web servisiniz DB şifresini bilir ve bu güvenli olmalıdır.
Scott Whitlock
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.