Araştırmalara Dön
Backend Security

Modern API'lerin Sessiz Katili: BOLA / IDOR Zafiyetleri ve Etkileri

İsa CanYazar
31 Mart 2026
4 dk okuma

Modern API'lerin Sessiz Katili: BOLA (IDOR) Zafiyetleri ve Etkileri

Yıl 2026, şirketinizin Backend ekibi Go veya Node.js kullanarak inanılmaz hızlı bir mikroservis API mimarisi (GraphQL veya REST) çıkardı. Veritabanınız ölçekleniyor, kullanıcı yetkilendirmesi (Authentication) JWT ile mükemmel şekilde Auth0 veya AWS Cognito üzerinden yapılıyor. Siz güvende olduğunuzu sanırken, sıradan yetkilere sahip bir kullanıcı (Saldırgan) diğer BÜTÜN kullanıcıların faturalarını tarayıp indirebiliyor. Nasıl mı? Karşınızda Broken Object Level Authorization (BOLA), nam-ı diğer IDOR (Insecure Direct Object Reference).

BOLA, uygulamanızda kritik verileri veya fonksiyonları çeken uç noktaların (Endpoints) manipüle edilmesine dayanır. Geleneksel WAF'lar (Web Application Firewall) veya otomatik kod tarayıcılar (SAST) bu zafiyeti asla bulamaz. Çünkü BOLA, bir SQL Injection gibi "hatalı kod (syntax)" barındırmaz; tamamen "iş mantığı" (Business Logic) eksikliğinden kaynaklanır.

Bu rehberde Eresus Security sızma testi tecrübeleriyle BOLA zafiyetini otopsi masasına yatırıyor, Backend geliştiricilerinin yetki mimarisini oluştururken düştükleri en büyük mantık hatalarını gün yüzüne çıkartıyoruz.


1. Zafiyetin Anatomisi: IDOR/BOLA Nasıl Çalışır?

Bir API'ye yapılan en masum isteği düşünelim: GET /api/v1/invoices/1055

Backend bu isteği aldığında iki şeyi kontrol eder:

  1. Authentication (Kimlik Doğrulama): İstek yapan kişinin geçerli bir JWT'si (Oturumu) var mı? Evet.
  2. Authorization (Genel Yetkilendirme): Bu kişinin faturaları (invoices) okuma yetkisi (Role) var mı? Evet, çünkü o bir Müşteri.

İşte tam burada siber güvenlik felaketi başlar. Sisteme giriş yapmış ve genel anlamda kendi faturasını "okuma" yetkisine sahip bir kullanıcı (Müşteri), isteği GET /api/v1/invoices/1056 olarak değiştirir.

Eğer Backend, Object-Level Authorization (Nesne Seviyesi Yetkilendirme) kontrolünü ihmal etmişse veritabanına sadece SELECT * FROM tbl_invoices WHERE id = 1056 sorgusunu atar. ID numarasının (1056) o an istek yapan Session sahibine (Kullanıcı_ID) ait olup olmadığını teyit etmez! Sonuç? Bipolar manipülasyonlarla rakip firmaların tüm fatura verisini otomatize sömüren bir hacker.


2. Gelişmiş BOLA Saldırı Vektörleri

Makalelere konu olan klasik 1,2,3 rakamlarını değiştirme taktiğini modern geliştiriciler biliyor. Ancak saldırganlar her zaman bir adım öndedir. İşte manuel sızma testlerinde (Pentest) yakaladığımız ileri düzey (Advanced) BOLA vektörleri:

A. UUIDv4 Kullanmak Zafiyeti Çözmez (Blind IDOR)

"Sistemi güvenli hale getirdik, artık Auto-Incrementing Integer (1,2,3) yerine karmaşık UUID'ler (a3f1...) kullanıyoruz" demek devasa bir yanılgıdır. Saldırgan UUID'leri tahmin edemeyebilir ama uygulamadaki başka bir endpoint'ten zafiyet zinciriyle o UUID'leri sızdırabilir (Örnek: GET /users/list), daha sonra bu sızan UUID'leri kritik BOLA zafiyeti olan endpointte dener. Buna Security by Obscurity (Gizleyerek Güvenlik) denir ve başarısızlığa mahkumdur.

B. HTTP Parameter Pollution (HPP) ile BOLA

Sistem nesne sahibini kontrol etse bile, zafiyet parametre manipülasyonu ile atlatılabilir. Örneğin saldırgan isteği şöyle gönderir: GET /api/profile?user_id=BenimID&user_id=HedefKurbanID Eğer Backend WAF katmanı sadece ilk ID'yi doğruluyor, ancak veritabanına giden ORM paketi (örn: Prisma veya Sequelize) listeye dönüştürülmüş şekilde son parametreyi referans alıyorsa, savunma baypas edilmiş olur.

C. PUT/POST ile İlişkisel Manipülasyonlar (Mass Assignment/BOLA Mix)

Alışveriş sepetinizi veya ödeme altyapınızı düşünün: Saldırgan POST /checkout işlemi yaparken, faturaya farklı bir firmanın indirim kupon ID'sini veya mağdur bir kullanıcının sepet ID'sini {"cart_id": "890"} manuel olarak yollar. Uygulama Sepet 890'ı sepet olarak işler ve mağdurun sepetindeki ürünleri bedavaya ya da çok ucuza kendi hesabına geçirebilir.


3. Kurşun Geçirmez BOLA (IDOR) Savunma Stratejisi

Zafiyetin tek bir kesin çözümü vardır: Kodunuzun veritabanına dokunduğu her saniye "Sahiplik" (Ownership) testinden geçmesi.

  1. Backend'de Mutlak Filtreleme: user_id bilgisini Asla istemciden (Query Params, Body, Headers) okumayın. Aradığınız ID ne olursa olsun user_id değerini her zaman Sunucu tarafında (Server-side) JWT'nin içerisinden çıkartın ve SQL/ORM sorgunuza AND olarak bağlayın.
    • Yanlış Sorgu: SELECT * FROM invoices WHERE invoice_id = ?
    • Doğru Sorgu (Auth Bound): SELECT * FROM invoices WHERE invoice_id = ? AND owner_user_id = ?(JWT.User)
  2. Access Control Matrix veya Policy Framework: Go için Casbin, Node.js (NestJS) için @casl/ability tarzı policy motorları kullanın. Böylece geliştiricilerin controller metotları içinde tek tek if/else yetki blokları yazmasını engelleyip, kurumsal ve bypass edilemez bir mimari kurarsınız.
  3. Manuel Sızma Testi (DAST Yetmez): Otomatik tarayıcılar (Nessus, Acunetix) sizin uygulamanızın "Fatura Nesnesi Kime Ait" mantığını tasavvur edemez. API'lerinizin BOLA açıklarını bulmak istiyorsanız, siber güvenlik uzmanlarının (Red Team / Pentester) API dökümanınızı (Swagger/Postman) çift yetkili profille satır satır denetlemesi ZORUNLUDUR.

Modern API güvenliğinde en ölümcül hatanın, kullanıcının gönderdiği (Input) parametreye sorgusuz sualsiz güvenmek olduğunu asla unutmayın. Bu güven ortamında test yapmadan Production'a çıkmak istiyorsanız, veri sızıntılarınıza da hazır olmalısınız.