📌 CAPTCHA Nedir?

  • CAPTCHA: "Completely Automated Public Turing test to tell Computers and Humans Apart" ifadesinin kısaltmasıdır.
  • Amaç: Bir kullanıcının gerçekten insan olduğunu kanıtlamak.
  • Örnekler: Harf-rakam kombinasyonlarını yazmak, resimlerden nesne seçmek, basit matematik soruları çözmek.

Lab'ın Amacı Nedir?

Bu lab, kullanıcıdan:

  • Bir yorum girmesini
  • Captcha'yı doğru çözmesini

bekleyen basit bir web formu içeriyor. Amaç, captcha doğrulamasını geçmeden yorum eklenememesi.

Ancak uygulamada captcha:

  • Tek kullanımlık değil
  • Form ile ilişkili değil
  • Session içinde yanlış şekilde yönetiliyor

Sonuç olarak captcha teorik olarak var, pratikte yok.

Captcha Mekanizması Nasıl Çalışıyor?

Sayfa her yüklendiğinde şu işlemler gerçekleşiyor:

$captchaData = generateCaptcha(200, 50);
$captchaValue = $captchaData['captcha'];
array_push($_SESSION['captchas'], $captchaValue);

Bu kod:

  • Yeni bir captcha üretir
  • Bu captcha'yı session içindeki captchas dizisine ekler

⚠️ Kritik nokta: Eski captcha'lar silinmez.

Session'da Ne Birikiyor?

Sayfa her yenilendiğinde session şu hale gelir:

[
  "Ab3Xk9",
  "Qp8L2A",
  "Z7mN4R",
  ...
]

Yani:

  • Sınırsız captcha
  • Hepsi geçerli
  • Hangisinin form ile ilişkili olduğu bilinmiyor

Bu noktada captcha, tekil bir doğrulama mekanizması olmaktan çıkar, bir izin listesine (whitelist) dönüşür.

Captcha Doğrulama Mantığı (Asıl Hata)

Form gönderildiğinde yapılan kontrol:

if (in_array($submitted_captcha, $_SESSION['captchas'])) {
    // başarılı
}

Bu kontrol şunu söylüyor:

"Eğer girilen captcha, daha önce ürettiğim captcha'lardan herhangi biri ise kabul et."

❌ Şu kontrollerin hiçbiri yok:

  • Bu captcha son üretilen mi?
  • Bu form isteğine mi ait?
  • Daha önce kullanılmış mı?

Bu da replay attack'e açık bir yapı oluşturuyor.

Lab Nasıl Çözüldü?

1️⃣ İlk giriş

  • Sayfa açıldı
  • Captcha-1 üretildi
  • Session'a eklendi

2️⃣ İlk form gönderimi

  • Captcha-1 girildi
  • in_array() kontrolü geçti
  • Yorum başarıyla eklendi

3️⃣ Sayfaya tekrar girildi

  • Yeni captcha (Captcha-2) üretildi
  • Session artık:
[Captcha-1, Captcha-2]

4️⃣ Bypass noktası

  • Görselde Captcha-2 olmasına rağmen
  • Formda Captcha-1 tekrar girildi
None

5️⃣ Sonuç

  • in_array(Captcha-1, session) → TRUE
  • Form tekrar kabul edildi
  • Captcha tamamen bypass edildi

🎯 Lab başarıyla çözüldü.

Broken Captcha

1️⃣ Uygulamanın İncelenmesi (Recon)

Karşımıza basit bir iletişim formu çıkıyor:

None
  • Name-Surname
  • Message
  • Captcha
  • Captcha resmi
  • Submit / Forward Message butonu

Yüzeyden bakıldığında:

  • Kullanıcıdan captcha resminde görünen işlemin sonucu bekleniyor
  • Yanlış captcha girilirse form gönderilmemeli

Ama burada kritik soru şu:

Bu doğrulama gerçekten server-side mı yapılıyor?

Bunu anlamanın tek yolu request'i yakalamak.

2️⃣ Burp Suite ile Request Yakalama

  1. Burp Suite açılır
  2. Proxy → Intercept ON
  3. Form normal şekilde doldurulur (captcha doğru ya da yanlış fark etmez)
  4. Submit tıklanır

Request Burp'te yakalanır.

3️⃣ Yakalanan Request'in Analizi

Burp'te görülen POST isteğinde şu parametreler dikkat çekiyor:

name=Test User
message=Test message
num1=0
num2=0
captcha=0

Burada çok kritik bir şey fark ediyoruz:

  • Captcha resmi ekranda farklı bir işlem gösteriyor
  • Ama request içinde num1 ve num2 isimli değerler client tarafından gönderiliyor
  • Yani captcha'nın cevabı server'da üretilmemiş

Bu şu anlama gelir:

Server, captcha'nın doğruluğunu kendisi hesaplamıyor, kullanıcının gönderdiği sayılara güveniyor.

Bu başlı başına bir tasarım hatasıdır.

4️⃣ Zafiyetin Mantığını Çözmek

Server tarafındaki kontrol mantığı fiilen şuna benziyor:

if (captcha == num1 + num2) {
    başarılı
}

Ama:

  • num1 ve num2 kullanıcıdan geliyor
  • Yani biz bu denklemin her iki tarafını da kontrol ediyoruz

Bu noktada artık captcha'nın hiçbir anlamı kalmıyor.

5️⃣ Burp ile Manipülasyon (Asıl Sömürü)

Şimdi bilinçli şekilde request'i değiştiriyoruz.

Yapılan değişiklik:

num1=0
num2=0
captcha=0

Matematik:

0 == 0 + 0 → TRUE

Captcha resmi ne gösterirse göstersin:

  • Server bu isteği doğru kabul etmek zorunda

Burp'te request bu şekilde Forward edilir.

6️⃣ Server Cevabının İncelenmesi

Response şu şekilde gelir:

HTTP/1.1 200 OK

Body içinde:

None
Congratulations, verification successful!

Bu çok önemli çünkü:

  • Bu mesaj client-side değil
  • PHP tarafından üretiliyor
  • Yani captcha doğrulaması gerçekten geçmiş durumda

7️⃣ Neden Bu Bir Broken Captcha?

Bu lab'daki temel hata şudur:

  • Captcha verileri server'da üretilmiyor
  • Doğrulama kullanıcıdan gelen değerlere güveniyor
  • Görsel captcha hiç kullanılmıyor

Bu da şu sonucu doğuruyor:

Captcha sadece kullanıcıyı kandıran bir görsellikten ibaret.

Gerçek güvenlik sıfır.