Mevcut kullanıcılar için yeni bir şifre zorlamadan şifre karma işleminin güncellenmesi


32

Mevcut bir uygulamayı, kurulmuş bir kullanıcı tabanı ile sürdürürsünüz. Zamanla, mevcut şifre karma tekniğinin modası geçmiş olduğuna ve iyileştirilmesi gerektiğine karar verilir. Ayrıca, UX nedenleriyle, mevcut kullanıcıların şifrelerini güncellemeye zorlanmasını istemiyorsunuz. Şifrelerin tamamen güncellenmesinin tamamı ekranın arkasında gerçekleşmelidir.

Aşağıdakileri içeren kullanıcılar için 'basit' bir veritabanı modeli düşünün:

  1. İD
  2. E-posta
  3. Parola

Kişi böyle bir gereksinimi çözmek için nasıl dolaşıyor?


Mevcut düşüncelerim:

  • uygun sınıfta yeni bir karma yöntemi oluşturun
  • Ek bir şifre alanı tutmak için veritabanındaki kullanıcı tablosunu güncelle
  • Bir kullanıcı eski parola karmaşasını kullanarak başarılı bir şekilde oturum açtığında, ikinci parola alanını güncelleştirilmiş karma ile doldurun.

Bu beni ve şifre karma değerlerini güncellemeyen ve bu nedenle her ikisini de kontrol etmeye zorlanacak kullanıcılar arasında ayrım yapamayacağıma dair sorun çıkarıyor. Bu korkunç derecede kusurlu görünüyor.

Ayrıca, bu temelde, eski karma tekniğin, her bir kullanıcı şifresini güncelleyene kadar süresiz olarak kalmaya zorlanabileceği anlamına gelir. Sadece o anda eski karma denetimini kaldırmaya başlayabilir ve gereksiz veritabanı alanını kaldırabilirim.

Burada esasen bazı tasarım ipuçlarını arıyorum, çünkü şu anki 'çözümüm' kirli, eksik ve ne olmasın, ancak olası bir çözümü tanımlamak için gerçek kod gerekiyorsa, herhangi bir dili kullanmaktan çekinmeyin.


4
Neden bir küme ile dengesiz ikincil hastayı ayırt edemesiniz? Sadece veritabanı sütunu null yapılabilir ve null olup olmadığını kontrol edin.
Kilian Foth,

6
Yeni karma için bir alan yerine, yeni sütununuz olarak bir karma türüyle gidin. Karma öğesini güncellediğinizde, tür alanını değiştirin. Bu şekilde, gelecekte bu tekrar gerçekleştiğinde, zaten başa çıkacak bir durumda olacaksınız ve eski (muhtemelen daha az güvenli) bir hash tutma şansınız yok.
Michael Kohne

1
Ben doğru yolda olduğunu düşünüyorum. Bundan 6 ay veya bir yıl sonra, kalan kullanıcıları parolalarını değiştirmeye zorlayabilirsiniz. Bir yıl sonra veya her neyse, eski alandan kurtulabilirsiniz.
GlenPeterson,

3
Neden sadece eski esrar değil?
Siyuan Ren

çünkü parolanın şifrelenmesini (eski karma değil), böylece şifresini kaldırmak (yani, kullanıcı tarafından verilen bir karma şifreyle karşılaştırmak) size ... şifreyi verir - o zaman 'yıkılmak' gereken başka bir değer değil eski yöntemde. Mümkün ama daha temiz değil.
Michael Durrant

Yanıtlar:


25

Eski yöntemi belirtmek için 1, yeni yöntemi belirtmek için 2 olan "hash_method" alanını eklemenizi öneririm.

Makul bir şekilde konuşursak, eğer bu tür bir şeye önem veriyorsanız ve başvurunuz nispeten uzun sürüyor (görünüşe göre zaten), bu muhtemelen şifreleme ve bilgi güvenliği böyle gelişmekte olan, oldukça öngörülemeyen bir alan olduğu için tekrar olacak. Eğer karma kullanılıyorsa, MD5 üzerinden basit bir işlemin standart olduğu bir zaman vardı! O zaman biri SHA1'i kullanmaları gerektiğini düşünebilir ve şimdi tuzlu, küresel tuz + bireysel rastgele tuz, SHA3, şifrelemeye hazır rasgele sayı üretmenin farklı yöntemleri var ... bu sadece 'durmayacak' bunu genişletilebilir, tekrarlanabilir bir şekilde düzeltin.

