MySQL kullanıcı adını ve şifresini yeniden derlemeden nasıl koruyabilirim?


87

Java .classdosyaları oldukça kolay bir şekilde derlenebilir. Giriş verilerini kodda kullanmak zorunda kalırsam veritabanımı nasıl koruyabilirim?


Umarım sorunuzu yeniden etiketlememin sakıncası yoktur. "Kullanıcı adı" ve "şifre" yi kaldırdım ve "tersine mühendislik" ve "yeniden derlemeyi" ekledim. Orijinallerinden daha açıklayıcı olduklarını düşünüyorum. Bu arada, temellerle ilgili mükemmel bir soru!
William Brendel

6
Java kullanıyor olmanın burada gerçekten alakalı olmadığını unutmayın. Herhangi bir dilde sabit kodlanmış parolalara sahip olmak hemen hemen aynı şekilde sorunludur ("ikili dizeler" C programlarında da dize sabitlerini gösterir).
Joachim Sauer

@saua: Doğru, ama belki birisi Java'da kullanıcı adlarının ve parolaların nasıl ayrıştırılacağına dair bazı örnek kodlar gönderebilir. Zamanım olursa bunu kendim bile yapabilirim.
William Brendel

1
Birçok yanıtın, uygulamayı çalıştıran kullanıcı tamamken kullanıcı adını / şifrelerini yetkisiz bir kullanıcıdan gizlemeye çalıştığınızı düşündüğünü fark ettim. Şifreyi HERKES'den gizlemek istediğinize inanıyorum . Lütfen soruda bunu netleştirin.
pek

1
Örneğin, kimlik bilgilerinin, uygulama dışında kimsenin oturum açamayacağı bir sunucuya bağlanmak için kullanıldığını söyleyin.
pek

Yanıtlar:


124

Şifreleri asla kodunuza sabit kodlamayın. Bu, yakın zamanda En Tehlikeli 25 Programlama Hatası arasında gündeme getirildi :

Yetenekli tersine mühendisler için yazılımınıza gizli bir hesabı ve parolayı sabit kodlamak son derece kullanışlıdır. Parola tüm yazılımlarınızda aynıysa, bu parola kaçınılmaz olarak öğrenildiğinde her müşteri savunmasız hale gelir. Ve sabit kodlu olduğu için düzeltilmesi çok büyük bir acı.

Parolalar dahil olmak üzere yapılandırma bilgilerini, uygulamanın başladığında okuduğu ayrı bir dosyada saklamalısınız. Bu, kod çözme işleminin bir sonucu olarak parolanın sızmasını engellemenin tek gerçek yoludur (başlamak için asla ikili dosyada derlemeyin).

Bu yaygın hata hakkında daha fazla bilgi için CWE-259 makalesini okuyabilirsiniz . Makale, sorunla ilgili daha kapsamlı bir tanım, örnekler ve birçok başka bilgi içerir.

Java'da bunu yapmanın en kolay yollarından biri Tercihler sınıfını kullanmaktır. Bazıları bir kullanıcı adı ve şifre içerebilen her türlü program ayarını saklamak için tasarlanmıştır.

import java.util.prefs.Preferences;

public class DemoApplication {
  Preferences preferences = 
      Preferences.userNodeForPackage(DemoApplication.class);

  public void setCredentials(String username, String password) {
    preferences.put("db_username", username);
    preferences.put("db_password", password);
  }

  public String getUsername() {
    return preferences.get("db_username", null);
  }

  public String getPassword() {
    return preferences.get("db_password", null);
  }

  // your code here
}

Yukarıdaki kodda, setCredentialskullanıcı adı ve şifre için bir iletişim kutusu gösterdikten sonra yöntemi çağırabilirsiniz . Veritabanına bağlanmanız gerektiğinde , depolanan değerleri almak için getUsernameve getPasswordyöntemlerini kullanabilirsiniz. Oturum açma kimlik bilgileri ikili dosyalarınıza sabit bir şekilde kodlanmayacaktır, bu nedenle de derleme bir güvenlik riski oluşturmayacaktır.

Önemli Not: Tercih dosyaları yalnızca düz metin XML dosyalarıdır. Yetkisiz kullanıcıların ham dosyaları görüntülemesini önlemek için uygun adımları attığınızdan emin olun (UNIX izinleri, Windows izinleri vb.). En azından Linux'ta bu bir sorun değildir, çünkü çağırmak Preferences.userNodeForPackageXML dosyasını mevcut kullanıcının ev dizininde oluşturur ve bu zaten diğer kullanıcılar tarafından okunamaz. Windows'ta durum farklı olabilir.

