Neden kullanıcı şifrelerini saklamalıyım?


10

Bazen bir web uygulaması için kullanıcı şifrelerinin nasıl güvenli bir şekilde saklanacağını soran sorular görüyorum (RDBMS kullanarak Facebook veya Twitter'dan bahsetmiyorum). Genel cevap "şifreyi tuzlayın, ardından TDES veya SHA512 gibi güçlü bir algoritma ile karıştırın".

Benim sorum: RDBMS kullanıcısı olarak, çoğu motorda yerleşik bir kimlik doğrulama mekanizması bulunduğundan, neden sorunlu parola depolamayı hiç rahatsız etmeyeyim.

Örneğin, bazı X kullanıcıları web uygulamamda bir hesap kullanıcı şifresi Y oluşturmak istiyorsa, aşağıdaki sorguyu yanlış verme yöntemi:

CREATE USER X WITH ENCRYPTED PASSWORD Y IN GROUP baseuser;

Sonra benim uygulama içinde, kullanıcı kendi kimlik bilgilerini kullanarak veritabanına bir bağlantı açabilir ve tüm şifre yönetimi rahatsız etmiyorum.

Bu yöntemin birçok avantajı görüyorum:

  • RDBMS, şifreleme algoritmasının değiştirilmesi gerektiğine karar verirse, yalnızca güvenlik güncelleştirmelerini uygulamak için hiçbir şeye dokunmam gerekmiyor;
  • Kullanıcıların yetkilerini yönetmek benim için kolaydır. Bir kullanıcı bir yöneticinin rolüne yükseltilirse, kullanıcıyı ilgili gruba eklemem gerekir;
  • SQL enjeksiyonları artık anlamsızdır, çünkü veritabanındaki her kullanıcıya tam olarak izin vermek istediğim izinleri yönetiyorum (örneğin, SO gibi bir forumda, yeni yayınlar ekleme, yayınlara cevap verme, yorum yapma ve kendi sorularını düzenleme / silme) / cevaplar / yorum);
  • Uygulamama kimliği doğrulanmamış bağlantılar için "anonim" kullanıcı hesabı kullanılabilir;
  • Her kullanıcı, sağladığı verilerin sahibidir.

Ancak bu konuda gördüğüm hemen hemen her soruda, işlerin yapılması gereken yolun bu olmadığı konusunda genel bir fikir birliği var gibi görünüyor. Sorum şu: neden?

Not: Üçüncü nokta tarafından izin verilen politikaları PostgreSQL ve güvenlik politikaları Microsoft SQL Server. Bu kavramların yeni gelenler olduğunun farkındayım, ama yine de, şimdi buradalar, açıkladığım teknik neden kullanıcı hesaplarını işlemek için standart bir yol haline gelmiyor?


2
Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
Paul White 9

Bu arada, olağan cevap yanlış. Parolayı tuzlamalısınız , sonra bcrypt veya argon2 gibi yavaş bir algoritma ile karıştırmalısınız.
Tgr

Yanıtlar:


27

Çünkü birçok uygulama için, bireysel kullanıcı hesaplarının veritabanına bağlanmasını istemiyorlar. Kullanıcılar / parolalar / haklar / izinler uygulama katmanında işlenir ve veritabanının arka ucuna bağlanmak için tek bir özel hizmet hesabı kullanılır.

Bir DBA olarak, veritabanı düzeyinde, bazı orta ölçekli halka açık web uygulamasının 10.000 aktif kullanıcısını veya belki de aniden popüler bir uygulamanın 2 milyondan fazla kullanıcısını yönetmek istemiyorum.

Çok gerçek anlamda, bu, uygulama geliştiricileri ile veritabanı geliştiricileri / DBA'lar arasındaki felsefe farkıdır.

Çoğu / çoğu uygulama geliştiricisi, uygulama işlevselliğinin ve / veya iş kurallarının ana yönleri için sorumlulukları veritabanı katmanına aktarmak istemeyecektir. Bunun yerine, veritabanını verileri depolamak ve almak için bir araç olarak görürler.

Bazı durumlarda, bu kısa görüşlü olabilir; Birçok RDBMS, uygulama geliştirme hayatını daha kolay hale getirebilecek harika özelliklere sahiptir (satır düzeyinde güvenlik, sütun dizini, filestream depolama, vb.).

