Lütfen Dikkat: Güvenli parola saklaması için doğru yöntemin scrypt veya bcrypt olduğunu biliyorum. Bu soru gerçek yazılımda uygulama için değil, kendi anlayışım için.
İlgili
Arka plan
Bildiğim kadarıyla, şifre doğrulayıcıları saklamak için önerilen/onaylanan yöntem saklamaktır:
$verifier = $salt + hash( $salt + $password )
Nerede:
hash()bir şifreleme karma algoritmasıdır
$saltRastgele, eşit olarak dağıtılmış, yüksek bir entropi değeridir
$passwordKullanıcı tarafından girilen şifredir
Bazı insanlar karışıma gizli bir anahtar eklemeyi tavsiye eder (bazen biber olarak adlandırılır). Biber gizli, yüksek entropi, sisteme özgü bir sabittir.
Gerekçe, saldırgan şifre doğrulayıcıları ele geçirse bile, biber değerini bilmemesi için iyi bir şans var. Böylece başarılı bir saldırı yapmak zorlaşır.
Sorum şu:
Parolaları karıştırırken bir tuza ek olarak bir biber değeri eklemek genel güvenliği artırır mı?
Yoksa algılanan artan güvenlik yanlış varsayımlara mı dayanıyor?
Hızlı Güncelleme
$salt 'Un amacını biliyorum (bunun hakkında StackOverflow üzerine oldukça zun bir cevap yazdım) ek
$pepper Anahtarı değil tuzun ne yaptığını geliştirmek.
Soru şu:
$pepper Tuzdan daha fazla güvenlik diğer ekliyor mu?
Bazı durumlarda, biberler yardımcı olabilir.
Tipik bir örnek olarak, diyelim ki bir web uygulaması oluşturuyorsunuz. Webapp kodundan (bazı webapp çerçevesinde çalışan ASP.NET MVC, Python'daki Piramit, önemli değil) ve bir Depolama için SQL Veritabanı. Webapp ve SQL DB farklı fiziksel sunucularda çalışır.
Veritabanına karşı en yaygın saldırı başarılı bir SQL Enjeksiyon Saldırısıdır. Webapp farklı bir sunucu ve kullanıcı kimliğinde çalıştığından, bu tür saldırılar mutlaka webapp kodunuza erişim sağlamaz.
Şifreleri güvenli bir şekilde saklamanız gerekir ve şu formda bir şey bulmalısınız:
$hashed_password = hash( $salt . $password )
burada
$salt,
$hashed_password temsili ve her yeni veya değiştirilmiş şifre için rastgele seçilir ile birlikte veritabanında düz metin olarak saklanır.
her şifre karma şemasının en önemli yönü
hash bir yavaş kriptografik olarak güvenli sağlama işlevidir, bkz https: // güvenlik .stackexchange.com/a/31846/10727 daha fazla arka plan bilgisi için.
O zaman soru şudur: ygulama değerine sabit bir değer eklemenin neredeyse sıfır çabası olduğ ve uygulama kodunun genellikle değil SQL Injection Attack, aşağıdakiler yukarıdakilerden önemli ölçüde daha mı iyidir?
$hashed_password = hash( $pepper . $salt . $password )
burada
$salt veritabanında düz metin olarak saklanır ve
$pepper, uygulama kodunda (veya kod birden çok sunucuda kullanılıyorsa veya kaynak herkese açıksa yapılandırılırsa) düz metinde depolanan bir sabittir.
Bu
$pepper eklemek kolaydır - sadece kodunuzda bir sabit oluşturuyor, büyük bir kriptografik olarak güvenli rastgele değer giriyorsunuz (örneğin/dev/urandom hex veya base64 kodlu 32bayt) ve bu sabiti kullanıyorsunuz şifre karma fonksiyonunda. Mevcut kullanıcılarınız varsa, bir geçiş stratejisine ihtiyacınız vardır; örneğin, bir sonraki girişte şifreyi yeniden girin ve karma ile birlikte şifre karma stratejisinin sürüm numarasını saklayın.
$pepperdoes şifresini kullanarak karma değerini artırın if veritabanının güvenliğinin sağlanması ima etmez uygulamanın güvenliğinin ihlal edilmesi. Biber bilgisi olmadan şifreler tamamen güvende kalır. Parolaya özel tuz nedeniyle, veritabanındaki iki parolanın aynı olup olmadığını bile bulamazsınız.
Bunun nedeni,
hash($pepper . $salt . $password) 'nin anahtar olarak
$pepper ve girdi olarak
$salt.$password ile etkili bir sahte rasgele fonksiyon oluşturmasıdır (SHA * ile PBKDF2 gibi
hash adaylar için, bcrypt veya scrypt). Sahte bir rasgele fonksiyonun iki garantisi, gizli bir anahtarın altındaki çıkışı ve anahtarın bilgisi olmadan girişin çıktısını çıkaramamanızdır. Bu, karma işlevlerin tek yönlü özelliğine çok benziyor, ancak fark, parolalar gibi düşük entropi değerleriyle tüm olası değerleri etkili bir şekilde numaralandırabileceğiniz ve görüntüleri genel karma işlevi altında hesaplayabileceğiniz ve böylece resim ön resim ile eşleşir. Sözde rastgele bir işlevle, anahtar olmadan (yani biber olmadan) bunu yapamazsınız, çünkü anahtar olmadan tek bir değerin görüntüsünü bile hesaplayamazsınız.
Bu ayardaki
$salt öğesinin önemli rolü, veritabanına uzun süre erişebiliyorsanız ve normalde uygulama ile dışarıdan çalışabiliyorsanız devreye girer.
$salt olmadan kontrol ettiğiniz bir hesabın şifresini bilinen bir
$passwordKnown değerine ayarlayabilir ve karmayı bilinmeyen bir şifre
$passwordSecret ile karşılaştırabilirsiniz.
hash($pepper . $passwordKnown)==hash($pepper . $passwordSecret) olarak ve yalnızca
$passwordKnown==$passwordSecret ise, bilinmeyen bir parolayı seçilen herhangi bir değerle karşılaştırabilirsiniz (teknik olarak karma işlevinin çarpışma direncini varsayarım). Ancak tuzla,
$salt1 . $passwordKnown == $salt2 . $passwordSecret ve
$salt1 ve
$salt2 ve
$passwordKnown ve sırasıyla
$passwordSecret için rastgele seçilmişse
hash($pepper . $salt1 . $passwordKnown)==hash($pepper . $salt2 . $passwordSecret) elde edersiniz tuzlar asla aynı olmayacaktır (256bit gibi yeterince büyük rastgele değerler varsayarak) ve böylece şifreyi artık birbirinizle karşılaştıramazsınız.
(Not: bir tuz kullanmak işin sadece yarısıdır; ayrıca karma işlevini yavaşlatmanız gerekir - böylece tek bir düşük entropi parolasına saldırmak hala zordur. Yavaşlık genellikle birden çok yineleme veya birleştirme işlemiyle karma elde edilir. Tuz ve şifrenin 10000 kopyası.)
"Biber" inizin yaptığı, karmayı bir MAC biçimine dönüştürmesidir. Karma işlevinden iyi ve güvenli bir MAC yapmak kolay değildir, bu yüzden ev yapımı bir yapı (teorik olarak koyma yöntemi) yerine HMAC kullanmanız daha iyi olur çarpmaya dayanıklı bir karma işlevinin rastgele bir Oracle'dan ayırt edilemeyeceği anlamına gelir).
Bir MAC ile, şu anlamda bir miktar güvenlik kazanabilirsiniz: muhtemelen, saldırganın veritabanı okuma erişimi gerçek bir sorun olmaktan çıkabilir. MAC anahtarı ("biber") gizlilik ihtiyacını yoğunlaştırabilir . Bununla birlikte, bu, MAC'nin aynı zamanda, birçok MAC yapısından (HMAC dahil) alacağınız, ancak kriptografik olarak gerçekten garanti edilmeyen (incelikler var) bir özellik olan tek yönlü bir işlev olmasına dayanır.
"Biber", yeniden başlatmaya direnecek şekilde güvenli depolama da dahil olmak üzere yönetmeniz gereken bir anahtarınız olduğunu gösterir. Bir anahtar küçüktür ve RAM'e sığar, ancak depolama gereksinimleri nedeniyle, güvenliğini geliştirip geliştirmediği belirsizdir. Veritabanının tamamını okuyabilen bir saldırgan, genellikle herhangi bir "korumalı" dosya da dahil olmak üzere tüm sabit diski okuyabilir. Anahtarın küçük boyutu bazı gelişmiş kurulumlara izin verebilir, örn. anahtar, önyükleme sırasında kullanılan ancak daha sonra bağlı bırakılmayan akıllı kartlarda saklanır. Özetlemek gerekirse, biberin çabaya değip değmeyeceği bağlama bağlıdır - genel olarak, eklenen karmaşıklığı önlemek için buna karşı tavsiye ederim.
Bir biberin gerçekten neler yapabileceğini belirtmek isterim.
Diğerleri daha önce işaret ettiği gibi, saldırganın veritabanındaki karma değerlerine erişimi olduğu, ancak sunucu üzerinde hiçbir kontrolü olmadığı ve bu nedenle biberi bilmediği için) biber eklemek sadece bir avantajdır. Bu, muhtemelen daha sık kullanılan saldırılardan biri olan SQL enjeksiyonu için tipiktir, çünkü yapılması çok kolaydır.
$hashValue = bcrypt('12345', $cost, $salt);
Bu parola, yavaş bir anahtar türetme işlevi doğru kullansanız bile sözlük saldırısıyla kolayca alabilirsiniz. Bu zayıf parolalarla en çok kullanılan parolaları sözlüğe ve kaba kuvvete koyun. Şifreyi birçok durumda da bulmamız muhtemeldir.
$hashValue = bcrypt('12345anm8e3M-83*2cQ1mlZaU', $cost, $salt);
Biber ile zayıf şifre uzar, şimdi özel karakterler içerir ve daha da önemlisi, hiçbir sözlükte bulamazsınız. Biber gizli kaldığı sürece sözlük saldırılarını önler yapar, bu durumda zayıf şifreleri koruyabilir.
Düzenle:
Bir sunucu tarafı anahtarı eklemenin, biber olarak kullanmaktan daha iyi bir yolu vardır. Biberle saldırganın anahtarı alabilmesi için sunucuda ek ayrıcalıklar edinmesi gerekir. Aynı avantajı önce hash'ı hesaplayıp sonra hash'ı sunucu tarafı anahtarıyla (iki yönlü şifreleme) şifreleyerek elde ederiz. Bu bize gerekli olduğunda anahtarı değiştirme seçeneği sunar.
$hash = bcrypt($passwort, $salt); $encryptedHash = encrypt($hash, $serverSideKey);
Unix şifreleri için tuzlama ve iterasyonun icat edilmesiyle ilgili makale ( Password Security: A Case History, Morris & Thompson, 1978 ), bir biberin eşdeğerini de açıkladı:
Kullanıcının şifresinin ilk sekiz karakteri DES için bir anahtar olarak kullanılır; daha sonra algoritma bir sabiti şifrelemek için kullanılır. Bu sabit şu anda sıfır olmasına rağmen, kolayca erişilebilir ve kuruluma bağlı hale getirilebilir.
Yine de kullanıldığını duymadım. Başkası var mı?
Sadece bir BTW, yeni NIST Dijital Kimlik Yönergeleri (Taslak), Pepper'ı da kullanmanızı şiddetle tavsiye eder:
126.96.36.199 Ezberlenen Sırlar Doğrulayıcı:
... Anahtar, karma kimlik doğrulayıcılardan (ör., Bir donanım güvenlik modülünde) ayrı olarak depolanmış bir anahtarlı karma işlevi (örn. HMAC [FIPS198-1]), kayıtlı karma kimlik doğrulayıcılarına karşı sözlük saldırılarına daha fazla direnmek için KULLANILMALIDIR.
Şu senaryoyu inceleyin:
Ben bir şifre X karma ve tuz ile kullanıcıların bir listesini almak için bir SQL enjeksiyon kullanarak bir web sitesine X girmek üzereyim. Diyelim ki X web sitesi küresel bir biber kullanıyor.
Tek yapmam gereken, X web sitesinde bir kullanıcıyı SQL enjeksiyonundan önce bilinen bir kullanıcı adı ve parolayla kaydetmek olacaktır. Daha sonra veritabanındaki belirli bir kayıt için, parola karması, düz metin parolası, tuz (düz metin olarak depolanır) bilirim ve bu tek kayıt temelinde küresel biberi çatlatmak benim için önemsiz olurdu .
Yani, gerçekten bir biber, bir saldırganı önemsiz bir ek süre için yavaşlatmanın bir yolu olacaktır. Parola + tuz + karabiber, amaçlandığı gibi, sadece karabiber zorlamak zorunda kalmazlar.
Yukarıda seçilen düz metin saldırısı biçimidir. Saldırganlar algoritmayı (hash ()), çıktıyı ($ hashed_password) ve girdilerden biri ("sabitler" $ salt & $ şifre ve "değişken" $ biber) hariç hepsini bildiği sürece, x için çözebilirler "lineer cebir denklemi gibi (h = s + p + x == hsp = x), ama tabii ki kaba kuvvetle. Biberleri 56 bayttan (448 bit) daha uzun yapmak, bcrypt'in limiti, zaman maliyetini arttırır ve bcrypt kadar iyidir, ancak yine de scrypt kadar iyi olmayabilir. Böylece, biber yeterince uzun olduğu sürece, bir gelişmedir.
Bir sunucunun küresel biber sabitini nasıl gizleyebileceğine çok aşina değilim ama benim er ya da geç sunucuya nüfuz eden bir hacker biber değerini nasıl yakalayacağını anlayacaktır. Biber değerini tamamen güvenli hale getirmek için özel donanım gerekir. Bunu yapmanın bir yolu, sunucuda kurulu bir FPGA kartı kullanmaktır. FPGA, biber değerini içeren karma gerçekleştirmek için kullanılan kodu içerecek ve tüm karma hesaplamalar FPGA içinde gerçekleşecektir. FPGA ile programlama tek yönlü bir işlev olabilir. Biber programlanabilir, ancak geri okumak için gönderilebilecek bir talimat yoktur. Biber, kasada kilitli bir kağıt parçası üzerinde saklanır. Biber rastgele üretilen 128+ bit ise, bunu belirlemenin pratik bir yolu olmaz.
Sunucu donanım maliyetini artıracağından bunun ne kadar pratik olacağından emin değilim.