HG PHP GüvenliğiEl Kitabı
Bölümler 13 / 38

İçindekiler/Kimlik, Yetki ve Oturum

Bölüm 13

Password Security & Cryptography

14 dk okuma2.851 kelimePHP 8.1+
Ön koşul

Bölüm 1 (hashequals, randombytes), Bölüm 12 (kimlik doğrulama süreci).

Bu bölümün kazanımı

Kodlama, şifreleme ve hash'leme arasındaki hayati farkı; parolaların neden şifrelenmemesi, hash'lenmesi gerektiğini; tuz (salt), pepper, yavaş/bellek-zor hash'lerin (bcrypt/Argon2) rolünü; ve modern PHP'de kriptografiyi (password, libsodium) doğru kullanmayı öğreneceksiniz. Kendi kriptonuzu yazmamanın neden bir kural olduğunu göreceksiniz.

1. Giriş

Kriptografi, güvenlikte hem en güçlü hem de en kolay yanlış uygulanan araçtır. Doğru kullanıldığında matematiksel garantiler sunar; yanlış kullanıldığında yanlış bir güvenlik hissi verir — ki bu, hiç kullanmamaktan daha tehlikelidir. Tarihin en büyük veri ihlallerinin çoğu, şifreleme kullanılmadığı için değil, yanlış kullanıldığı için felakete dönüşmüştür. Adobe'nin 2013'teki 153 milyon hesaplık ihlali (Bölüm 11) bunun ders kitabı örneğidir: Adobe parolaları koruyordu — ama yanlış yöntemle.

Bu bölümün merkezî mesajı iki kuralda özetlenir. Birinci kural: parolaları şifreleme, hash'le. Şifreleme geri döndürülebilirdir; parolanın asla geri döndürülememesi gerekir. İkinci kural: kendi kriptonu yazma. Kriptografi, sezgiye aykırı ayrıntılarla doludur; "işe yarıyor gibi görünen" bir çözüm, uzman gözünde delik doludur. Modern PHP, bu iki kuralı kolaylaştıran yüksek seviyeli API'ler (password_hash, libsodium) sunar; doğru araç, karmaşık olanı basit ve güvenli kılar.


2. Temel Teori

Üç kavramı asla karıştırma:

Kavram Yön Anahtar? Amaç Örnek
Kodlama (encoding) Geri döndürülebilir Hayır Temsil/taşıma Base64, URL-encode
Şifreleme (encryption) Geri döndürülebilir Evet Gizlilik (geri alınabilir) AES, ChaCha20
Hash'leme (hashing) Tek yönlü Hayır Bütünlük/parola saklama bcrypt, SHA-256, Argon2

Base64 bir güvenlik önlemi değildir — sadece bir temsildir; herkes çözebilir. Şifreleme geri alınabilir, dolayısıyla anahtarı olan (ya da ele geçiren) düz metni elde eder. Hash tek yönlüdür: çıktıdan girdiye pratik bir dönüş yoktur. Parola saklama bir tek-yönlü problem olduğundan (parolayı geri almanız asla gerekmez, yalnızca doğrulamanız gerekir), doğru araç hash'lemedir — şifreleme değil. Adobe'nin ölümcül hatası tam buydu.

Parola hash'leme neden özel bir hash gerektirir? SHA-256 gibi genel hash'ler hızlıdır — bu, bütünlük için iyi ama parola için felakettir. Modern bir GPU, saniyede milyarlarca SHA-256 hash'i deneyebilir; bir parola sızarsa hızla kırılır. Parola hash'leme, bilinçli olarak yavaş ve/veya bellek-zor algoritmalar gerektirir: bcrypt, scrypt, Argon2. Bunlar, her denemeyi pahalılaştırarak kaba kuvveti ekonomik olarak imkânsız kılar.

