Modern API'lerin Sessiz Katili: BOLA / IDOR Zafiyetleri ve Etkileri
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:
- Authentication (Kimlik Doğrulama): İstek yapan kişinin geçerli bir JWT'si (Oturumu) var mı? Evet.
- 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.
- Backend'de Mutlak Filtreleme:
user_idbilgisini Asla istemciden (Query Params, Body, Headers) okumayın. Aradığınız ID ne olursa olsunuser_iddeğ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)
- Yanlış Sorgu:
- Access Control Matrix veya Policy Framework: Go için
Casbin, Node.js (NestJS) için@casl/abilitytarzı 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. - 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.