Daha Önemli Notlar: Bu cevabın yorumlarında ve diğerlerinde bu durum için doğru mimarinin ne olduğu hakkında birçok tartışma yapılmıştır. Orijinal soru, uygulamanın kullanıldığı bağlamdan gerçekten bahsetmiyor, bu yüzden aklıma gelen iki durum hakkında konuşacağım. Birincisi, programı kullanan kişinin veritabanı kimlik bilgilerini zaten bildiği (ve bilmeye yetkili olduğu) durumdur. İkincisi, geliştirici olarak, veritabanı kimlik bilgilerini programı kullanan kişiden gizli tutmaya çalıştığınız durumdur.

İlk Durum: Kullanıcı, veritabanı oturum açma kimlik bilgilerini bilmeye yetkilidir

Bu durumda yukarıda bahsettiğim çözüm işe yarayacaktır. Java Preferencesınıfı, kullanıcı adını ve parolayı düz metin olarak saklayacak, ancak tercihler dosyası yalnızca yetkili kullanıcı tarafından okunabilecektir. Kullanıcı basitçe tercihler XML dosyasını açabilir ve oturum açma kimlik bilgilerini okuyabilir, ancak bu bir güvenlik riski değildir çünkü kullanıcı başlangıçta kimlik bilgilerini biliyordu.

İkinci Durum: Oturum açma kimlik bilgilerini kullanıcıdan gizlemeye çalışmak

Bu daha karmaşık bir durumdur: kullanıcı oturum açma kimlik bilgilerini bilmemeli, ancak yine de veritabanına erişmesi gerekir. Bu durumda, uygulamayı çalıştıran kullanıcının veritabanına doğrudan erişimi vardır, bu da programın oturum açma kimlik bilgilerini önceden bilmesi gerektiği anlamına gelir. Yukarıda bahsettiğim çözüm bu durum için uygun değil. Veritabanı oturum açma kimlik bilgilerini bir tercihler dosyasında saklayabilirsiniz, ancak kullanıcı, sahibi olacağı için bu dosyayı okuyabilecektir. Aslında, bu davayı güvenli bir şekilde kullanmanın gerçekten iyi bir yolu yok.

Doğru Durum: Çok katmanlı mimari kullanma

Bunu yapmanın doğru yolu, veritabanı sunucunuz ile istemci uygulamanız arasında, tek tek kullanıcıların kimliğini doğrulayan ve sınırlı sayıda işlemin gerçekleştirilmesine izin veren bir orta katmana sahip olmaktır. Her kullanıcının kendi oturum açma kimlik bilgileri olur, ancak veritabanı sunucusu için değil. Kimlik bilgileri, orta katmana (iş mantığı katmanı) erişime izin verir ve her kullanıcı için farklı olur.

Her kullanıcının kendi kullanıcı adı ve şifresi olacaktır ve bunlar herhangi bir güvenlik riski olmaksızın bir tercihler dosyasında yerel olarak depolanabilir. Buna üç katmanlı mimari denir (katmanlar veritabanı sunucunuz, iş mantığı sunucunuz ve istemci uygulamanızdır). Daha karmaşık, ancak bu tür şeyleri yapmanın gerçekten en güvenli yolu.

Temel işlem sırası şöyledir:

  1. Müşteri, kullanıcının kişisel kullanıcı adını / şifresini kullanarak iş mantığı katmanıyla kimlik doğrulaması yapar. Kullanıcı adı ve şifre kullanıcı tarafından bilinir ve hiçbir şekilde veritabanı oturum açma bilgileriyle ilgili değildir.
  2. Kimlik doğrulama başarılı olursa, istemci iş mantığı katmanına veritabanından bazı bilgiler isteyen bir istekte bulunur. Örneğin, bir ürün envanteri. İstemcinin isteğinin bir SQL sorgusu olmadığını unutmayın; gibi uzak bir prosedür çağrısıdır getInventoryList.
  3. İş mantığı katmanı, veritabanına bağlanır ve istenen bilgileri alır. İş mantığı katmanı, kullanıcının isteğine göre güvenli bir SQL sorgusu oluşturmaktan sorumludur. SQL sorgusundaki tüm parametreler, SQL enjeksiyon saldırılarını önlemek için temizlenmelidir.
  4. İş mantığı katmanı, envanter listesini istemci uygulamasına geri gönderir.
  5. Müşteri envanter listesini kullanıcıya gösterir.

Tüm süreç boyunca , istemci uygulamasının hiçbir zaman doğrudan veritabanına bağlanmadığını unutmayın . İş mantığı katmanı, kimliği doğrulanmış bir kullanıcıdan bir istek alır, istemcinin bir envanter listesi isteğini işler ve ancak o zaman bir SQL sorgusu yürütür.


4
Bu, birisinin kullanıcı adını / şifreyi almasını tam olarak nasıl engeller? O halde onu dosyadan okuyamaz mısın?
Joe Phillips