Ancak bu daha havalı özelliklerin bazıları yalnızca daha yeni sürümlerde mevcuttur ve kuruluşlar mevcut ortamları yükseltmek için her zaman hızlı değildir ( 2014'ten bu tabloya bakın ).

Ve diğer durumlarda, bu şeyleri uygulama katmanında işlemek tercih edilir (ve sadece veritabanı platformu taşınabilirliği için değil, açıkçası iddianın abartılı olduğunu düşünüyorum).


2
İş mantığının uygulamaya mı yoksa veritabanına mı girdiği konusunda mevcut bir 'kutsal savaş' vardır. Tüm iş mantığının (özellikle güvenlik) veritabanında olduğu bir uygulama oluşturduysanız (saklı yordamlar, görünümler vb.), O zaman kimse doğrudan bağlanamayacağınız ve etrafınızda dolayamayacağınız için veritabanı güvenlik mekanizmalarını kullanmak için bir argüman olabilir. güvenlik. Özel bir tabloda bir güvenlik mekanizmasını (yani oturum açma / parola) yeniden oluşturmamanız gerektiğini tamamen kabul ediyorum. Bunu zaten etkin dizin / O365 güvenliğiniz varsa yapın.
Nick.McDmaid

1
@ Nick.McDermaid Gelecek geliştiricilerin neler olup bittiğine dair herhangi bir ipucu ipucuna sahip olma potansiyelini ortadan kaldırmak için DB ve uygulama arasında iş mantığını karıştırmamı sağlamak istiyorum, ayrıca kimse deli olmadığı için iş güvenliğimi korumama yardımcı oluyor yönetmek için yeterli.
Der Kommissar

Oraya bir web hizmeti ve bir tomcat uygulama sunucusu atın ve IBM için çalışabilirsiniz
Nick.McDermaid

8

Bölme çizgisi bu noktada biraz kabarıklaşıyor, ancak veritabanı düzeyinde kullanıcıları ve izinleri, verilerin bir parçası olmayan şemanın bir parçası olarak görüyorum ve genel uygulamalarda şemayı değiştiren bir yer yok ( her zaman olduğu gibi, bu kuralın istisnaları).

Yeni kullanıcılara ihtiyaç duyulurken ve eskileri ayrılırken uygulamalara şema nesnelerini (oturum açma, kullanıcı ve izinler) yönetmek için gereken izinleri vermemeyi tercih ederim, çünkü bu uygulama saldırıya uğradığında saldırgan bu izinlere erişebilir veritabanını daha da açmayı kolaylaştırır. Tamamen içerilen veritabanlarını kullanmadığınız sürece MS SQL Server'da oturumlar sunucu düzeyindeki nesnelerdir, bu nedenle tek uygulama veritabanının ötesinde hakları daha riskli hale getirmeniz gerekir.

Ayrıca, veritabanı düzeyinizde uygulama başına kullanıcı hesaplarınız olsa bile, kimlik doğrulaması yapılmayan isteklerle başa çıkmak için uygulama düzeyinde kullanıcı hesaplarına ihtiyacınız vardır - örneğin, uygulama kullanıcısı başarıyla doğrulanmadan önce uygulamanın veritabanından bilgi alması gerekiyorsa (belki de durum bilgilerini karşılama / giriş ekranında görüntülemek?).

Ayrıca, veritabanı motorları arasındaki taşınabilirlik bir hedefse (belki de uygulamanız hem mysql hem de postgres üzerinde çalışmak istiyor mu?), O zaman uygulamalarınızın her motor için kullanıcı / giriş yönetimi işlevlerini soyutlaştırmaları gerekir. - bu çabaya gidiyorsanız, o zaman parolaları kendiniz de uygulayabilir ve motorların sunduğu en düşük ortak özellik setini kabul etmek yerine istediğiniz yönetim seçeneklerini elde edebilirsiniz.


1
Tamam, bu yüzden "uygulama şemayı değiştirmemelidir" Bence önerdiğim tekniğe karşı ilk iyi nokta. Ancak, yeni kullanıcılar oluşturabilen anonim hesabın yalnızca en temel erişime sahip yeni kullanıcılar oluşturabilmesi gerekir. Sadece yöneticiler kullanıcıları tanıtabilir ve kullanıcıları bırakabilir, ki bu uygulamalarda aranan şeydir :-) Genel veriler anonim kullanıcı tarafından görülebilir, bu nedenle bu bağlantı kimlik doğrulama gerekli olmayan içerik için kullanılabilir. Taşınabilirlik de iyi bir noktadır, ancak kullanıcı komutlarının artık standardın bir parçası olduğunu düşünüyorum (emin değilim, yıllar önce değildi)
Fabian Pijcke

