Selam millet, BlueTornado yazıyor.
Veri sızıntılarında en acı senaryolardan biri, kullanıcı parolalarının düz metin veya hızlı hash ile saklanmış olmasıdır. Bu rehberde salt'ın rolünü, neden düz SHA-256 yetmediğini, bcrypt ve Argon2id kullanımını ve OWASP önerilerini lab örnekleriyle anlatıyoruz. Hashcat konusu ayrıca işlendiği için burada kırma değil, doğru saklama odaklıyız.
Konuda Anlatılacaklar
- Parola saklama tehdit modeli
- Salt, pepper, yavaşlık (key stretching)
- bcrypt kullanımı
- Argon2id (tercih edilen modern seçim)
- Migrasyon ve doğrulama akışı
- İleri seviye: parametre seçimi, MFA, passkey
- Kaynakça ve yasal uyarı
1) Tehdit Modeli
Saldırgan veritabanı yedeğinizi ele geçirdiğinde ne olur?
- Düz metin: tüm hesaplar anında açılır; parola reuse ile başka siteler risk altında
- Hızlı hash (MD5/SHA-1/SHA-256, tuzsuz): GPU ile toplu kırma pratik
- Yavaş KDF + unique salt: her parola için maliyetli deneme; iyi parolalar korunur
Alıntı:Hash'lemek "şifrelemek" değildir. Parolayı geri çözmeniz gerekmez; her girişte aynı KDF ile doğrularsınız.
OWASP Password Storage Cheat Sheet, modern uygulamalar için Argon2id'yi tercih edilen seçenek olarak listeler; bcrypt kabul edilebilir bir alternatiftir.
2) Salt ve Pepper
Salt: Her kullanıcı/parola için benzersiz rastgele değer. Aynı parola farklı hash üretir; rainbow table etkisizleşir. Salt gizlidir sanılmamalı; hash ile birlikte DB'de tutulur.
Pepper: Uygulama/sunucu tarafında tutulan ek gizli değer (KMS veya config). DB sızsa bile pepper olmadan doğrulama zorlaşır. Pepper'ı git'e yazmayın.
# Kavramsal
stored = argon2id(password, salt, params, pepper?)
# Doğrulama: aynı params ile verify[center][/center]
3) bcrypt Lab
pip install bcrypt
python3 - <<'PY'
import bcrypt
password = b"LabParola!2026"
hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
print(hashed)
print(bcrypt.checkpw(password, hashed))
print(bcrypt.checkpw(b"yanlis", hashed))
PY# Çıktı örneği (her seferinde farklı salt -> farklı string)
# $2b$12$...Dikkat: bcrypt bazı uygulamalarda 72 byte sınırına sahiptir; çok uzun parolalarda önce SHA-256 sonra bcrypt gibi sarmalamalar tartışılır — kütüphane dokümantasyonunu okuyun. Mümkünse Argon2id tercih edin.
4) Argon2id Lab
Argon2, Password Hashing Competition kazananıdır. Argon2id, side-channel ve GPU saldırılarına karşı dengeli bir varyanttır.
pip install argon2-cffi
python3 - <<'PY'
from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError
ph = PasswordHasher(
time_cost=3,
memory_cost=65536, # KiB cinsinden; donanımınıza göre ayarlayın
parallelism=2,
)
h = ph.hash("LabParola!2026")
print(h)
print(ph.verify(h, "LabParola!2026"))
try:
ph.verify(h, "yanlis")
except VerifyMismatchError:
print("mismatch ok")
print("needs_rehash", ph.check_needs_rehash(h))
PY[center][/center]
Parametreleri seçerken: giriş başına CPU/RAM maliyeti kabul edilebilir olmalı; brute-force ise pahalı olmalı. OWASP cheat sheet güncel parametre önerilerini kontrol edin (donanım yıllarına göre değişebilir).
5) Uygulama Akışı
# Kayıt
hash = ph.hash(password)
db.save(user, password_hash=hash)
# Giriş
if ph.verify(user.password_hash, password):
if ph.check_needs_rehash(user.password_hash):
user.password_hash = ph.hash(password)
db.save(user)
login_success()
else:
login_fail() # sabit zamanlı mesaj; kullanıcı var/yok sızdırmayın# YANLIŞ
hashlib.sha256(password.encode()).hexdigest()
# YANLIŞ
base64.b64encode(password.encode())
# YANLIŞ
AES_encrypt(password, server_key) # parola saklama için KDF tercih edilirMigrasyon: Eski SHA-256 kullanıcıları giriş yaptığında yeni Argon2id'ye yükseltin (transparent rehash). Toplu "hepsini bir gecede dönüştür" için eski hash'leri bilemiyorsanız kullanıcı parola sıfırlama gerekebilir.
6) Ek Kontroller
- Kayıt/şifre değişiminde uzunluk ve breached password kontrolü (Have I Been Pwned Pwned Passwords API, k-anonymity)
- Rate limit + MFA
- Password reset token'ları tek kullanımlık ve kısa ömürlü
- Loglarda parola ve hash yazmayın
- Yedekleri şifreleyin; DB erişimini least privilege yapın
# Pwned Passwords k-anonymity fikri (kavramsal)
# SHA-1(parola)'nın ilk 5 karakterini API'ye gönder, sonek listesinde ara
# Parolanın tamamını göndermeyin[center][/center]
7) İleri Seviye
Passkey / WebAuthn: Parola yerine phishing-resistant kimlik doğrulama. Parola yükünü azaltır.
Composition policy: NIST SP 800-63B, karmaşık zorunlu karakter setlerinden ziyade uzunluk + blacklist (yaygın/parola sızıntısı) vurgular. Kurum politikanızı güncel rehberlerle hizalayın.
HSM / KMS pepper: Pepper'ı uygulama belleğinden ayrı tutmak ihlal etkisini azaltır.
# Rapor / mimari not dili
Parola saklama: Argon2id (argon2-cffi), time_cost=3, memory_cost=65536, parallelism=2
Salt: kütüphane tarafından unique
Pepper: yok/var (KMS)
Migrasyon: SHA-256 -> Argon2id on-login8) Sonuç
Parolaları Base64 veya düz SHA ile saklamayın. Unique salt + Argon2id (veya bcrypt) + dengeli parametreler + MFA temel pakettir. Sızıntı olsa bile iyi parolaların toplu kırılmasını zorlaştırmak hedeflenir.
Ek: Operasyonel Senaryolar
Sızıntı sonrası: Tüm oturumları iptal edin, kullanıcıları bilgilendirin (KVKK süreçleri), zorla parola yenileme veya "girişte rehash + MFA zorunlu" uygulayın. Hash algoritmanız zayıfsa aciliyet artar.
Eski mobil uygulama: Eski istemci hâlâ SHA-1 hash gönderiyorsa sunucu tarafında kabul etmeyin; protokolü yükseltin.
# Doğrulama maliyeti ölçümü (lab)
python3 - <<'PY'
import time
from argon2 import PasswordHasher
ph = PasswordHasher(time_cost=3, memory_cost=65536, parallelism=2)
t0=time.time(); ph.hash("x"*12); print("hash_s", round(time.time()-t0,3))
PYHedef: meşru girişte yüzlerce ms kabul edilebilir; kitle brute-force'ta ise pahalı. Aşırı yüksek maliyet DoS'a dönüşebilir; login rate limit ile birlikte düşünün.
[center][/center]
Unutmayın: Teknik KDF doğru olsa bile kullanıcı "123456" seçerse risk devam eder; breached password engeli ve passkey geçişi tamamlayıcıdır.
Ek Lab Komutları
# bcrypt maliyeti karşılaştırması
python3 - <<'PY'
import bcrypt, time
for r in (10, 12, 14):
t=time.time(); bcrypt.hashpw(b"x", bcrypt.gensalt(r)); print(r, round(time.time()-t,3),"s")
PY# Argon2 parametre dizesini okuma
python3 - <<'PY'
from argon2 import PasswordHasher
h=PasswordHasher().hash("demo")
print(h.split("$")[:5])
PY# Secrets ile salt üretimi (elle saklama senaryosu - genelde kütüphane yapar)
python3 -c "import secrets; print(secrets.token_bytes(16).hex())"Kaynakça
- OWASP Password Storage Cheat Sheet
- Argon2 resmi depo
- NIST SP 800-63B
- Have I Been Pwned - Pwned Passwords API
- argon2-cffi dokümantasyonu
- OWASP A02 Cryptographic Failures
Yasal Uyarı
Bu içerik savunma ve güvenli yazılım geliştirme içindir. Başkalarına ait parola hash'lerini izinsiz kırmaya çalışmak veya sistemlere yetkisiz girmek TCK 243-245 kapsamında suç olabilir. Lab parolalarını üretimde kullanmayın; sorumluluk uygulayana aittir.
Yasal uyarı: Bu içerik eğitim amaçlıdır. Yalnızca kendi sistemlerinizde veya yazılı izin aldığınız hedeflerde uygulayın (TCK 243-245).