Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 56

REST API'lerde BOLA Zafiyetlerini Tespit Etme

Recommended resources

Merhaba! Bir önceki dersimizde GraphQL'in esnek dünyasına dalarak resolver fonksiyonlarındaki yetkilendirme mantığı atlatma ve N+1 sorgu problemlerini kod seviyesinde nasıl tespit edeceğimizi inceledik. Bir nesneye erişen her kod yolunun, nesnenin sahibini ve isteği yapan kullanıcının kimliğini doğrulaması gerektiği prensibini temel aldık.

Bu dersimizde, API güvenliğinin en yaygın ve kritik zafiyetlerinden birine, modern API'lerin Aşil topuğuna odaklanacağız. Konumuz, OWASP API Security Top 10 listesinin ilk sırasında yer alan Kırık Nesne Seviyesinde Yetkilendirme (Broken Object Level Authorization - BOLA). Bu dersin amacı, REST API endpoint'lerinde karmaşık sahiplik kontrolleri ve serializer konfigürasyonları üzerinden BOLA zafiyetlerini tespit etmektir. GraphQL'de gördüğümüz nesne seviyesi yetkilendirme kavramını, RESTful API'lerin daha yapısal ve kaynak odaklı dünyasına taşıyarak, farklı API paradigmalarında aynı temel güvenlik ilkesinin nasıl hayati önem taşıdığını kod denetimi perspektifinden analiz edeceğiz.

API1:2023 - Kırık Nesne Seviyesinde Yetkilendirme (BOLA)

BOLA, bir kullanıcının, erişim yetkisi olmaması gereken nesnelere (verilere) erişebilmesi, onları değiştirebilmesi veya silebilmesi durumunda ortaya çıkar. Genellikle IDOR (Insecure Direct Object Reference) olarak da bilinen bu zafiyet, API'nin, bir nesneye erişim isteği aldığında, isteği yapan kullanıcının o nesnenin gerçek sahibi olup olmadığını doğrulamayı unutması veya yanlış doğrulaması sonucu oluşur.

API güvenliği üzerine yazılmış bu blog yazısı, konuya harika bir giriş yapıyor.

API Sızma Testi: Kimlikli Akışlar ve İş Mantığı | SİTEY Blog

Bu kaynak, BOLA'nın ne olduğunu OWASP API Security Top 10 bağlamında tanımlıyor ve REST API'lerin yapısal özelliklerinin bu zafiyeti nasıl kolaylaştırdığını açıklıyor.

Lütfen önce Özet Anlatım bölümünü okuyarak temel konsepti anlayın. Ardından, API Güvenlik Standartları başlığı altındaki API1:2023 - BOLA tanımını dikkatle inceleyin. Son olarak, sayfanın alt kısmındaki REST API Güvenlik Riskleri başlığı altında, REST API'lerin yapısının IDOR saldırılarını neden kolaylaştırdığına dair açıklamayı okuyun.

Okuduğunuz gibi, REST'in /resources/{id} şeklindeki kaynak odaklı yapısı, saldırgan için potansiyel hedefleri çok bariz hale getirir. Aşağıdaki diyagram, bu durumu mükemmel bir şekilde özetlemektedir.

