OWASP A10:2025 "istisnai durumlar": hata yakalarken açık kapı bırakmak

Sabit admin açtı, 5 gün önce 0 yanıt 10 görüntülenme
admin Admin
  • 0 mesaj
  • 1K puan
  • Katılım 12.2025
  • Konu sahibi

OWASP Top 10:2025'e yeni giren A10 – Mishandling of Exceptional Conditions kategorisi, uzun süredir sahada gördüğümüz ama adı konmamış bir hata ailesini kapsıyor: uygulama beklenmedik bir durumla karşılaştığında yanlış yöne düşmesi. Bu konuda en sık gördüğüm üç kalıbı ve düzeltmelerini örnek kodla paylaşıyorum.

1. "Fail open": hata olunca izin vermek

Yetki kontrolü bir dış servise, veritabanına ya da önbelleğe bağlıysa ve o servis hata verirse ne oluyor?

// YANLIŞ: yetki servisi çökerse herkes içeri girer
function canEdit(int $userId, int $postId): bool {
    try {
        return $this->acl->check($userId, 'edit', $postId);
    } catch (\Throwable $e) {
        error_log($e->getMessage());
        return true;   // "kullanıcıyı mağdur etmeyelim"
    }
}

// DOĞRU: hata durumunda reddet
function canEdit(int $userId, int $postId): bool {
    try {
        return $this->acl->check($userId, 'edit', $postId);
    } catch (\Throwable $e) {
        error_log('ACL hatası: ' . $e->getMessage());
        return false;
    }
}

Aynı kalıp hız sınırlayıcılarda da görülür: Redis'e ulaşılamayınca sınırlamanın tamamen devre dışı kalması, kaba kuvvet saldırısı için tam fırsattır.

2. Hata mesajında iç bilgi sızdırmak

SQL hatası, dosya yolu, yığın izi ya da sunucu sürümü kullanıcıya gösterilmemeli. Doğrusu: kullanıcıya genel bir mesaj, kayıt dosyasına ayrıntı.

try {
    $router->dispatch();
} catch (\Throwable $e) {
    error_log(get_class($e) . ': ' . $e->getMessage() . ' @ ' . $e->getFile() . ':' . $e->getLine());
    http_response_code(500);
    include 'views/errors/500.php';   // ayrıntı yok
}

PHP'de üretim ortamında display_errors=0, log_errors=1 olmalı. Ayrıntıyı görmek isteyen yöneticiye bile yalnızca kısa bir özet gösterin, yığın izini değil.

3. Yarım kalan işlemler

Para transferi, puan aktarma, stok düşme gibi çok adımlı işlemlerde bir adım hata verirse önceki adımlar geri alınmalı. Aksi halde saldırgan hatayı bilerek tetikleyip tutarsız durumdan yararlanabilir (örneğin puanın düşülmeden ödülün verilmesi).

$db->beginTransaction();
try {
    $db->execute('UPDATE users SET points = points - ? WHERE id = ? AND points >= ?', [$cost, $uid, $cost]);
    if ($db->rowCount() !== 1) throw new RuntimeException('Yetersiz puan');
    $db->execute('INSERT INTO rewards (user_id, item) VALUES (?, ?)', [$uid, $item]);
    $db->commit();
} catch (\Throwable $e) {
    $db->rollBack();
    throw $e;
}

Kod incelemesinde sorulacak sorular

  • Her catch bloğunda sonuç ne? İşlem reddediliyor mu, yoksa sessizce devam mı ediliyor?
  • Boş catch {} blokları var mı?
  • Zaman aşımı, boş yanıt, beklenmeyen tür (null, dizi yerine metin) durumları test ediliyor mu?
  • Kullanıcıya dönen hata mesajları kimlik, yol ya da sürüm bilgisi içeriyor mu?

Kendi kodunuzda karşılaştığınız "fail open" örneklerini (anonimleştirerek) paylaşırsanız, iyi bir eğitim arşivi olur.

Kaynaklar

Yanıt yazmak için giriş yap. Giriş yap Hesap oluştur