Tuz (salt) — neden zorunlu? Tuz, her parolaya eklenen rastgele bir değerdir. İki amacı vardır: 1. Rainbow table'ları etkisiz kılar. Önceden hesaplanmış hash tablolarıyla eşleştirme, her parola benzersiz tuz taşıdığında işe yaramaz. 2. Aynı parolaların aynı hash üretmesini engeller. İki kullanıcı 123456 seçse bile, farklı tuzlar farklı hash'ler üretir. (Adobe'nin ECB modu tam bunun tersini yaptı: aynı parola → aynı şifreli metin.)

Pepper — opsiyonel ek katman. Pepper, tuzdan farklı olarak tüm parolalara uygulanan ve DB dışında (uygulama sırrı olarak, Bölüm 25) saklanan gizli bir değerdir. DB sızsa ama pepper sızmasa, hash'ler kırılamaz. Tuzun yerini almaz, üstüne eklenir.

Şifreleme gerektiğinde — mod önemlidir. Parola dışında, geri alınması gereken veriler (ör. saklanan API anahtarları) şifrelenir. Burada mod kritiktir: ECB modu kalıpları sızdırır (aynı blok → aynı şifreli blok; ünlü "ECB penguen" görseli bunu gösterir). Doğru seçim kimlik doğrulamalı şifreleme (authenticated encryption): AES-GCM veya libsodium'un XChaCha20-Poly1305'i. Bunlar hem gizlilik hem bütünlük sağlar (kurcalamayı yakalar).


3. Mimarisel Bakış

 PAROLA SAKLAMA (tek yönlü — HASH):
   Kayıt:  parola  →  password_hash(bcrypt/argon2, +otomatik salt)  →  DB
   Giriş:  parola  →  password_verify(girdi, saklanan_hash)  →  true/false
        ↑ geri dönüş YOK; DB sızsa bile parola kırılması pahalı

 VERİ ŞİFRELEME (geri alınabilir — ENCRYPTION):
   Yaz:  düz metin + anahtar + rastgele nonce  →  AES-GCM / secretbox  →  şifreli+etiket
   Oku:  şifreli+etiket + anahtar + nonce  →  doğrula & çöz  →  düz metin
        ↑ anahtar DB DIŞINDA (Bölüm 25); kurcalama etiketle yakalanır

 ADOBE'NİN YANLIŞI (asla):
   parola  →  3DES-ECB (sabit anahtar, salt yok)  →  DB
        ↑ geri döndürülebilir + aynı parola → aynı çıktı + düz-metin ipucu
        → anahtar sızmadan bile en yaygın parolalar çözüldü

Kritik ayrım: parola akışı tek yönlüdür (hash), veri akışı çift yönlüdür (şifreleme). Doğru problemi doğru araçla eşleştirmek, bu bölümün özüdür.


4. Güvensiz Kod

Gerçekçi bir kayıt/saklama katmanı:

<?php
// ⚠️ GÜVENSİZ — çoklu kripto hatası
declare(strict_types=1);

// 1) Parola: hızlı, tuzsuz hash (Adobe-benzeri hata sınıfı)
$hash = md5($_POST['password']);                 // tuzsuz + hızlı + kırık
$pdo->prepare('INSERT INTO users (email, pass) VALUES (?, ?)')
    ->execute([$_POST['email'], $hash]);

// 2) Saklanan API anahtarı: ECB modu (kalıp sızdırır)
$key = 'hardcoded-secret-key-1234';              // koda gömülü anahtar (Bölüm 25)
$enc = openssl_encrypt($apiKey, 'aes-128-ecb', $key);  // ECB!

// 3) "Rastgele" token: kriptografik değil
$token = md5(uniqid((string)rand(), true));      // tahmin edilebilir üreteç

// 4) Karşılaştırma: gevşek + zamanlamaya açık
if ($storedHash == md5($_POST['password'])) { /* ... */ }  // Böl. 1

5. Açığın Analizi

md5($_POST['password']) — Üç ayrı hata: (1) MD5 kriptografik olarak kırık ve hızlı — GPU ile saniyede milyarlarca deneme. (2) Tuzsuz — rainbow table'lara ve aynı-parola-aynı-hash sızıntısına açık. (3) Yavaşlatma yok — kaba kuvvet ucuz. Parola saklama için tamamen yanlış araç.

openssl_encrypt($apiKey, 'aes-128-ecb', $key)ECB modu. Her 16 baytlık blok bağımsız şifrelendiğinden, aynı düz-metin blokları aynı şifreli blokları üretir; bu, veri kalıplarını sızdırır (Adobe'nin hatası). Ayrıca ECB kimlik doğrulama sağlamaz — kurcalama yakalanmaz. Anahtar da koda gömülü (Bölüm 25). Doğrusu: AES-GCM / libsodium secretbox + rastgele nonce + DB-dışı anahtar.

md5(uniqid(rand()))Kriptografik olmayan rastgelelik. uniqid zamana dayalı ve tahmin edilebilir; rand/mt_rand kriptografik güvenli değildir. Bir güvenlik token'ı bu üreteçlerle tahmin edilebilir hâle gelir (Bölüm 12 reset token). Doğrusu: random_bytes/random_int (CSPRNG).

$storedHash == md5(...) — Gevşek karşılaştırma (type juggling, Bölüm 1/12) + zaten yanlış hash. Kimlik doğrulamada password_verify kullanılmalı.

Kök sorun: Her satır, kriptografiyi "işe yarıyor gibi" ama temelden yanlış kullanıyor — tam da "kendi kriptonu yazma" kuralının ihlali.


6. Hacker Bakış Açısı

Saldırgan kripto zayıflıklarını nasıl değerlendirir?

Sızıntı sonrası hash türünü tanır. Bir veritabanı sızarsa (SQLi, yedek ifşası vb.), saldırganın ilk işi hash biçimini tanımaktır: 32 hex karakter → MD5, 40 → SHA-1, $2y$... → bcrypt, $argon2id$... → Argon2. MD5/SHA-1 görürse sevinir; GPU ile hızla kırar. bcrypt/Argon2 görürse çoğu parolayı kıramaz — yavaşlatma işini yapar.

Tuz olup olmadığına bakar. Tuzsuz hash'lerde, önceden hesaplanmış rainbow table'larla anında eşleştirme yapar; aynı hash'i paylaşan kullanıcıları (aynı parola) toplu çözer. Adobe'de ECB modu ve düz-metin ipuçları, anahtar olmadan bile en yaygın parolaları ifşa etti.

Rastgeleliği yoklar. Token/nonce/session id gibi değerlerin tahmin edilebilir olup olmadığını inceler; time(), ardışık sayaç veya zayıf üreteç izleri arar. Tahmin edilebilir bir üreteç, tüm kriptografik korumayı çökertir.

Modu ve kurcalamayı test eder. Şifreli veri kurcalanabiliyorsa (kimlik doğrulamasız şifreleme — ECB/CBC-without-MAC), saldırgan bit çevirme (bit-flipping) veya padding oracle gibi saldırılarla düz metni etkileyebilir. Kimlik doğrulamalı şifreleme (GCM/Poly1305) bunu kapatır.

Savunmacı dersi: Kripto zayıflığı, çoğu zaman başka bir açık (SQLi, yedek sızıntısı) DB'yi ifşa ettiğinde ortaya çıkar. Bu yüzden parola saklama, "son savunma hattıdır" — sızıntı gerçekleştiğinde bile parolaların kırılmamasını sağlamalıdır. bcrypt/Argon2 + tuz + pepper bu hattı tutar.


7. Exploit Mantığı

Bu bölüm çalıştırılabilir kırma araçları içermez. Kripto hatalarının neden felakete vardığı kavramsaldır:

  • Geri döndürülebilirlik = toplu ifşa. Parolalar hash yerine şifrelenmişse ve anahtar sızarsa, tüm parolalar anında düz metne döner. Adobe'de anahtar sızmasa bile, ECB + ipuçları en yaygın parolaları çözdü.
  • Hız = kaba kuvvet. Hızlı hash (MD5/SHA), sızmış hash'lerin GPU ile ekonomik biçimde kırılmasını sağlar. Yavaşlatma (bcrypt/Argon2) bu ekonomiyi bozar.
  • Tuzsuzluk = ölçek. Tuz yoksa saldırgan bir kez hesaplayıp milyonlarca hash'e uygular (rainbow table); tuz bunu her parola için ayrı işe çevirir.
  • Kötü rastgelelik = tahmin. Zayıf üreteçle üretilen token/anahtar, kriptografiyi baypas ederek tahmin edilir hâle gelir.
  • Kimlik doğrulamasız şifreleme = kurcalama. MAC'siz modlar, saldırganın şifreli metni anlamlı biçimde değiştirmesine (bit-flipping, padding oracle) açıktır.

Araştırmacının çerçevesi: (a) parola şifreli mi hash mi, (b) hash hızlı mı yavaş mı, tuzlu mu, (c) rastgelelik CSPRNG mi, (d) şifreleme kimlik doğrulamalı mı. Savunma, bu dördünü modern API'lerle otomatik doğru yaparak sağlanır.


8. Güvenli Kod

Modern PHP'de doğru araçlar zoru basitleştirir:

<?php
// ✅ GÜVENLİ — modern parola hash'leme ve şifreleme
declare(strict_types=1);

// 1) PAROLA: password_hash — tuz OTOMATİK, algoritma yavaş/bellek-zor
$hash = password_hash($_POST['password'], PASSWORD_ARGON2ID, [
    'memory_cost' => 65536,   // 64 MB
    'time_cost'   => 4,
    'threads'     => 2,
]);
// (Argon2id yoksa PASSWORD_BCRYPT + ['cost' => 12] da güçlü bir seçimdir)
$pdo->prepare('INSERT INTO users (email, pass_hash) VALUES (?, ?)')
    ->execute([$email, $hash]);

// Giriş doğrulama (Böl. 12)
if (password_verify($_POST['password'], $storedHash)) {
    if (password_needs_rehash($storedHash, PASSWORD_ARGON2ID, [...])) {
        // parametreler eskiyse sessizce yükselt
    }
}

// 2) VERİ ŞİFRELEME (geri alınabilir): libsodium — kimlik doğrulamalı
$key = sodium_crypto_secretbox_keygen();           // anahtarı GÜVENLİ sakla (Böl. 25)
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);   // her mesaj için YENİ
$cipher = sodium_crypto_secretbox($plaintext, $nonce, $key);
$stored = base64_encode($nonce . $cipher);         // nonce'u şifreli metinle sakla

// Çözme (kurcalanmışsa exception atar)
$raw = base64_decode($stored);
$n   = substr($raw, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$c   = substr($raw, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$plain = sodium_crypto_secretbox_open($c, $n, $key);
if ($plain === false) {
    throw new RuntimeException('Şifre çözme/kimlik doğrulama başarısız (kurcalama?)');
}

// 3) RASTGELELİK: CSPRNG
$token = bin2hex(random_bytes(32));                // token
$otp   = random_int(100000, 999999);               // sayısal OTP

// 4) KARŞILAŞTIRMA: sabit-süreli (Böl. 1)
if (hash_equals($expectedToken, $providedToken)) { /* ... */ }

Öne çıkan modern PHP araçları: - password_hash / password_verify: Tuzu otomatik üretir ve hash'e gömer; algoritmayı (PASSWORD_ARGON2ID, PASSWORD_BCRYPT, PASSWORD_DEFAULT) ve maliyeti yönetir. Parola saklamanın tek doğru yolu budur. - password_needs_rehash: Parametreler güçlendikçe girişte sessiz yükseltme (Bölüm 12). - libsodium (sodium_crypto_*): PHP 7.2+ ile yerleşik; kimlik doğrulamalı şifreleme (secretbox = XChaCha20-Poly1305), imzalama, anahtar üretimi. Modern PHP kriptosunun standardıdır. - random_bytes / random_int: CSPRNG; token/nonce/OTP için. rand/mt_rand/uniqid güvenlik için asla. - hash_equals: Sabit-süreli karşılaştırma (Bölüm 1).

bcrypt tuzağı: bcrypt girdiyi 72 bayta keser; çok uzun parolalarda sessiz kesme olur. Argon2id bu sınırı taşımaz; bcrypt kullanılacaksa çok uzun girdiler için önce SHA-256+base64 ön-hash uygulanır.


9. Patch Analizi

Neden işe yarar? password_hash, dört doğru kararı otomatikleştirir: yavaş/bellek-zor algoritma (kaba kuvveti pahalılaştırır), otomatik benzersiz tuz (rainbow table + toplu ifşayı önler), ayarlanabilir maliyet (donanım güçlendikçe artırılır) ve taşınabilir hash biçimi (algoritma/tuz/maliyet hash'in içinde). libsodium ise kimlik doğrulamalı şifrelemeyi varsayılan yapar; kurcalama otomatik yakalanır. Her iki API de "kendi kriptonu yazma" kuralını uygulanabilir kılar.

Alternatiflerin karşılaştırması:

İhtiyaç Yanlış Doğru
Parola saklama MD5/SHA (hızlı, tuzsuz) password_hash (Argon2id/bcrypt)
Geri alınabilir veri AES-ECB / MAC'siz AES-GCM / libsodium secretbox
Rastgelelik rand/mt_rand/uniqid random_bytes/random_int
Hash karşılaştırma ==/=== hash_equals
Anahtar saklama Koda gömülü Sır yöneticisi (Bölüm 25)

Performans: Parola hash'leme bilinçli olarak yavaştır — bu bir güvenlik özelliğidir. Maliyet, sunucuyu zorlamadan kaba kuvveti caydıracak biçimde ayarlanır (bcrypt cost ~12, Argon2 ~64 MB tipik başlangıç). Argon2 bellek-zor olduğundan GPU/ASIC saldırılarına bcrypt'ten daha dayanıklıdır; maliyeti sunucu kapasitesine göre kalibre edilir. libsodium/AES-GCM çok hızlıdır; performans engeli değildir.


10. Gerçek Hayat Senaryosu

Kurgu — bir sağlık teknolojisi (healthtech) platformu. Sistem, hasta kayıtlarını ve giriş parolalarını saklıyor. Geliştirici, "hepsi hassas veri" diye parolaları da hasta verisiyle aynı AES anahtarıyla şifreliyor (hash yerine) — böylece "destek ekibi gerekirse parolayı görebilsin" diye. Yıllar sonra bir yedek sızıntısı (yanlış yapılandırılmış depolama) hem şifreli veriyi hem anahtarı ifşa ediyor. Parolalar hash'lenmediği için tümü anında düz metne dönüyor; kullanıcılar parola tekrar kullandığından, saldırgan bu parolalarla başka platformlara da giriyor (credential stuffing, Bölüm 12). Dersler: (1) parola asla şifrelenmez, hash'lenir — "geri görme" ihtiyacı bir anti-desendir; (2) "hepsi hassas" mantığı, tek-yönlü ve çift-yönlü problemleri birbirine karıştırır; (3) tek anahtara bağımlılık, tek nokta felaketidir (Adobe dersi).


11. Gerçek Vaka Analizi — Adobe İhlali (2013)

Have I Been Pwned, Ars Technica, CSO, Sophos ve Bruce Schneier'in analizleriyle doğrulanmıştır. Kripto hatalarının en öğretici gerçek dünya vakasıdır.

Özet. Ekim 2013'te yaklaşık 153 milyon Adobe hesabı ihlal edildi. Sızan kayıtların her biri bir iç kimlik, kullanıcı adı, e-posta, şifrelenmiş parola ve düz metin parola ipucu içeriyordu. Sorun parolaların korunmaması değildi — yanlış korunmasıydı. Bu, "her şeyi yaptık ama yanlış yaptık" durumunun ders kitabı örneğidir.

Teknik neden — üç kripto hatası bir arada. 1. Hash yerine şifreleme. Adobe parolaları tek-yönlü hash'lemek yerine 3DES ile şifreledi — yani geri döndürülebilir biçimde. Parola saklama tek-yönlü bir problem olduğundan bu temelden yanlıştı; anahtar sızarsa tüm parolalar düz metne döner. 2. ECB modu. Şifreleme ECB modunda ve tüm parolalar için aynı anahtarla yapıldı. ECB'de aynı düz metin aynı şifreli metni ürettiğinden, aynı parolayı seçen kullanıcılar bayt-bayt aynı şifreli metni paylaştı. Bu, en yaygın parolaların anahtar olmadan bile kümelenerek belirlenmesini sağladı. 3. Düz metin ipuçları. Parola ipuçları düz metin saklandı. Kullanıcıların çoğu ipucu olarak parolanın kendisini (veya çok belirgin bir çağrışımı) yazdığından, araştırmacılar (Jeremi Gosney) aynı şifreli metni paylaşan binlerce ipucunu analiz ederek en yaygın 100 parolayı yaklaşık üç saatte, şifreleme anahtarına hiç ihtiyaç duymadan çözdüler.

Bu üç hata birbirini büyüttü: ECB "hangi kullanıcılar aynı parolayı kullanıyor" bilgisini verdi, düz-metin ipuçları da o ortak parolanın ne olduğunu ifşa etti. Doğru yaklaşım — her parolaya benzersiz tuzlu, yavaş bir hash (bcrypt/scrypt) — bu saldırıların hepsini imkânsız kılardı.

Etki. Yüz milyonlarca kullanıcının parolası (ve parola alışkanlıkları) ifşa oldu. Kullanıcılar parola tekrar kullandığından etki Adobe'nin çok ötesine (credential stuffing) taştı; sızan liste, sonraki yıllarda parola kırma sözlüklerini besledi.

Çıkarılacak dersler: 1. Parolalar şifrelenmez, hash'lenir. Geri döndürülebilir her yöntem yanlıştır — "geri görme" ihtiyacı bir anti-desendir. 2. ECB modu asla kullanılmaz — kalıp sızdırır. Kimlik doğrulamalı modlar (GCM/Poly1305) standarttır. 3. Yardımcı veriler (ipuçları) korumayı çökertebilir. Bir sistemin güvenliği en zayıf bileşeni kadardır; düz-metin ipucu, kriptografiyi anlamsız kıldı. 4. Tuz zorunludur. Benzersiz tuz olsaydı, aynı-parola-aynı-çıktı sızıntısı hiç oluşmazdı.


12. Detection

Kod incelemede: Yanlış kripto araçlarını arayın:

grep -rnE 'md5\(|sha1\(|hash\("?(md5|sha1)' src/ | grep -i pass   # parola için zayıf hash
grep -rn  'ecb'                    src/   # ECB modu
grep -rnE 'mcrypt_'                src/   # kaldırılmış, güvensiz kütüphane
grep -rnE 'rand\(|mt_rand\(|uniqid\(' src/ | grep -iE 'token|key|salt|nonce|otp'  # zayıf rastgelelik
grep -rn  'openssl_encrypt'        src/   # mod ve IV kullanımını incele

Her bulguda: parola password_hash mı? Şifreleme kimlik doğrulamalı mı? Rastgelelik CSPRNG mi?

SAST: Zayıf hash (CWE-327/916), ECB/statik IV, sabit anahtar (CWE-321), zayıf rastgelelik (CWE-330) için olgun kurallar.

DAST: Tahmin edilebilir token/OTP'yi (öngörülebilirlik testi) ve kimlik doğrulamasız şifrelemeyi (kurcalama toleransı) tespit edebilir.

Loglar/SIEM: Kripto hataları çoğunlukla sızıntı sonrası görünür; asıl tespit, sızıntıyı besleyen açıkların (SQLi, yedek ifşası) izlenmesidir. Ayrıca çok sayıda başarılı girişin ardından gelen olağandışı erişim, kırılmış parolaların kullanıldığına işaret edebilir (Bölüm 12).


13. Prevention

  • Parolayı hash'le, şifreleme: password_hash (Argon2id/bcrypt) + otomatik tuz; opsiyonel pepper (Bölüm 25).
  • Yavaş/bellek-zor algoritma: Argon2id tercih; maliyeti donanıma göre kalibre et.
  • Kimlik doğrulamalı şifreleme: Geri alınabilir veri için libsodium secretbox / AES-GCM; ECB/mcrypt asla.
  • Her mesaja yeni nonce/IV; statik IV kullanma.
  • CSPRNG: random_bytes/random_int; asla rand/mt_rand/uniqid.
  • Sabit-süreli karşılaştırma: hash_equals (Bölüm 1).
  • Anahtar yönetimi: Anahtarlar koda gömülmez; sır yöneticisinde (Bölüm 25); düzenli rotasyon.
  • Kendi kriptonu yazma: Yüksek seviyeli API'lere (libsodium) güven; ilkel blokları elle birleştirme.

14. Mitigation

  • Acil: Zayıf hash tespit edilirse, girişte password_verify başarılı olunca parolayı güçlü algoritmayla rehash et (Bölüm 12); yeni kayıtları hemen güçlü API'ye geçir.
  • Geçici: Sızıntı olduysa etkilenen tüm parolaları geçersiz kıl ve zorunlu sıfırlama başlat; sızmış olabilecek anahtarları döndür; kullanıcıları credential stuffing'e karşı uyar/MFA'ya yönlendir.
  • Kalıcı: Tüm parola saklamayı password_hash'e taşı; şifrelemeyi libsodium'a geçir; anahtar yönetimini sır yöneticisine al; testler + SAST kuralları ekle.

15. Checklist

  • [ ] Parolalar password_hash (Argon2id/bcrypt) ile mi saklanıyor (MD5/SHA/şifreleme yok)?
  • [ ] Tuz otomatik ve benzersiz mi (elle tuz yönetimi yok)?
  • [ ] password_needs_rehash ile sessiz yükseltme var mı?
  • [ ] Geri alınabilir veri kimlik doğrulamalı şifreleme (GCM/secretbox) ile mi? ECB/mcrypt yok mu?
  • [ ] Her şifrelemede yeni, rastgele nonce/IV mi kullanılıyor?
  • [ ] Token/OTP/nonce/anahtar random_bytes/random_int ile mi (CSPRNG)?
  • [ ] Hash/token karşılaştırmaları hash_equals mı?
  • [ ] Anahtarlar koddan ayrı, sır yöneticisinde mi (Bölüm 25)?
  • [ ] bcrypt kullanılıyorsa 72 bayt kesme tuzağı ele alındı mı?

16. Laboratuvar

Lab 13.1 — Hash türlerini karşılaştır. İzole ortamda aynı parolayı MD5, SHA-256, bcrypt ve Argon2id ile hash'le; her birini bir kez daha çalıştırıp bcrypt/Argon2'nin her seferinde farklı (otomatik tuz), MD5/SHA'nın aynı çıktı verdiğini gözlemle. Yavaşlık farkını (microtime) ölç.

Lab 13.2 — ECB kalıp sızıntısı. Aynı 16 baytlık bloğu birkaç kez içeren bir veriyi AES-ECB ve AES-GCM ile şifrele; ECB çıktısında tekrar eden blokları (kalıp), GCM'de tekrarın olmadığını gözlemle. "ECB penguen" ilkesini açıkla.

Lab 13.3 — Rastgelelik. mt_rand ve random_int ile üretilen çok sayıda token'ı karşılaştır; birincinin tohumdan tahmin edilebilirliğini (aynı tohum → aynı dizi) göster.

Lab 13.4 — Rehash. password_needs_rehash ile, maliyet artırıldığında girişte hash'in nasıl sessizce yükseltildiğini uygula.


17. Quiz

  1. Kodlama, şifreleme ve hash'leme arasındaki üç temel fark nedir?
  2. Parolalar neden hash'lenmeli, şifrelenmemelidir? "Geri görme" ihtiyacı neden bir anti-desendir?
  3. SHA-256 neden parola için yanlış, ama bütünlük için doğrudur?
  4. Tuzun iki işlevi nedir? Tuzsuzluk hangi iki saldırıya açar?
  5. Pepper nedir ve tuzdan farkı nedir? Nerede saklanır?
  6. bcrypt ile Argon2id arasındaki fark nedir? Argon2 neden "bellek-zor"dur?
  7. ECB modu neden tehlikelidir? Adobe'de bu ne sızdırdı?
  8. password_hash hangi dört doğru kararı otomatikleştirir?
  9. rand/mt_rand/uniqid neden güvenlik token'ları için uygun değildir? Alternatifi nedir?
  10. Kimlik doğrulamalı şifreleme (GCM/Poly1305) MAC'siz modlardan neyi fazladan sağlar?
  11. Adobe vakasında üç kripto hatası nasıl birbirini büyüttü?
  12. bcrypt'in 72 bayt tuzağı nedir ve nasıl ele alınır?

18. Kaynakça

  • OWASP, Password Storage Cheat Sheet; Cryptographic Storage Cheat Sheet.
  • MITRE, CWE-327: Use of a Broken or Risky Cryptographic Algorithm; CWE-916: Use of Password Hash With Insufficient Computational Effort; CWE-759: Use of One-Way Hash without a Salt; CWE-330: Use of Insufficiently Random Values.
  • PHP Manual, password_hash, password_verify, password_needs_rehash, random_bytes, random_int, hash_equals ve Sodium (sodium_crypto_*) referansları.
  • NIST SP 800-63B; NIST SP 800-38A (blok şifreleme modları — ECB uyarısı).
  • Have I Been Pwned, Adobe ihlal kaydı; Sophos/Naked Security ve Bruce Schneier, Adobe cryptographic blunder analizleri.
  • IETF RFC 9106 (Argon2) ve libsodium dokümantasyonu.