Bu şemada, "Giriş yapmış kullanıcı" (Logged in user), `GET /api/users/sensitive-info` gibi bir istekle kendi verisine (Verified User) doğru bir şekilde erişirken; "Kötü niyetli varlık" (Malicious entity), normalde erişememesi gereken bir kaynağa (`/api/admin/sensitive-info` veya başka bir kullanıcının ID'si ile) istek göndererek yetkilendirme kontrolünü atlatır ve veriye (Unverified User) ulaşır.

Kod Gözünden Klasik BOLA/IDOR Tespiti

En temel BOLA zafiyeti, tahmin edilebilir (genellikle sıralı artan) ID'ler kullanan GET endpoint'lerinde bulunur. Saldırgan, /orders/101 olan kendi sipariş ID'sini /orders/102, /orders/103 olarak değiştirerek başkalarının siparişlerini okumayı dener.

Bu zafiyetin pratikte nasıl sömürüldüğünü görmek için aşağıdaki videoyu izleyebilirsiniz. Bir siber güvenlik uzmanının, Burp Suite kullanarak bir mesajlaşma uygulamasındaki mesaj ID'sini değiştirerek diğer kullanıcıların özel mesajlarını nasıl okuduğunu göreceksiniz.

Burp Suite + IDOR: Kullanıcı Verilerini Nasıl Aldık!

Bu video, basit bir IDOR zafiyetinin nasıl tespit edildiğini ve istismar edildiğini adım adım gösteriyor.

Videoda bu bölümü izleyin. Analistin, kendi mesajının ID'sini (5) fark ettikten sonra, bu değeri değiştirerek (1, 2, 3...) diğer kullanıcıların, hatta bir sistem yöneticisinin hassas mesajlarına (bir SSH parolası dahil) nasıl eriştiğine dikkat edin.

Kod Denetimi Perspektifi:

Bu zafiyet, kodda genellikle tek bir eksik satır olarak kendini gösterir. Bir Django (Python) uygulamasında bu zafiyet şöyle görünebilir:




# GÜVENSİZ KOD
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Order

class OrderDetailView(APIView):
    def get(self, request, order_id):



        # 1. Adım: Nesne, kullanıcı girdisiyle (order_id) veritabanından alınır.
        try:
            order = Order.objects.get(id=order_id)
        except Order.DoesNotExist:
            return Response(status=404)
        



        # 2. Adım: Nesne doğrudan kullanıcıya döndürülür.
        # EKSİK OLAN KONTROL: Bu sipariş, isteği yapan kullanıcıya mı ait?
        # if order.customer_id != request.user.id:
        #     return Response(status=403) # Forbidden
        
        serializer = OrderSerializer(order)
        return Response(serializer.data)

Güvenli kod, nesneyi veritabanından çektikten hemen sonra, o nesnenin sahiplik ilişkisini (order.customer_id), isteği yapan kullanıcının kimliğiyle (request.user.id) karşılaştırmalıdır. Kod denetçisi olarak göreviniz tam da bu eksik if bloğunu aramaktır.


Sadece Okumak Değil: Yazma ve Değiştirme Yoluyla BOLA

BOLA, GET istekleriyle sınırlı değildir. POST, PUT ve DELETE gibi veri değiştiren metotlarda ortaya çıktığında çok daha yıkıcı olabilir. Saldırgan, başkasının verisini okumakla kalmaz, değiştirebilir veya silebilir.

"Pentest Günlükleri" adlı bu kaynak, gerçek dünyadan birçok IDOR vakası içermektedir. "Candostum IDOR" başlıklı vaka, bu durumu mükemmel bir şekilde örnekliyor.

PENTEST GÜNLÜKERİ

Bu vaka çalışması, bir profil güncelleme API'sindeki user_id parametresinin manipüle edilmesiyle başka bir kullanıcının e-posta adresinin nasıl değiştirildiğini ve bunun sonucunda hesabın tamamen nasıl ele geçirildiğini (account takeover) anlatıyor.

Lütfen "Candostum IDOR" başlıklı 40. günlüğü okuyun. Pentester'ın, profil güncelleme isteğindeki user_id değerini başka bir test kullanıcısının ID'si ile değiştirerek, yetkisi olmayan bir hesabın e-postasını güncellediğini ve ardından şifre sıfırlama mekanizmasıyla hesabı nasıl ele geçirdiğine odaklanın.

Kod Denetimi Perspektifi:

Bu tür bir zafiyet genellikle Mass Assignment (Toplu Atama) adı verilen bir programlama hatasından kaynaklanır. Geliştirici, API isteğinin gövdesinden (body) gelen tüm veriyi, hiçbir filtreleme yapmadan doğrudan veritabanı modeline veya nesnesine uygular.

Örneğin bir Node.js/Express uygulamasında:

// GÜVENSİZ KOD - Mass Assignment
app.put('/api/users/:id', async (req, res) => {
    // Kullanıcının kendi profilini güncellediğini varsayalım.
    // Ancak request body'de gelen veriyi filtrelemiyoruz.
    const userToUpdate = await User.findByPk(req.params.id);

    // EĞER req.body = { "email": "hacker@evil.com", "role": "admin" } ise
    // bu değişiklikler doğrudan uygulanır!
    await userToUpdate.update(req.body); 

    res.json(userToUpdate);
});

Saldırgan, normalde kullanıcı arayüzünde bulunmayan role: "admin" gibi bir alanı isteğe ekleyerek yetkisini yükseltebilir. Okuduğunuz vakadaki gibi, user_id alanının PUT veya POST isteğinin gövdesinde gönderilmesine izin verilmesi ve sunucu tarafında bu alanın göz ardı edilmemesi, bir kullanıcının başka bir kullanıcının verilerini değiştirmesine olanak tanır.

Güvenli Kod Pratiği:

  1. Whitelist Yaklaşımı: Sadece güncellenmesine izin verilen alanları açıkça belirleyin (email, first_name, last_name gibi). role, is_admin, user_id gibi hassas alanları asla istemciden gelen veriye göre güncellemeyin.
  2. Read-only Alanlar: Modern framework'lerdeki serializer'lar, belirli alanları "read-only" (salt okunur) olarak işaretleme imkanı sunar. user_id veya role gibi alanlar bu şekilde korunmalıdır.
  3. İşlemi Kullanıcı Bağlamında Yapmak: Bir nesneyi güncellemek için ID'yi URL'den alın, ancak güncellenecek veriyi asla kullanıcıdan gelen user_id'ye göre belirlemeyin. Her zaman oturumdaki kullanıcının kimliğini (request.user) temel alın.

Karmaşık Sahiplik ve İş Mantığı Hataları

En sofistike BOLA zafiyetleri, basit ID kontrollerinin ötesinde, uygulamanın iş mantığına gömülüdür. Bu zafiyetler, nesneler arasında dolaylı ilişkiler veya karmaşık yetkilendirme kuralları olduğunda ortaya çıkar.

"Pentest Günlükleri"ndeki bir başka vaka, bu tür bir mantık hatasını gözler önüne seriyor.

PENTEST GÜNLÜKERİ

Bu vaka, kurumsal bir portaldaki "vekalet verme" özelliğindeki bir mantık hatasının nasıl istismar edildiğini anlatıyor. Saldırgan, önce basit bir IDOR ile personel listesini elde ediyor, ardından vekalet verme isteğindeki kaynak kullanıcı ID'sini manipüle ederek başkası adına vekalet veriyor ve sonuçta hesabı ele geçiriyor.

"Vekilin Demek Sen Demek" başlıklı 65. günlüğü dikkatle okuyun. Zafiyetin tek bir satırda değil, birden fazla adım ve özelliğin birleşiminden nasıl doğduğuna odaklanın.

Kod Denetimi Perspektifi:

Bu tür karmaşık BOLA'ları bulmak, sadece tek bir fonksiyonu değil, tüm iş akışını anlamayı gerektirir. Kod denetçisi olarak sormanız gereken sorular şunlardır:

  • Bu işlem (create_delegation) hangi aktörleri içeriyor? (Vekaleti veren, vekaleti alan, işlemi başlatan)
  • Kod, işlemi başlatan kullanıcının (request.user), vekaleti veren kullanıcı (from_user_id) adına hareket etme yetkisi olup olmadığını kontrol ediyor mu?
  • Kod, dolaylı nesne referanslarını (örneğin, bir şirkete ait kullanıcıları listeleme) kontrol ederken, isteği yapan kullanıcının o şirketi görme yetkisi olup olmadığını doğruluyor mu?

Bu senaryoda zafiyet, create_delegation(from_user, to_user) fonksiyonunun, sadece from_user ve to_user'ın var olup olmadığına bakması, ancak bu işlemi tetikleyen request.user'ın from_user ile aynı kişi olup olmadığını (veya onun yöneticisi olup olmadığını) kontrol etmeyi unutmasından kaynaklanır.


Sonuç ve Sonraki Adımlar

Bu derste, REST API'lerdeki en kritik zafiyetlerden biri olan BOLA'yı derinlemesine inceledik. Basit ID manipülasyonlarından karmaşık iş mantığı hatalarına kadar bu zafiyetin farklı yüzlerini gördük ve bunları kod seviyesinde nasıl tespit edebileceğimize odaklandık.

Anahtar Çıkarımlar:

  • BOLA Evrenseldir: Herhangi bir nesneye ID ile erişen veya onu değiştiren her API endpoint'i potansiyel bir BOLA adayıdır.
  • Yetkilendirme Sunucuda Olmalıdır: GET, POST, PUT, DELETE fark etmeksizin, bir nesne üzerinde işlem yapılmadan önce, isteği yapan kullanıcının o nesne üzerindeki sahiplik veya yetki ilişkisi sunucu tarafında doğrulanmalıdır.
  • Mass Assignment Tehlikelidir: İstemciden gelen veriyi körü körüne veritabanı nesnelerine uygulamak, yetki yükseltme ve BOLA zafiyetlerine davetiye çıkarır. Serializer konfigürasyonları ve veri modelleme kritik öneme sahiptir.
  • Bağlam Her Şeydir: Özellikle karmaşık iş akışlarında, kod denetçisinin görevi "Bu işlemi kimin adına yapıyorsun ve buna yetkin var mı?" sorusunu sormaktır.

Bir sonraki ve son dersimizde, bu kursta öğrendiğimiz tüm teknikleri bir araya getireceğiz. "Bulguları Birleştirme: Varyant Analizi ve İstismar Zinciri" başlıklı dersimizde, tek bir zafiyet bulgusundan yola çıkarak bu zafiyetin kök nedenini soyutlamayı (varyant analizi), kod tabanındaki diğer benzerlerini bulmayı ve farklı zafiyetleri birleştirerek nasıl daha büyük etkili istismar senaryoları (exploit chain) oluşturabileceğimizi ele alacağız. Bu ders, edindiğiniz "uzman gözünü" en üst seviyeye taşımanıza yardımcı olacak.