Kullanıcı Parola Güvenliği için Hashing ve Salting Kullanımı
Bu yazıda uygulamalarda kullanıcı kimlik denetiminin bir parçası olan parolaları veri tabanlarında nasıl güvenli bir şekilde tutabileceğimizi anlatmaya çalışacağım.
Bir web geliştiricisi iseniz, sitenizde muhtemelen kullanıcı kimlik denetim sistemi yapmışsınızdır. Buradaki önemli noktalardan biri kullanıcı bilgilerinin güvenliğidir. Sonuç olarak kullanıcı, sitenize giriş yaparak size güveniyor. Biz geliştiricilerin de en önemli görevlerinden biri kullanıcı bilgilerini dışarıdan gelen tüm saldırılara karşı korumaktır. Farklı saldırı teknikleri kullanılarak sistemimizdeki kullanıcı tablolarında yer alan bilgiler çalınabilir. Bu saldırılardaki ilk hedeflerden biri de parolalardır. Kullanıcıların da bu parolaları başka uygulamalarda da kullanabilme ihtimalini göz önüne alırsak parolaların güvenliği çok önemli bir konu haline geliyor (Bkz: Mark Zuckerberg’in sosyal medya hesaplarının hacklenmesi).
Parola güvenliği için en iyi yöntemlerden biri salting (tuzlama) yöntemidir. Bu yazıda bu yöntemi neden yapmamız gerektiğini anlatacağım.
Hashing nedir?
En kısa tanımla hashing farklı büyüklükteki girdileri bir hash fonksiyonu yardımı ile sabit büyüklükte çıktı üretilmesi sürecidir. Aşağıda üç farklı metin değerinin hashing işlemi sonucundaki çıktısını görebilirsiniz.
hashing("merhaba") = C39436EE452E641CDE2EB992AB397911 hashing("marhaba") = ECF853B448D836DB76DEBF2C342E0369 hashing("medium") = 075A3E36A0A52DCBC568C05788E8A713
Hash algoritmaları deterministiktir. Yani girdi değişmediği sürece her zaman aynı hash çıktısı alınır. Örneğin yukarıdaki “merhaba” değerini tekrar tekrar hashing işleminden geçirseniz dahi sonuç hep sağda gördüğünüz değer olacaktır. Hashing için en çok kullanılan iki algoritmadan SHA-256 hashing algoritması 256 bit çıktılar üretebilirken MD5 ise 128 bitlik çıktılar üretir. Hash algoritmaları tek yön çalışır. Yani bir hash değerini bilsek bile ondan hash’lenmemiş haline geri dönemeyiz. Ayrıca çıktılarda görüldüğü gibi en ufak bir harf değişikliğinde bile hashlenmiş çıktı tamamen değişmektedir.
Kullanıcının sisteme üyeliği ve kimlik doğrulamasının genel akışı aşağıdaki gibidir;
- Kullanıcı hesap oluşturur.
- Parolası hashlenir ve veri tabanına kaydedilir. Bu kısımda parolaları asla düz metin olarak kaydedilmemesi gerekir.
- Kullanıcı sisteme giriş yapmaya çalıştığında girdiği parola hash’i veri tabanındaki hash ile karşılaştırılır.
- Hash’ler uyuyor ise kullanıcıya sisteme giriş yetkisi verilir.
Burada önemli bir nokta da 4. maddede eğer hash’ler uymuyor ise kullanıcıya verilen mesaj “Kullanıcı adı veya parola yanlıştır” olmalıdır. Bu da saldırganın sadece parolanın değil kullanıcı adının da yanlış olabileceği izlenimine kapılmasını sağlar.
Parolaları hash’leyip veri tabanında saklamanın güvenli olduğunu düşünebilirsiniz. Saldırganların işini biraz zorlaştırsa da yanlış bir düşüncedir. Şimdi bu parolaları kırmak için saldırı yöntemlerinden bahsedelim.
Dictionary ve Brute Force Saldırıları
Bir hash’i kırmanın en kolay yolu, parolayı tahmin edip her tahminde hash yapıp ve o hash’i var olan hash ile eşit olup olmadığını kontrol etmektir. Hash’ler eşit ise parola bulunur. Bu yönetimi uygulayıp parolaları tahmin etmenin en yaygın iki saldırı biçimi dictionary ve brute force saldırılarıdır.
Dictionary saldırıları, içerisinde yaygın kullanılan basit/karmaşık parolalar, isim, soy isim, telefon numaraları vb. bilgileri içeren bir dosyayı kullanır. Her bir parola hash’lenir ve mevcut parola ile kontrol edilir.
Brute Force saldırıları, parolaları deneme-yanılma yoluyla bulma yöntemidir. Belirli uzunluğa kadar olası tüm karakter kombinasyonlarını dener. Bu yöntem ile güvenlik unsurlarını içeren karmaşık kombinasyonlara sahip şifreler kırılıyor. Bu saldırıdan korunmak için paroları daha uzun tutmak, alfanümerik kombinasyonlar, iki faktörlü kimlik doğrulama ve CAPTCHA gibi önlemler alınabilir.
Rainbow Tabloları
Dictionary saldırılarına çok benzerdir. Olası parolaların daha önceden hazırlanmış hash değerleri ile birlikte barındıran tablolardır. Bu sayede sistem parola için hash değeri hesaplaması yapmaz ve doğrudan hash’leri kontrol ederek parolaya erişebilir.
Bu saldırılarla parolaların hash değerlerinden nasıl dönüldüğünü öğrenmiş olduk. Problemin asıl kaynağı kullanıcıların yeterli uzunlukta ve karmaşıklıkta olmayan parolaları tercih etmesidir. Bu durumu önlemek ve bu saldırılardan korunmak için parolaların veri tabanında saklanmadan önce tuzlanması (salt) gerekmektedir.
Salt (Tuzlama)
Bu yöntemde parolaları hash’lemeden önce salt (tuz) adı verilen rastgele bir metin parolanın başına ya da sonuna ekleyerek bu değerin hash’lenmesinin sağlanmasıdır. Aşağıda aynı metnin yalın ve iki farklı salt değeri ile hashlenmesinin sonucunu görebilirsiniz.
hashing("merhaba") = C39436EE452E641CDE2EB992AB397911 hashing("merhaba" + "e$7H3$YVYJpeyjAO") = A89A880CF2CB460B689DDF6F2F09EF5C hashing("merhaba" + "2!yt*hrBwoK4Avvh") = 82A2A1BA55B1538C22E3D133D4DFB5FC
Bu sayede aynı parolayı seçmiş kullanıcıların parolalarının hash’leri her seferinde tamamen farklı bir metine dönüştürülür. Parolaların doğruluğunu kontrol etmek için aynı şekilde şifrelerken kullandığımız tuza (salt) ihtiyacımız vardır. Dolayısıyla veri tabanında kullanıcı bilgileriyle birlikte bu tuz (salt) değeri de saklanır.
Bu yapılan yöntem ile şifrenin uzunluğu ve karmaşıklığı artmış olur. Tuz (salt) değeri bulunsa bile her kullanıcı için ayrı bir rainbow tablosu üretilmesi gerekir ve bir seferde tek bir kullanıcının şifresi sorgulanabilir. Saldırılardan korunmak için tuz (salt) değerinin her kullanıcıda farklı olması ve hashlenip saklanması önerilir. Kısa tuz (salt) değerlerinin kullanılması saldırganlar tarafından tuz (salt) değerinin tahmin edilmesini kolaylaştırır. Kullanıcı adının tuz (salt) değeri olarak kullanmaması gerekir. Tuz (salt) değerlerini oluşturmak için kriptografik hash algoritmaları kullanılmalıdır. Bu algoritmalar tuz (salt) değerinin tahmin edilmesini zorlaştırır. Çeşitli programlama dillerinde bu değerleri üreten nesneler vardır. Örneğin;
Php -> mcrypt_create_iv, openssl_random_pseudo_bytes
Java ->java.security.SecureRandom
.NET -> System.Security.Cryptography.RNGCryptoServiceProvider
Ruby -> SecureRandom
Python -> os.urandom
Yanlış yapılan başka bir çözüm ise hash algoritmalarını iç içe kullanıp iterasyonla kompleksliği arttırıldığının sanılmasıdır. Eğer kullanılan hash algoritması zayıf ise bu yöntem de zayıf olacaktır. Zayıf parolaların iterasyonları rainbow tabloları ile kolayca çözülebilir. Kendi kriptografik algoritmanızı üretmeye çalışmayın. Bunlar zaten uzman kişiler tarafından yazıldı ve test edildi. Doğru olan bunları kullanmak. İç içe hash fonksiyonları kullanılarak üretilen değerler parolaların kırılmasını yavaşlatır fakat tam bir çözüm olmaz.
Zayıf Hash Algoritmaları
Yukarıda bahsettiğimiz zayıf hash algoritmalarına örnek olarak MD5, SHA-1 vs algoritmaları örnek verebiliriz. Bu algoritmalar birçok nedenden dolayı zayıf sayılmaktadır. Hesaplama süreleri çok hızlıdır ve sonucunu bulabileceğiniz çok sayıda rainbow tabloları mevcuttur. Bunlar yerine uygulamanın tipine göre SHA-256, SHA512, RipeMD, bcrypt veya PBKDF2 gibi algoritmalar kullanılmalıdır.
PBKDF2 ve bcrypt gibi algoritmaların hem tuzlama hem de iterasyon gibi güvenliği arttıracak özellikleri vardır. Tabii ki bunların da dezavantajları vardır. MD5 gibi algoritmalara göre yavaştır ve daha fazla CPU kaynağı tüketir. Bu durumda da sisteme yapılacak bir Brute-Force saldırısıyla sistem servis dışı kalabilir.
Özetlemek gerekirse;
- Zayıf hash algoritmaları yerine daha güçlü algoritmalar kullanılmalı.
- İterasyon sayısı sistemi bozmayacak şekilde yüksek tutulmalı.
- Kullanıcılar daha uzun ve kompleks bir şifre kullanmaya zorlanmalı.
- Her bir kullanıcı için ayrı bir tuz değeri oluşturulup farklı bir tablo veya veri tabanında saklanmalı. Her parola değişikliğinde de bu tuz değeri değiştirilmelidir.
Sonuç
Bu yazıda bahsedilen yöntemlerin dışında daha başka ve güvenli yöntemler de var. Sistem güvenliği sadece şifre güvenliği ile bitmiyor. Web uygulamalarındaki güvenlik açıklarını öğrenmek için OWASP sitesini ziyaret etmenizi öneririm. En iyi geliştiriciler bile hata yapabilir. Dolayısıyla alınan önlemleri üst düzeyde tuttuktan sonra sistemi penetrasyon testine sokmak ve güvenlik uzmanlarından destek almak gerekebilir.