Bu ayar ile, bir bilgisayar korsanı anonim kullanıcı olarak veritabanına erişirse, istediği kadar kullanıcı oluşturabilir, ancak bu bir güvenlik sorunu değildir, aynı zamanda veritabanından birini kullanarak oluşturulan hesaplar, bu can sıkıcı ama yine de hiçbir güvenlik sorunu (ve yine de standart arayüzü kullanarak yapabilirdi, ama çok daha yavaş olurdu: p)
Fabian Pijcke

3
Güvenlik açısından veritabanı düzeyinde kullanıcıların daha iyi olacağını kabul ediyorum. Bununla birlikte, 50 milyon kayıtlı kullanıcınızın olduğu çevrimiçi mağazalarla yönetilmesi temel olarak imkansızdır. Her birinin bir veritabanı kullanıcısı olması gerekir. Artı: bu genellikle bir bağlantı havuzu kullanan web uygulamalarıyla iyi oynamaz.
a_horse_with_no_name

6

Soruyu yeniden ifade etme

Neden kullanıcı şifrelerini saklamalıyım?

En basit cevap, bunu yapmanız gerektiğidir. Şifreleri hala alternatif yönteminizde saklıyorsunuz. Depolamayı yönetmek için veritabanının yerleşik sistemini kullanmanız yeterlidir. Yani yönteminiz sadece veritabanınız kadar iyidir. Bu, aksi takdirde yapabileceklerinizden daha iyi olabilir, ancak depolamadan kaçınmaz. Gerçekten sadece kodlama deposundan kaçınıyor.

Ayrıca daha iyi olmayabilir. Bir veritabanının güvenliğini aşar ve dosyaların kopyalarını alırsam, tablolara doğrudan erişebilirim. Bu yüzden mükemmel bir şifre yönetim sistemi kullanmanın pek bir anlamı yoktur. Çünkü birisi parolaları veya karma parolaları içeren sistem düzeyi tablosuna erişebiliyorsa, dosyalara doğrudan da erişebilir. Verilere zaten sahip olduğunuzda neden şifreleri kırmıyorsunuz? Verileri kolayca şifreleyebileceğiniz gibi değil. Her kullanıcının erişebilmesi gerekir. Bu nedenle kullanıcı düzeyinde şifreleme çok iyi çalışmaz.

Ama gerçekten sorduğunuz gibi

Veritabanında zaten bir uygulama varken neden uygulama düzeyinde bir kimlik doğrulama düzeni kullanılmalı?

Güvenlik

Daha güvenli bir sürüm yazma olasılığını göz ardı ederek, diğerleri bir dizi neden önermişlerdir. Genel olarak katılıyorum. Ama henüz kimsenin bahsetmediği bir tane daha var. Veritabanınızın güvenliğinden ödün veriyorsunuz.

Bu sistemde, uygulamanızın her kullanıcısının bir veritabanı kullanıcısı ve parolası vardır. Tabii, sınırlı bir kullanıcı, ama yine de veritabanına bağlanabilen bir kullanıcı. Satır düzeyinde güvenlik kullansanız bile, son kullanıcıların veritabanı bağlantı bilgilerini bilmesine izin veriyorsunuz. Bir kullanıcının tablo düzeyinde erişim sağlayabileceği bir istismar varsa, veritabanınızı saldırmak için açtınız. Ve bazı istismarlar yönetici erişiminin ötesine geçti.

Güvenlik soğanının katmanlarında normal sistem:

  • Yalnızca belirli makinelerin bağlantılarına izin veren veritabanı.
  • Veritabanı, yalnızca belirli kullanıcı / şifre kombinasyonları gibi bağlantılara izin verir.
  • Uygulamalardan bağlantılara izin veren veritabanı izinlerine sahip sunucular.
  • Uygulamalar sunucuda çalıştırılır.
  • Uygulamaların sınırlı ayrıcalıklara sahip veritabanı bağlantı bilgileri vardır.
  • Uygulamalar, veritabanını değiştirmelerine izin vermeden önce kullanıcıların kimliğini doğrular (muhtemelen yeni hesaplar oluşturma hariç).