Diyelim ki şimdi şöyle bir şeyiniz var (basitlik için sözde-javascript'te, umarım):

var user = getUserByID(id);
var tryPassword = hashPassword(getInputPassword());


if (user.getPasswordHash() == tryPassword)
{
    // Authenticated!
}

function hashPassword(clearPassword)
{
    // TODO: Learn what "hash" means
    return clearPassword + "H@$I-I";
}

Şimdi daha iyi bir yöntem olduğunu fark edersek, sadece küçük bir yeniden düzenleme yapmanız gerekir:

var user = getUserByID(id);
var tryPassword = hashPassword(getInputPassword(), user.getHashingMethod());

if (user.getPasswordHash() == tryPassword)
{
    // Authenticated!
}

function hashPassword(clearPassword, hashMethod)
{
    // Note: Hash doesn't mean what we thought it did. Oops...

    var hash;
    if (hashMethod == 1)
    {
        hash = clearPassword + "H@$I-I";
    }
    else if (hashMethod == 2)
    {
        // Totally gonna get it right this time.
        hash = SuperMethodTheNSASaidWasAwesome(clearPassword);
    }
    return hash;
}

Bu cevabın üretiminde hiçbir gizli ajan veya programcı zarar görmedi.


+1 Bu oldukça mantıklı bir soyutlama gibi görünüyor, teşekkürler. Bununla birlikte, bunu uyguladığımda karma ve hashmethod alanlarını ayrı bir masaya taşımayı başarabilirim.
Willem

1
Bu tekniğin sorunu, hesaplar için oturum açmadığı için karmaları güncelleyememenizdir. Deneyimlerime göre çoğu kullanıcı, hiç olmadığı kadar yıllarca giriş yapmaz (etkin olmayan kullanıcıları silmediğiniz sürece). Soyutlamanız da gerçekten işe yaramıyor, çünkü tuzlar hesaba katmıyor. Standart soyutlama, biri doğrulama için diğeri oluşturma için iki işleve sahiptir.
KodlarInChaos

Şifre şifreleme son 15 yılda çok az gelişti. Bcrypt 1999 yılında yayınlandı ve hala önerilen karmaşelerden biri. O zamandan bu yana yalnızca önemli bir gelişme yaşandı: sırasıyla şifreli bir öncekine sahip olan sabit karmaları belleğe.
KodlarInChaos 10:13

Bu, eski hasheleri savunmasız bırakır (örneğin biri DB'yi çalarsa). Hala birbirinden ayırt etmek karma türünü gerekir (bir dereceye kadar yeni daha güvenli bir yöntem azaltan bu her eski karma karma newHash(oldHash, salt)veyanewHash(password, salt)
dbkk

42

Yeni karma şemasını tüm kullanıcılara olabildiğince çabuk (örneğin eski olanı gerçekten güvensiz olduğu için) kullanıma sunmaya yeterince önem veriyorsanız, aslında her parolanın anında "geçişi" için bir yol vardır .

Fikir temelde karma hash etmektir . Kullanıcılar bir psonraki oturum açışında mevcut şifrelerini ( ) beklemek yerine , eski algoritma ( ) tarafından zaten mevcut olan karmaH2 üzerinde yeni karma algoritmasını ( ) kullanırsınız :H1

hash = H2(hash)  # where hash was previously equal to H1(p) 

Bu dönüşümü yaptıktan sonra, hala şifre doğrulaması yapabiliyorsunuz; kullanıcı parola ile giriş yapmaya çalıştığında sadece bir H2(H1(p'))önceki yerine hesaplamanız gerekir .H1(p')p'

Teorik olarak, bu teknik, çok sayıda taşıma (tatbik edilebilir H3, H4vb.) Uygulamada, hem performans hem de okunabilirlik nedeniyle eski hash fonksiyonundan kurtulmak istersiniz. Neyse ki, bu oldukça kolay: bir sonraki başarılı oturum açışınızda, kullanıcının parolasını içeren yeni kareyi hesapla ve mevcut karışıma sahip olanı değiştir:

hash = H2(p)

Ayrıca, sakladığınız karmaşayı hatırlamak için ek bir sütuna ihtiyacınız olacaktır: şifrenin biri veya eski karma. Talihsiz veritabanı sızıntısı durumunda, bu sütun krakerin işini daha kolay hale getirmemelidir; değeri ne olursa olsun, saldırganın H2eskisinden çok güvenli algoritmayı tersine çevirmesi gerekirdi H1.


3
Dev + 1: H2 (H1 (p)) genellikle H1 korkunç olsa bile doğrudan H2 (p) kullanmak kadar güvenlidir, çünkü (1) tuz ve gerdirme H2 ile halledilir ve (2) sorunlar MD5 gibi "bozuk" kareler ile parola karmasını etkilemez. İlgili: crypto.stackexchange.com/questions/2945/...
OriP

İlginçtir ki, eski karmanın bir tür güvenlik “sorunu” yaratacağını düşündüm. Görünüşe göre yanılmışım.
Willem

4
Eğer H1 gerçekten korkunç ise, bu güvenli olmayacak. Bu bağlamda korkunç olmak, girdilerden çok fazla entropi kaybetmekle ilgilidir. MD4 ve MD5 bile bu bakımdan neredeyse mükemmeldir, bu nedenle bu yaklaşım sadece bazı kısa devre hashları veya gerçekten kısa çıktılı hashlar için güvensizdir (80 bitin altında).
KodlarInChaos,

1
Bu durumda, muhtemelen tek seçenek isimli sen berbat itiraf sert ve sadece tüm kullanıcılar için devam edin ve şifre sıfırlama. Bu noktada göç hakkında daha az ve hasar kontrolü hakkında daha fazla.
Xion

8

Çözümünüz (veritabanındaki ek sütun) tamamen kabul edilebilir. Bununla ilgili tek sorun, daha önce bahsettiğiniz sorun: eski karma işleminin, değişiklikten bu yana kimliği doğrulanmamış kullanıcılar için hala kullanılıyor.

Bu durumu önlemek için, en aktif kullanıcılarınızın yeni karma algoritmaya geçmesini bekleyebilirsiniz.

  1. Çok uzun süre kimlik doğrulaması yapmamış kullanıcıların hesaplarını kaldırın. Üç senedir web sitesine hiç gelmemiş olan bir kullanıcının hesabını kaldırmakta yanlış bir şey yoktur.

  2. Kalan kullanıcılara bir süre kimliği doğrulanmamış kullanıcılar arasında, yeni bir şeyle ilgilenebileceklerini söyleyen bir e-posta gönderin. Eski karıĢmayı kullanan hesap sayısını daha da azaltmaya yardımcı olacaktır.

    Dikkatli olun: Spam içermeyen bir seçeneğiniz varsa, kullanıcılar web sitenizi kontrol edebilirler, e-postayı kontrol eden kullanıcılara göndermeyin.

  3. Son olarak, 2. adımdan birkaç hafta sonra, hala eski tekniği kullanan kullanıcılar için şifreyi imha edin. Kimlik doğrulamaya çalışırlarsa ve parolalarının geçersiz olduğunu görürler; Hizmetinizle hala ilgileniyorlarsa, sıfırlayabilirler.


1

Muhtemelen asla bir kaç hash tipinden daha fazlasına sahip olmayacaksınız, bu yüzden veritabanınızı genişletmeden bunu çözebilirsiniz.

Yöntemlerin farklı uzunlukları varsa ve her yöntemin karma uzunluğu sabittir (md5'ten hmac-sha1'e geçiş), yöntemi karma uzunluğundan söyleyebilirsiniz. Aynı uzunluktalarsa, önce yeni yöntemi, sonra da ilk sınama başarısız olursa eski yöntemi kullanarak hash değerini hesaplayabilirsiniz. Kullanıcının en son ne zaman güncellendiğini / oluşturulduğunu söyleyen bir alanınız (gösterilmiyor) varsa, bunu hangi yöntemin kullanılacağının göstergesi olarak kullanabilirsiniz.


1

Böyle bir şey yaptım ve yeni karma olup olmadığını ve daha güvenli hale getirip getirmediğini söylemenin bir yolu var. Tahmininizi güncellemek için zaman ayırıyorsanız daha güvenli olduğunu düşünüyorum sizin için iyi bir şey ;-)

DB tablonuza "tuz" adlı yeni bir sütun ekleyin ve peki, bunu kullanıcı başına rasgele oluşturulmuş bir tuz olarak kullanın. (Gökkuşağı masa saldırılarını engeller)

Bu şekilde, şifrem "pass123" ve rasgele tuz 3333 ise, yeni şifrem "pass1233333" 'in karması olur.

Kullanıcının bir tuzu varsa, bunun yeni karma olduğunu biliyorsun. Kullanıcının tuzu null ise, bunun eski karma olduğunu bilirsiniz.


0

Geçiş stratejiniz ne kadar iyi olursa olsun, eğer veritabanı zaten çalınmışsa (ve bunun asla gerçekleşmediğini negatif olarak kanıtlayamazsanız), o zaman güvensiz hash işlevleriyle saklanan şifreler zaten tehlikeye girebilir. Bunun için tek azaltma, kullanıcıların şifrelerini değiştirmelerini gerektirir.

Bu, (sadece) kod yazarak çözülebilecek bir sorun değildir. Çözüm, kullanıcıları ve müşterileri maruz kaldıkları riskler hakkında bilgilendirmektir. Bu konuda açık olmaya istekli olduğunuzda, geçişi her kullanıcının şifresini sıfırlayarak kolayca yapabilirsiniz, çünkü en kolay ve en güvenli çözümdür. Tüm alternatifler gerçekten batırdığın gerçeğini gizlemekle ilgili.


1
Geçmişte yapmış olduğum bir uzlaşma, eski şifreleri belli bir süre saklamak, onları giriş yaptıktan sonra yeniden şekillendirmek, ancak o zaman geçtikten sonra sizi giriş yapmış olmayanlar için bir şifre sıfırlama zorlamaktır. o zaman. Bu yüzden hala daha az güvenli şifrelerinizin olduğu bir süreniz var, ancak bu zaman sınırlı ve düzenli olarak giriş yapan kullanıcılar için kesintileri de en aza indiriyorsunuz.
Sean Burton,
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.