Cevabımda söylediğim gibi, dosya izinleriniz doğru ayarlanmışsa, sadece programı çalıştıran kullanıcının bu tercihler dosyasına okuma erişimi vardır. UNIX ortamlarında bu otomatik olarak yapılır. Windows ek adımlar gerektirebilir (Windows'u fazla kullanmadığım için gerçekten emin değilim).
William Brendel

Bence fikir, uygulamayı çalıştıran kullanıcının onu saklamaya çalıştığınız kişi olmamasıdır. Eğer durum buysa, şifrelemeniz gerekir.
Michael Haren

Evet, Michael haklı. Esasen fikir, kullanıcı adını / şifreyi zaten bilmenizdir, bu yüzden bunu kendinizden saklamanıza gerek yoktur. Ancak dosya izinleriyle diğer kullanıcılardan gizlenecektir.
William Brendel

7
Bir kullanıcıya bir DB düzenleme uygulaması dağıtıyorsanız (örneğin) ve onların veritabanı kullanıcı adını ve şifresini bilmelerini istemiyorsanız, çözümü yanlış tasarlamışsınızdır ve istemci yazılımı bir sunucu ile iletişim kuruyor olmalıdır ( Örneğin, DB işini yapan bir web servisi).
JeeBee

15

Parolayı uygulamanın okuyacağı bir dosyaya koyun. Parolaları ASLA bir kaynak dosyaya yerleştirmeyin. Dönem.

Ruby'nin bu tür bir kullanım için DBI :: DBRC adında az bilinen bir modülü vardır . Java'nın bir eşdeğeri olduğundan şüphem yok. Neyse, yazmak zor değil.


7
Bu, parolaları daha sonra değiştirmeyi biraz kolaylaştırsa da, temel güvenlik sorununu çözmez.
Brian Knoblauch

Evet öyle. William Brendel'in cevabına da bakınız.
Keltia

1
Keltia ve benim işaret ettiğimiz yöntem, bu sorunla başa çıkmanın kabul edilmiş yoludur. Oturum açma kimlik bilgilerinizi derlenmiş kodunuzdan ayırmak, en temel yazılım güvenliği uygulamalarından biridir. Oturum açma kimlik bilgilerini ayrı bir dosyaya koymak, bunu başarmanın etkili bir yoludur.
William Brendel

Ayrıca, konfigürasyon bilgilerinizin bir düz metin dosyasında olması işletim sistemi kısıtlamaları ile iptal edilmelidir. Örneğin, UNIX'te, düz metin dosyası programı çalıştıran kullanıcıya ait olmalı ve 0600 izinlerine sahip olmalıdır, böylece yalnızca sahibi okuyabilir.
William Brendel

4
Tamam, böylece dosya yalnızca programı çalıştıran kullanıcı tarafından okunabilir. Harika. Bu hiçbir şeyi çözmez. :-) ben, şifre gizli tutmak için çalışıyoruz kullanıcı, ... app gibi rahatlıkla okuyabilirsiniz
Brian Knoblauch

3

Bir web uygulaması mı yazıyorsun? Öyleyse, JNDI'yı uygulamaya harici olarak yapılandırmak için kullanın. Burada bir genel bakış mevcuttur :

JNDI, bir uygulamanın ağ üzerinden uzak hizmetleri bulması ve bunlara erişmesi için tek tip bir yol sağlar. Uzak hizmet, bir mesajlaşma hizmeti veya uygulamaya özgü bir hizmet dahil olmak üzere herhangi bir kurumsal hizmet olabilir, ancak tabii ki bir JDBC uygulaması esas olarak bir veri tabanı hizmetiyle ilgilenir. Bir DataSource nesnesi oluşturulduktan ve bir JNDI adlandırma hizmetine kaydedildikten sonra, bir uygulama bu DataSource nesnesine erişmek için JNDI API'sini kullanabilir ve bu, daha sonra temsil ettiği veri kaynağına bağlanmak için kullanılabilir.


sağlanan bağlantı bozuk
James Oravec

2

Ne yaparsanız yapın, hassas bilgiler bir yerde bir dosyada saklanacaktır. Amacınız bunu mümkün olduğunca zorlaştırmaktır. Bunun ne kadarını elde edebileceğiniz, projenize, ihtiyaçlarınıza ve şirketinizin cüzdanının kalınlığına bağlıdır.

En iyi yol, herhangi bir yerde herhangi bir şifre saklamamaktır. Bu, parola karmaları oluşturmak ve depolamak için karma işlevler kullanılarak elde edilir:

hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366

