Modern uygulamalarda güvenliği artırmak için yapılan değişiklikler bazen tam tersine kritik zafiyetlere yol açabilir.
Bunun güzel bir örneği: FreshRSS’te keşfedilen CVE-2025-68402 (GHSA-pcq9-mq6m-mvmp).
Bu zafiyet, basitçe söylemek gerekirse:
İlginç olan kısım ise şu:
Bu hata, güvenliği artırmak amacıyla yapılan bir güncellemeden sonra ortaya çıkıyor.
Bu nedenle pratik exploitation çok kolay, fakat anlaşılması oldukça öğretici bir bug.
bcrypt hash’leri şu yapıya sahiptir:
$2y$10$abcdefghijklmnopqrstuuABCDEFGHIJKLMNOPQRSTUVWXYZ01234
Parçalayalım:
💡 Kritik bilgi:
FreshRSS klasik login yerine challenge-response kullanıyor:
s = bcrypt(password, salt1)
c = bcrypt(nonce + s, randomSalt)
password_verify($nonce . $hash, $challenge);
Yapılan değişiklikler:
Güzel görünüyor, değil mi?
Ama kritik değişiklik:
- sha1(...) → 40 karakter nonce
+ sha256(...) → 64 karakter nonce
nonce (40) + hash (60) = 100 karakter
bcrypt → ilk 72 byte:
[ nonce (40) + hash’in ilk 32 karakteri ]
Bu 32 karakter:
👉 şifreye bağlı hash içeriyor → doğrulama doğru çalışıyor
nonce (64) + hash (60) = 124 karakter
bcrypt → ilk 72 byte:
[ nonce (64) + hash’ten sadece 8 karakter ]
Bu 8 karakter:
$2y$10$X
Yani:
❗ Şifreye bağlı hiçbir veri yok
password_verify(...) → HER ZAMAN TRUE
Yani:
Çözüm çok basit:
- nonce + hash
+ hash + nonce
password_verify($hash . $nonce, $challenge);
Artık:
Bu bug, tek bir hatadan değil:
👉 birleşiminden doğuyor
FreshRSS:
Ama çoğu modern uygulama:
👉 Daha basit → daha güvenli → daha test edilebilir
Projede:
Tek bir test bunu yakalardı:
"yanlış şifre ile login → başarısız olmalı"
👉 En teknik kullanıcılar risk altındaydı
Bu zafiyet, klasik bir örnek:
Ve bize şunu hatırlatıyor:
CVE-2025-68402, exploitation açısından basit olsa da
security engineering açısından oldukça değerli bir ders sunuyor.
Eğer güvenlik alanında çalışıyorsanız:
Bu konu: https://spyhackerz.org/ için hazırlanmıştır, İzinsiz ve link vermeden lütfen paylaşmayın.
Bunun güzel bir örneği: FreshRSS’te keşfedilen CVE-2025-68402 (GHSA-pcq9-mq6m-mvmp).
Bu zafiyet, basitçe söylemek gerekirse:
Kullanıcının şifresi ne olursa olsun giriş yapılabilmesine neden oluyor.
İlginç olan kısım ise şu:
Bu hata, güvenliği artırmak amacıyla yapılan bir güncellemeden sonra ortaya çıkıyor.
Zafiyetin Kapsamı
- Etkilenen: FreshRSS edge (geliştirme) branch
- Etkilenmeyen: Stable sürümler
- Etki: Authentication bypass (şifre kontrolü tamamen devre dışı)
- Exploit zorluğu: Çok düşük (herhangi bir şifre ile login)
Bu nedenle pratik exploitation çok kolay, fakat anlaşılması oldukça öğretici bir bug.
bcrypt Nasıl Çalışır? (Kısa Hatırlatma)
bcrypt hash’leri şu yapıya sahiptir:
$2y$10$abcdefghijklmnopqrstuuABCDEFGHIJKLMNOPQRSTUVWXYZ01234
Parçalayalım:
- $2y$ → algoritma
- 10 → cost factor
- 22 karakter → salt
- 31 karakter → password’a bağlı hash çıktısı
💡 Kritik bilgi:
bcrypt, input’u 72 byte ile sınırlar.
72 byte sonrası tamamen yok sayılır.
FreshRSS Authentication Mekanizması
FreshRSS klasik login yerine challenge-response kullanıyor:
Adımlar:
- Client → server’dan alır:
- nonce
- salt1
- Client hesaplar:
s = bcrypt(password, salt1)
c = bcrypt(nonce + s, randomSalt)
- Client → server’a gönderir:
- challenge (c)
- Server doğrular:
password_verify($nonce . $hash, $challenge);
Sorunun Başlangıcı: "Crypto Güçlendirme" Commit’i
Yapılan değişiklikler:
- mt_rand() → random_bytes()
- uniqid() → daha güvenli random üretim
- sha1() → sha256
Güzel görünüyor, değil mi?
Ama kritik değişiklik:
- sha1(...) → 40 karakter nonce
+ sha256(...) → 64 karakter nonce
Hata Nasıl Oluştu?
Önceki durum:
nonce (40) + hash (60) = 100 karakter
bcrypt → ilk 72 byte:
[ nonce (40) + hash’in ilk 32 karakteri ]
Bu 32 karakter:
👉 şifreye bağlı hash içeriyor → doğrulama doğru çalışıyor
Yeni durum:
nonce (64) + hash (60) = 124 karakter
bcrypt → ilk 72 byte:
[ nonce (64) + hash’ten sadece 8 karakter ]
Bu 8 karakter:
$2y$10$X
Yani:
- algoritma bilgisi
- cost
- salt’ın bir kısmı
❗ Şifreye bağlı hiçbir veri yok
Sonuç
password_verify(...) → HER ZAMAN TRUE
Yani:
Kullanıcı adı doğruysa, şifre ne olursa olsun giriş yapılabiliyor.
🛠️ Fix Nasıl Yapıldı?
Çözüm çok basit:
- nonce + hash
+ hash + nonce
Yeni akış:
password_verify($hash . $nonce, $challenge);
Artık:
- İlk 60 byte = hash (şifreye bağlı veri)
- bcrypt truncation artık problem değil
Çıkarılması Gereken Dersler
1. “Daha Güçlü” Her Zaman Daha Güvenli Değildir
- SHA-256, SHA-1’den daha güçlüdür
- Ama burada:
Daha uzun nonce → bcrypt truncation → auth bypass
2. Kriptografik Primitive’leri Birleştirirken Dikkat
Bu bug, tek bir hatadan değil:
- nonce uzunluğu
- bcrypt limiti
- string birleştirme sırası
👉 birleşiminden doğuyor
3. Over-Engineering Güvenliği Zayıflatabilir
FreshRSS:
- client-side bcrypt
- challenge-response
- nonce sistemi
Ama çoğu modern uygulama:
HTTPS üzerinden şifre gönder + server-side hash
👉 Daha basit → daha güvenli → daha test edilebilir
4. Authentication Testleri Şart
Projede:
- şifre validasyon testleri var
- ama login testleri yok
Tek bir test bunu yakalardı:
"yanlış şifre ile login → başarısız olmalı"
5. Edge Branch de Güvenlik Riski Taşır
- Bug stable’a çıkmadı ✅
- Ama 2 ay boyunca edge branch’te kaldı ❗
👉 En teknik kullanıcılar risk altındaydı
Sonuç
Bu zafiyet, klasik bir örnek:
“Güvenliği artırmaya çalışırken sistemi kırmak”
Ve bize şunu hatırlatıyor:
- Kriptografi hassastır
- Küçük değişiklikler büyük sonuçlar doğurabilir
- Basit sistemler genelde daha güvenlidir
Kapanış
CVE-2025-68402, exploitation açısından basit olsa da
security engineering açısından oldukça değerli bir ders sunuyor.
Eğer güvenlik alanında çalışıyorsanız:
Bu tür "subtle bug"’ları anlamak sizi bir adım öne taşır.
Bu konu: https://spyhackerz.org/ için hazırlanmıştır, İzinsiz ve link vermeden lütfen paylaşmayın.