Bu sistemde:

  • Son kullanıcılar, çok düşük ayrıcalıklarla, veritabanında çalışacak kullanıcı / şifre kombinasyonlarını bilirler.
  • Sadece bir sunucu içermeli veya ikna edici bir şekilde yetkili bir sunucu gibi davranmalıdır.

Tüm uygulama güvenlik düzeyini kaybettik. Ve veritabanı katmanının bir kısmını gönüllü olarak bıraktık. Yani sadece iki istismara ihtiyacımız var:

  1. Yetkili sunucuyu aldatın veya güvenliğini sağlayın.
  2. Sınırlı ayrıcalık hesabının erişimini artırın.

Bu iki şeyi yapabilirsek, veritabanına erişimimiz olur. Bu yüzden üç katmandan ikiye geçiyoruz. (Normal sistemdeki üçüncü katman, veritabanına bağlanmak için geçerli bir kullanıcıya ihtiyaç duymanızdır.)

Bu hesapların birçok yönetimini yapacaksınız. Ya bir hata yaparsan? X kullanıcısını yalnızca belirli satırlarla sınırlamak yerine, hepsine kritik bir tabloya erişim izni verirsiniz. Bu tür şeyler normalde manuel olarak yapılır ve bunlardan sadece birkaçı vardır, bu nedenle denetlenmesi kolaydır. Ancak sisteminizde, her birinin kendi kendine özgü erişimi olan binlerce veya milyonlarca hatta milyarlarca kullanıcı hesabı yapıyor olabilirsiniz.

Bu nedenle, veritabanının sistemi milyonlarca veya milyarlarca kullanıcıya ölçekleniyor mu? Varsa, kural sayısı ne olacak? Her kullanıcı neye erişebildikleri ve erişemedikleri hakkında yüz veya daha fazla kural alırsa, bu bir milyar kullanıcıya kadar ölçeklenebilir mi? Normalde küçük ölçekli bir sistem alıyorsunuz ve onu büyük ölçekli yapıyorsunuz. Bu mutlaka işe yaramaz. Büyüdükçe sistem sınırlamaları bulabilirsiniz.


5

Açıkladığınız şey kimlik doğrulamasını işleyecek, ancak yetkilendirmeyi (kullanıcının hangi verilere erişebileceğini) veya yalnızca kullanım durumunun en basitini ele almayacaktır.

Stackexechange ile örneğinize devam etmek için: Silinen yayını yalnızca yüksek rep kullanıcısı için nasıl görünür hale getirirdiniz? Dolayısıyla, erişim kuralları için yine de kodda mantık gerekir. Erişim mantığını veritabanı kuralları ve uygulanabilir erişim kuralları arasında paylaşmak yerine, çoğu geliştirici hepsinin aynı yerde olmasını tercih eder.

Kullanıcı bilgilerini depolamak için bir tabloya da ihtiyacınız olacak: bir kullanıcı sadece bir kullanıcı adı + şifre değildir. Bir e-postası, bir itibarı vb. Vardır. Böylece, erişebilmeniz şartıyla, veritabanı kullanıcı tablosuyla senkronize olduğundan emin olmanız gereken kullanıcı tablosuna hala ihtiyacınız vardır.

Çözümünüzle, doldurması çok zor olmayan bir şifre sütununu atlayabilirsiniz: şifrelerin nasıl işleneceği / özetleneceği hakkında iyi kütüphaneler ve belgeler vardır.

Başka bir nokta: nasıl bir bağlantı havuzu oluşturmak istiyorsunuz? Ben sadece jdbc (java <-> db) biliyorum, ve sonra bir havuz almak için bir bağlantı almak için bir kullanıcı adı + şifre sağlamanız gerekir.

Yerleşik yoldan daha zor / daha kıvrımlı olacak bazı noktaları düşündüm:

  • şifre kurtarma ile başa çıkmak
  • İlk uygulamadan 2 yıl sonra, ürün yöneticiniz sizden oauth şeması için destek eklemenizi veya çift faktörlü kimlik doğrulamasına izin vermenizi ister

