Aradığınız içerik sitemizde mevcut durumdadır
buradan sitemize dönebilirsiniz !
Forum Başlıklarına gitmek için tıklayınız
Şifre Karıştırma (Password Hashing)
| Kod Alanı: |
James McGlinn tarafından www.phpsec.org'ta yazılan yazı
|
Bu yazıda yeni web geliştiricileri tarafından çoğunlukla göz ardı edilen şifre karıştırma konusu ele alınacaktır. Son zamanlarda incelediğim bazı yazılımlarda kullanıcı şifrelerinin düz metin olarak veritabanında tutulduğunu gördüm (Türkiye'de de durum pek farklı değil). Bu ciddi bir güvenlik açığıdır. Şifre karıştırma kullanıcı şifrelerini gizlemek için bir yoldur. Karıştırılmış şifrelerin bulunduğu veritabanı başkalarının eline geçse bile şifrelerin elde edilmesi imkansız denebilir. Şifre karıştırma yeni bir kavram değildir. Aksine uzun zamandır birçok sistemde kullanılmaktadır. Örnek olarak UNİX sistemlerde kullanıcı şifrelerinin tutulduğu dosyalarda kullanılmaktadır. Bu yazıda şifre karıştırmanın ne olduğu, neden kullanılması gerektiği konularından bahsedilecek ve PHP ve MYSQL kullanarak bazı örnekler verilecektir.
Giriş
Yazıda örneklerde SHA-1 (Secure Hashing Algorithm - Güvenli Karıştırma Algoritması) kullanılmıştır. Bu yazıyı yazdıktan sonra bir grup araştırmacı (Xiaoyun Wang, Yiqun Lisa Yin, and Hongbo Yu) SHA-1 'in düşünüldüğü kadar güçlü bir algoritma olmadığını gösterdiler. Çok üst seviyede güvenlik isteyen uygulamalarda (dijital imzalama gibi) SHA-256 ve SHA-512 kullanılması tavsiye ediliyor. Yazının konusu olan kullanıcı şifreleri karıştırma işlemi için SHA-1'in yeterli güvenliği sağlayacağını düşünüyorum. Ama siz kişisel olarak yazılım geliştirirken başka algoritmaları da kullanabilirsiniz.
Bu konuda daha fazla bilgi için Bruce Schneier'ın yazdığı makaleye bakabilirsiniz.
http://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html
(Makale ingilizcedir.)
Metin karıştırma (Hash) nedir?
Hash (Hash code, mesaj digest) bir verinin kendisine özel parmak izi olarak düşünülebilir. Bir metinden tek taraflı (geri dönüşümsüz) matematik algoritmaları (SHA-1, MD5 gibi) kullanılarak belli uzunlukta karışık metin (hash) elde edilebilir. Bu karışık metinleri asıl metinlere geri dönüştürmek imkansıza yakındır. Ayrıca iki farklı metnin aynı karışık metine sahip olması da imkansızdır. Bu özellikleri karışık metinleri şifre kaydetmek için güvenli bir yol haline getiriyor. Karışık metin haline getirdiğiniz şifreleri veritabanında veya dosya halinde tuttuğunuzu düşünelim. Dosyanın veya veritabanının başka kişilerin eline geçmesi durumunda karışık metinleri kullanarak şifrelerinizi geri dönüştüremeyeceklerinden şifreleriniz yine güvendedir.
Peki Sisteme giren Kullanıcıların Şifreyi Doğru Girdiğini Nasıl Anlayacağım?
Karışık metinlerden geri dönüşüm yapılamadığını belirttik. Peki kullanıcılar giriş yaparken şifrelerini girdiklerinde doğru olduğunu nasıl anlayacağız. Kullanıcıların girdiği şifrelerin aynı yöntemle karışık metinlerini oluşturup ve veritabanında yada dosyada kaydedilmiş olan kullanıcının şifresinin karışık metniyle karşılaştırarak kullanıcının doğru şifreyi girip girmediği kontrol edilir. Aşağıdaki örnek şifre karıştırmaya ve kullanıcı girişine örnektir.
Kullanıcı Kayıt ve Şifre Kontrolü
Kullanıcı kaydı yapılırken basitçe aşağıdaki formdaki gibi kullanıcıdan kullanıcı adı ve şifre (onaylamak için iki defa) alınır.
Şekil 1. Kullanıcı kayıt formu
Kullanıcıyı aşağıdaki kodları kullanarak şifresini karıştırıp sisteme kaydedilir.
<?php
/* Kullanıcı kayıt */
// Şifre karıştırılıyor SHA1 kullanılıyor
$passwordHash = sha1($_POST['password']);
$sql = 'INSERT INTO user (username,passwordHash) VALUES (?,?)';
$result = $db->query($sql, array($_POST['username'], $passwordHash));
?>
Kullanıcı giriş yaparken kullanıcı adını ve şifreyi girer.
Şekil 2. Kullanıcı giriş formu
<?php
/* Kullanıcı girişi kontrol ediliyor */
// şifre karıştırılıyor
$passwordHash = sha1($_POST['password']);
$sql = 'SELECT username FROM user WHERE username = ? AND passwordHash = ?';
$result = $db->query($sql, array($_POST['username'], $passwordHash));
if ($result->numRows() < 1)
{
/* Kullanıcı adı yada şifre yanlış */
echo 'Kullanıcı adı yada şifre yanlış !';
}
else
{
/* Giriş başarılı */
printf('Hoş geldin %s!', $_POST['username']);
}
?>
Karıştırma Türleri
Birçok metin karıştırma algoritması (MD5 ve SHA-1 en çok kullanılanlarıdır) vardır. Örneğin eski sistemlerde (Birçok Linux türevinde) çok güvenli kabul edilmeyen 56 bit DES (Data Encryption Standard) karıştırma yöntemi kullanılmaktadır.
Örnekler
PHP'de md5()ve sha1() fonksiyonlarını kullanarak karışık metin oluşturulabilir. md5() 128 bit (32 karakter uzunluğunda onaltılı sayı) sha1() ise 160 bit (40 karakter uzunluğunda onaltılı sayı) oluşturur.
<?php
$string = 'PHP & Information Security';
printf("Gerçek metin: %s\n", $string);
printf("MD5 ile karıştırılmış hali: %s\n", md5($string));
printf("SHA-1 ile karıştıılmış hali: %s\n", sha1($string));
?>
Bu PHP kodu aşağıdaki çıktıyı oluşturur.
Gerçek metin: PHP & Information Security
MD5 ile karıştırılmış hali: 88dd8f282721af2c704e238e7f338c41
SHA-1 ile karıştırılmış hali: b47210605096b9aa0129f88695e229ce309dd362
MySQL password(), md5() yada sha1() fonksiyonlarını kullanarak bu işlemi yapabilirsiniz. password() fonksiyonu MySQL'in kendi kullanıcı giriş işlemlerinde kullandığı fonksiyondur. 4.1 sürümünden önce 16 byte 4.1 ve sonraki sürümlerde ise 41 byte karışık metinler oluşturur. md5() 3.23.2 sürümünden sonra sha1() ise 4.0.2 sürümünden sonra eklenmiştir.
mysql> select PASSWORD( 'PHP & Information Security' );
+------------------------------------------+
| PASSWORD( 'PHP & Information Security' ) |
+------------------------------------------+
| 379693e271cd3bd6 |
+------------------------------------------+
1 row in set (0.00 sec)
mysql> select MD5( 'PHP & Information Security' );
+-------------------------------------+
| MD5( 'PHP & Information Security' ) |
+-------------------------------------+
| 88dd8f282721af2c704e238e7f338c41 |
+-------------------------------------+
1 row in set (0.01 sec)
Not : Algoritma zamanla değişmiş olması ve MySQL 4.1 sürümlerinden önce kullanılan algoritmanın kısmen zayıf olması yüzünden password() fonksiyonunu kullanmak tavsiye edilmiyor.
Şifre karıştırma işlemi MySQL de yapıldığında yukarıdaki kullanıcı kayıt örneği için kayıt kodu aşağıdaki gibi olmalıdır.
<?php
/* Kullanıcı kayıt */
$sql = 'INSERT INTO user (username, passwordHash) VALUES (?, SHA1(?))';
$result = $db->query($sql, array($_POST['username'], $_POST['password']));
?>
Zayıflıklar
Genel olarak ve bu yazıda şimdiya kadar anlatılanlara göre şifreler karıştırılıp tutulduğunda saldırganları işini zorlaştığı kesindir. Bir saldırgan kullanıcı veritabanını ele geçirdiği zaman şifreleri geri dönüştürmesinin imkansız olduğu düşünülür. Acaba bu gerçekten doğru mu?.
Saldırgan kullanıcı veritabanını ele geçirdiğinde şifreleri elde edebilmek için yapacağı ilk iş kaba kuvvet ile yani belli olasılıkları deneyerek şifreleri bulmaya çalışmaktır. Örneğin olması muhtemel şifreleri karıştırıp (sözlük saldırısı (dictionary attack) ile şifreler üreterek) denenir.
Gelişen bilgisayarlar donanımları MD5() ve SHA-1 gibi algoritmaları çok hızlı (saniyede binlerce) çalıştırabilecek özelliktedir. Sözlükteki kelimeler sayılarla değişik kombinasyonlarla denenip (dictionary attack) karıştırılmış halleri kullanıcı veritabanıyla karşılaştırılabilir. Günümüz teknolojisiyle kolay şifreleri (kullanıcıların genelin yaptığı basit anlamlı kelimelerden oluşan şifreler) bu yöntemle çözmek düşünüldüğü kadar uzun vakit almayabilir. Uzun şifreler yada karışık şifreler (Whilst strong) için bu geçerli değildir ama bütün kullanıcıları bu hassasiyet ve yeterlilikte olmadıkları gerçeği göz ardı edilmemelidir.Ayrıca birden fazla hesabın aynı şifreye sahip olması da saldırganın işin kolaylaştırır.
Biraz Daha Zorlaştıralım
Yukarıda bahsedilen zayıflıklar karıştırma işlemine bir ekleme yaparak kapatılabilir. Şifreyi karıştırmadan önce belli uzunlukta rasgele kelime (salt) oluşturup şifreye ekleyip karıştırma işlemi yapılır. Burada oluşturulan kelimenin (salt) yeterince uzun ve yeterince karışık olmasına da dikkat edilmelidir. Bu kelimeyi oluşturup şifre karıştırmayı bu kelime ile birlikte yaptıktan sonra geriye bu kelimeyi veritabanına kaydetmek kalıyor. Bu da kelimeyi (salt) karışık metnin önüne eklenip kaydedilerek yapılır. Bu durumda sadece veritabanındaki alanın boyutunu biraz artırmak yeterli olacaktır. Böylece her kullanıcı için ayrı kelime (salt) oluşacağından ve şifre basit olsa da karışık bir kelime (salt) ile birleştirip karıştırılacağından kaba kuvvetle (brute force) çözülmesi daha zor hale gelmiştir.
Kullanıcıyı kontrolü yaparken veritabanında kayıtlı olan ve karışık metne eklenmiş belli uzunluktaki salt alınıp kullanıcın girdiği şifreyle aynı yöntem karıştırılarak kontrol edilir. Bu karıştırma işlemi için aşağıdaki fonksiyon kullanılabilir.
<?php
// salt uzunluğu
define('SALT_LENGTH', 9);
function generateHash($plainText, $salt = null)
{
if ($salt === null)
{
// salt boşsa yeni salt oluşturuluyor
$salt = substr(md5(uniqid(rand(), true)), 0, SALT_LENGTH);
}
else
{
// salt gönderilmişse veritabanından alınan karışım verilmiştir
// başlangıçtaki belli uzunluktaki salt alınıyor
$salt = substr($salt, 0, SALT_LENGTH);
}
// salt kullanılarak metin karıştırılıyor ve salt karışımın başına ekleniyor
return $salt . sha1($salt . $plainText);
}
?>
Not : Fonksiyonda 'salt' kelimesinin uzunluğu 32 karakterle sınırlıdır. Kendi fonksiyonlarınızı yazarak bu değeri artırabilirsinz.
generateHash() fonksiyonu tek parametreyle çağırıldığında ($palinText karıştırılacak metin ile ) salt oluşturulur ve metin salt ile birlikte karıştırır. Salt karıştırılmış metnin başına eklenerek sonuç dönülür. generateHash() fonksiyonu kullanıcı kaydını yaparken tek parametre ile çağırarak kullanılmalıdır.
Kullanıcı şifresi kontrol edilirken generateHash() fonksiyonu iki parametreyle çağırılmalıdır. Birinci parametre kullanıcının şifresi ($plainText), ikinci parametre ($salt) ise veritabanında kullanıcıya ait olan karıştırılmış metindir. Bu durumda fonksiyon ikinci parametreden gerçek 'salt' kelimesini ayırır ve aynı yöntemle bu 'salt' kelimesini ve kullanıcı şifresini kullanarak karıştırılmış metin oluşturur. Bu metinle veritabanındaki kullanıcıya ait karışımı karşılaştırarak kullanıcı şifresi kontrol edilir.
Salt kullanmak farklı kişilerin aynı şifreye sahip olduğunda aynı karışık metnin oluşması durumunu ortadan kaldırır. Ayrıca sözlük saldırısı (dictionary attack) ile şifreleri çözmek daha zor hale gelir. Saldırganın hem salt yönteminin kullanıldığını hem de salt uzunluğunu göz önünde bulundurması gerekmektedir.
Sonuç
Yazı metin karıştırma yönteminin ne olduğu ve neden kullanılması gerekti konusunda idi. Verilen örnekler başlangıç olarak düşünülmeli ve üzerinde çalışılarak daha gelişmiş güvenli yöntemler bulunabileceği unutulmamalıdır.
Hosting Sponsorumuz - Noktahost internet hizmetleri