Karma algoritmalar tek yönlü işlevlerdir. Herhangi bir miktarda veriyi tersine çevrilemeyen sabit uzunlukta bir "parmak izine" dönüştürürler. Ayrıca, giriş çok küçük bir bit bile olsa, ortaya çıkan karmanın tamamen farklı olma özelliğine sahiptirler (yukarıdaki örneğe bakın). Bu, parolaları korumak için harikadır, çünkü parolaları, parola dosyası ele geçirilse bile onları koruyan bir biçimde saklamak istiyoruz, ancak aynı zamanda bir kullanıcının parolasının doğru olduğunu doğrulayabilmemiz gerekir.

İlgisiz not: İnternetin eski günlerinde, 'şifremi unuttum' bağlantısını tıkladığınızda, web siteleri size düz metin şifrenizi e-posta ile gönderiyordu. Bunları muhtemelen bir yerde bir veritabanında saklıyorlardı. Bilgisayar korsanları veritabanlarına eriştiklerinde, tüm şifrelere erişim elde edeceklerdi. Birçok kullanıcı aynı parolayı birden fazla web sitesinde kullanacağından, bu çok büyük bir güvenlik sorunuydu. Şans eseri, günümüzde bu yaygın bir uygulama değil.

Şimdi soru geliyor: şifreleri saklamanın en iyi yolu nedir? Ben ele alacak bu (kimlik doğrulama ve kullanıcı yönetimi hizmeti stormpath en) çözümü bayağı İdeal bir:

  1. Kullanıcınız kimlik bilgilerini girer ve bu, parola karmasına karşı doğrulanır
  2. Parola karmaları oluşturulur ve saklanır, parolalar değil
  3. Hashes, birden çok kez gerçekleştirilir
  4. Hash'lar rastgele oluşturulmuş bir tuz kullanılarak oluşturulur
  5. Hash'ler özel bir anahtarla şifrelenir
  6. Özel anahtar, karma değerlerden fiziksel olarak farklı bir yerde saklanır
  7. Özel anahtarlar zamana göre güncellenmiştir
  8. Şifrelenmiş hash'ler parçalara bölünmüştür
  9. Bu parçalar fiziksel olarak ayrı yerlerde saklanır

Açıkçası Google veya banka değilsin, bu yüzden bu senin için aşırı bir çözüm. Ama sonra şu soru geliyor: Projeniz ne kadar güvenlik gerektiriyor, ne kadar zamanınız ve paranız var?

Pek çok uygulama için, önerilmese de, kodda sabit kodlanmış parolanın saklanması yeterince iyi bir çözüm olabilir. Ancak yukarıdaki listeden birkaç ekstra güvenlik adımını kolayca ekleyerek uygulamanızı çok daha güvenli hale getirebilirsiniz.

Örneğin, 1. adımın projeniz için kabul edilebilir bir çözüm olmadığını varsayalım. Kullanıcıların her seferinde şifre girmesini istemezsiniz veya kullanıcıların şifreyi bilmesini bile istemezsiniz / buna ihtiyaç duymazsınız. Yine de bir yerlerde hassas bilgileriniz var ve bunu korumak istiyorsunuz. Basit bir uygulamanız var, dosyalarınızı depolayacak bir sunucu yok veya bu projeniz için çok fazla güçlük yaratıyor. Uygulamanız, dosyaların güvenli bir şekilde saklanmasının mümkün olmadığı ortamlarda çalışır. Bu en kötü durumlardan biridir, ancak yine de bazı ek güvenlik önlemleriyle çok daha güvenli bir çözüme sahip olabilirsiniz. Örneğin, hassas bilgileri bir dosyada saklayabilir ve dosyayı şifreleyebilirsiniz. Şifreleme özel anahtarının kodda sabit kodlanmasını sağlayabilirsiniz. Kodu gizleyebilirsiniz, böylece birinin onu kırmasını biraz daha zor hale getirebilirsiniz.bu bağlantı . (Bunun% 100 güvenli olmadığı konusunda sizi bir kez daha uyarmak istiyorum. Doğru bilgi ve araçlara sahip akıllı bir bilgisayar korsanı bunu hackleyebilir. Ancak gereksinimlerinize ve ihtiyaçlarınıza göre bu sizin için yeterince iyi bir çözüm olabilir).



0

MD5 bir şifreleme algoritması değil, bir karma algoritmadır, kısacası karma işlemi yapamazsınız, yalnızca karşılaştırabilirsiniz. İdeal olarak kullanıcı kimlik doğrulama bilgilerini saklarken kullanılmalı ve kullanıcı adı ve şifresini değil. db kullanıcı adı ve pwd, en azından şifrelenmeli ve bir yapılandırma dosyasında saklanmalıdır.


Tüm olası dizge kombinasyonlarını oluşturan ve karşılık gelen MD5 hash'lerini depolayan insanları duydum. Yani birinin MD5 karmasını bulduklarında, sakladıkları karmayı bulurlar ve karşılık gelen dizeyi alırlar.
Nav
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.