CREATE POLICY deleted_posts_high_rep ON posts FOR SELECT TO baseuser USING ((SELECT rep FROM users WHERE name = current_user()) > 10000)İlk sorunuza cevap gibi bir şey . Ben artık bir kullanıcı tabloya ihtiyaç duymadım ve db kullanıcı tablosu ile senkronizasyonu sağlamak biraz zor ama mümkün olduğunu söylemedim. Tartışılan tekniğin ana noktası güvenliktir. Bağlantı havuzu gelince, OCaml ile çalışmak ve ben neden bir bağlantı havuzu gerekir alamadım söylemek gerekir. Şu anda bağlantıları dönen 0-ary işlevleriyle çerez değerlerini ilişkilendiren bir karma harita kullanıyorum :-)
Fabian Pijcke

5
Bağlantı havuzu, performansı artırmak için uygulanır: onlarla birlikte, her kullanıcı isteği için bir bağlantı kurmanıza gerek yoktur (bu nedenle, tcp bağlantısı + veritabanıyla tüm bağlantı ve kimlik doğrulaması oluştururken cpu / io / latency'den tasarruf edin). Politika tanımına gelince: veritabanınız, bir kez kontrol etmiş olsanız bile, verilere her erişimde sürekli erişimi kontrol edecektir. Ayrıca 'erişim reddedildi veya yasaklandı', 'Tamam, sonuç yok' ile aynı değildir. Güvenlik adamlarının OK sürümünü tercih edeceğinden emin değilim.
Thierry

3
Fabian, bağlantı havuzu her türlü ölçekte esastır, kullanmamayı düşünmemeniz gerçekten bir varsayılan. İşte size ne kadar önemli olduğu hakkında bir fikir vermek için bazı kriterler: Bağlantı havuzlaması ile 600x performans artışı ( vladmihalcea.com/2014/04/17/the-anatomy-of-connection-pooling ) ve 4.000x üzeri performans artışı bağlantı havuzu oluşturma ( progress.com/tutorials/jdbc/… ). Büyüklük farkının birkaç sırası, "sahip olmak güzel" değil, uygulamalar onsuz durma noktasına öğütülür.
Ivan McA

1
İlginç numaralar. Ve aslında, bağlantı havuzları kullanmayan bir uygulama görmedim. Ama onları bu kadar hızlanmaları için bilmiyordum (ve beklemiyordum). Bağlantı havuzuyla elde ettiğiniz diğer özellik kaynak kontrolüdür: onlar sayesinde, bir kerede bağlanmaya çalışan istemcideki büyük bir artış uygulamanızı yavaşlatacaktır, ancak veritabanınız o kadar fazla etkilenmeyecektir (havuz iyi yapılandırılmışsa) .
Thierry

Tamam, sadece bağlantı havuzları hakkında daha fazla bilgi aradım ve web sitesinin saniyede yüzden fazla bağlantıyı ele alması gerektiğinde bunun çok geçerli bir nokta olduğunu kabul ediyorum, ki bu yüksek değil. PostgreSQL'deki her bağlantının yaklaşık 10MiB RAM yediği görülüyor! Hiç bu kadar çok olduğunu düşünmemiştim.
Fabian Pijcke

1

Başka bir nokta: birçok [1] web uygulaması, uygulamanın kendisi aracılığıyla çevrimiçi olarak bir kullanıcı hesabı kaydetmenize ve oluşturmanıza olanak tanır. Bu, anonim kullanıcınızın (birinin sahip olacağı en az ayrıcalıklara sahip olması gerekir) kullanıcı oluşturma ve ayrıcalık verme haklarına sahip olması gerektiği anlamına gelir!

Tamam, hangi ayrıcalıkları verebileceğini sınırlamak ve daha üst düzey kullanıcılara daha fazla hibe seçeneği vermek mümkün olabilir (bunun farkında değilim - sık sık "ayrıcalıklar tanımak" değildir). Ama yine de, herkesin hacklemesine hibe ayrıcalıkları olan bir şeyi çevrimiçi yapmak anlamına geliyor. Eminim bunu yapsaydım DBA'm beni sevmez :)

Bir düzeyde bu sorunun zaten var olduğunu biliyorum, ancak web uygulamasının DB kullanıcılarını yönetmesine izin vermiyorsanız, özellikle verileri silmek için savunma katmanlarınız var.

Ayrıca, bu, toplanan veya yeniden kullanılan DB bağlantılarının kullanılmasını önler.

[1] Çoğu söyleyebilirim, ama destekleyecek rakamlar değil

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.