Merhaba, bir önceki dersimizde bir kod tabanındaki en kritik iki noktayı, yani verinin sisteme girdiği giriş noktalarını (entry points) ve potansiyel olarak zafiyete yol açtığı tehlikeli hedefleri (sinks) nasıl sistematik olarak bulacağımızı öğrenmiştik. Bu, tek bir uygulama bileşeni içindeki veri akışının başlangıcını ve sonunu haritalamak için temel bir adımdı.
Bu derste ise merceğimizi genişletiyor ve modern dağıtık mimarilerin kalbine, yani mikroservisler arasındaki etkileşime odaklanıyoruz. Monolitik uygulamaların aksine, mikroservis mimarileri, genellikle birbirlerine körü körüne güvenen düzinelerce küçük servisten oluşur. İşte bu örtük güven ilişkileri (implicit trust relationships), deneyimli bir güvenlik analistinin en verimli av sahalarından biridir. Bu dersteki amacımız, bu örtük güveni analiz ederek geliştiricilerin farkında olmadan bıraktığı istismar edilebilir varsayımları kod seviyesinde nasıl ortaya çıkaracağımızı öğrenmek. Bu, önceki derste öğrendiğimiz "giriş noktası/hedef" analizini bir üst seviyeye taşıyarak servisler arası veri akışını anlamamızı sağlayacak.
Monolitten Mikroservise: Güvenin Dağılması
Geleneksel monolitik mimarilerde, güvenlik modeli genellikle daha basittir: güçlü bir dış çevre (perimeter) ve büyük ölçüde güvenilir bir iç dünya. Bir fonksiyonun başka bir fonksiyonu çağırması genellikle bir ağ atlaması içermez ve aynı süreç (process) içinde gerçekleşir.
Mikroservisler ise bu modeli tamamen değiştirir. Artık neredeyse her fonksiyon çağrısı bir ağ çağrısıdır (HTTP/gRPC). Bu, saldırı yüzeyini dramatik bir şekilde genişletir. Servisler arası bu "doğu-batı" (east-west) trafiği, genellikle dışarıya dönük "kuzey-güney" (north-south) trafiğinden daha az denetlenir. Geliştiriciler, "nasılsa bu servise sadece başka bir internal servis erişebilir" varsayımıyla hareket etme eğilimindedir. Bu varsayım, "güvenilir alt sistem" (trusted subsystem) anti-desenini doğurur ve bizim kod analizinde hedef alacağımız temel zayıflıktır.
Aşağıdaki diyagram, bu durumu mükemmel bir şekilde özetlemektedir:

Dahili Servisler Arasındaki İstismar Edilebilir Varsayımlar
Kod analizi yaparken, geliştiricilerin bu servisler arası iletişimde bıraktığı varsayımları ararız. İşte en yaygın olanlardan birkaçı:
- "Beni çağıran servis, söylediği kişidir.": Bir servis (
Service-B), başka bir servisten (Service-A) gelen isteğin gerçektenService-A'dan geldiğini doğrulamadan kabul edebilir. Ağ içinde olduğunu varsayarak kimlik doğrulama adımını atlar. Pentest ve kırmızı takım tecrübelerinizden bildiğiniz gibi, bir kere ağın içine sızıldığında bu tür güven ilişkileri yanal hareket (lateral movement) için bir otoban görevi görür. - "Akran servisten gelen veri zaten doğrulanmıştır.": Bu en tehlikeli varsayımlardan biridir. Dış dünyaya açık olan
Service-A, kullanıcıdan gelen girdiyi alır ve bir miktar doğrulama yapar. Daha sonra bu veriyi bir iç servis olanService-B'ye iletir.Service-B, verininService-Agibi "güvenilir" bir kaynaktan geldiğini varsayarak hiçbir ek doğrulama yapmadan doğrudan tehlikeli birsinkiçinde kullanır (örneğin, bir veritabanı sorgusuna ekler veya bir dosya yolunu oluşturur). - "Dahili API endpoint'leri dışarıdan erişilemez.": Geliştiriciler genellikle hata ayıklama, yönetim veya servisler arası özel işlevler için yalnızca dahili kullanım amaçlı API endpoint'leri oluşturur.
Service-A'daki bir SSRF veya path-traversal zafiyeti, saldırganın bu "gizli" dahili endpoint'lere ulaşmasını sağlayabilir. Bu endpoint'ler genellikle daha zayıf yetkilendirme kontrollerine sahip olduğundan, sonuçları kritik olabilir.
Bu varsayımların nasıl istismar edildiğini ve kodda nasıl tespit edileceğini anlamak için GitHub'daki şu kaynağı inceleyelim.
websec101/18.md at main - GitHub
Bu doküman, mikroservis ortamlarında yanal hareketin temellerini ve saldırganların bu mimarileri nasıl hedef aldığını özetliyor. Okurken, bu saldırı vektörlerinin temelinde yatan "örtük güven" varsayımlarını düşünün.
İlk olarak, Tanım ve Kapsam bölümünü okuyarak konsepti anlayın. Ardından, Lateral Movement Teknikleri bölümünü inceleyin. Bu bölüm, API zafiyetleri ve token sızdırma gibi, servisler arasındaki güvenin nasıl kötüye kullanılabileceğine dair somut örnekler sunar. Saldırı senaryosu bölümü, bir SQL enjeksiyonu ile başlayan bir saldırının, servis keşfi ve yanal hareket ile nasıl yetki yükseltmeye kadar gidebileceğini gösterir. Bu senaryo, tek bir zafiyetin tüm sistemi nasıl tehlikeye atabileceğinin pratik bir kanıtıdır. Son olarak, Çözümler ve En İyi Uygulamalar bölümüne göz atın. Bu bölüm, kodda arayacağımız güvenli desenlerin (Zero Trust, API Güvenliği, Least Privilege) ne olduğunu anlamamıza yardımcı olacaktır.
Kod İncelemesinde Pratik Analiz Teknikleri
Peki, bu istismar edilebilir varsayımları kod seviyesinde nasıl buluruz?
1. Kimlik Yayılımını (Identity Propagation) İzleme
Bir kullanıcının kimliği, servis zinciri boyunca nasıl taşınıyor? Bu, en kritik sorulardan biridir.
-
JWT'yi Olduğu Gibi Aktarmak: En yaygın ama tehlikeli yöntemlerden biri, kullanıcıdan alınan orijinal JWT'nin sonraki tüm servislere olduğu gibi aktarılmasıdır. Bu durumda, zincirdeki her bir servisin bu token'ın imzasını, süresini (expiry), ve taleplerini (claims) yeniden doğrulaması gerekir.
- Kod İnceleme Görevi: JWT alan bir servis bulun. Token'ı sadece
jwt.decode()gibi bir fonksiyonla açıp içindekiuser_id'yi mi kullanıyor, yoksajwt.verify()gibi bir fonksiyonla imzayı ve diğer talepleri doğruluyor mu?
- Kod İnceleme Görevi: JWT alan bir servis bulun. Token'ı sadece
-
Token Değişimi (Token Exchange / STS): Daha güvenli bir model, bir "Security Token Service" (STS) veya API Gateway kullanmaktır. Bu bileşen, kullanıcıdan gelen harici (external) token'ı doğrular ve bu token karşılığında, daha kısıtlı yetkilere (
scopes) sahip, kısa ömürlü bir dahili (internal) token üretir. Sonraki servisler bu dahili token ile iletişim kurar.
* **Kod İnceleme Görevi:** STS'nin veya token üreten servisin kodunu analiz edin. Harici token'daki yetkileri dahili yetkilere doğru bir şekilde haritalıyor mu? Bir saldırgan, harici token'a ekleyeceği sahte bir `scope` ile dahili token'da fazladan yetki elde edebilir mi?
2. Parametre Enjeksiyonu ve Kirliliği Avı
Burası sizin saldırgan bakış açınızın en çok parlayacağı yerdir. Servisler birbirlerini çağırırken genellikle gelen isteğin parametrelerini alıp kendi yapacakları isteğe eklerler. Bu noktada "Server-Side Parameter Pollution" (SSPP) ve benzeri enjeksiyon teknikleri devreye girer.
Aşağıdaki video, bu tür API saldırılarının kodda nasıl göründüğünü ve bir proxy servis üzerinden dahili servislerin nasıl manipüle edilebileceğini canlı örneklerle gösteriyor.
Web Security 0x26 | Kanlı-Canlı API Security ve Hacking
Bu videoda Mehmet İnce, API güvenliği üzerine konuşurken mikroservis mimarilerindeki zafiyetleri pratik olarak açıklıyor. Anlatılan senaryolar, kod incelemesi sırasında aramanız gereken desenler için harika birer rehber niteliğindedir.
İlk olarak, bu bölümü izleyin. Burada, dışarıdan gelen bir username parametresinin, bir ara servis tarafından alınıp bir internal servise nasıl iletildiği anlatılıyor. Sunucu, bu aradaki servisin, kullanıcıdan gelen parametreleri körü körüne iç servise aktarması durumunda path traversal (../) veya "hidden field" enjeksiyonu ile iç API'nin beklenmedik metotlarının nasıl çağrılabileceğini açıklıyor. Bu, "gelen veri doğrulanmıştır" varsayımının istismarının en net örneğidir. Ardından, SSPP bölümüne atlayın. "Server-Side Parameter Pollution" konsepti, bir isteğe aynı isimde birden fazla parametre eklenerek arka uç sistemlerinin farklı yorumlamasının sağlanmasıdır. Videoda, bir şifre sıfırlama akışında, iç servise giden isteğin URL'ine ek parametreler enjekte ederek (fields=...) normalde dönmemesi gereken reset_token gibi hassas bilgilerin nasıl sızdırılabileceği canlı olarak gösteriliyor. Son olarak, bu örnekte ise bir ürünün fiyatının, bir ara servis üzerinden manipüle edilmesi gösteriliyor. Saldırgan, ürün ID'sini içeren path'e müdahale ederek (/api/products/1/price yerine /api/products/1/../admin/price_update) ve isteğin gövdesine yeni parametreler ekleyerek iç servisin fiyat güncelleme mantığını tetikliyor. Bu, path traversal ve parametre enjeksiyonunun birleşimiyle iş mantığının nasıl atlatılabileceğini gösteren ileri seviye bir örnektir.
Kod İnceleme Görevi: Servisler arası HTTP isteği oluşturan kod bloklarını (HttpClient, requests.post, fetch vb.) bulun. Giden isteğin URL'i, query parametreleri veya gövdesi, gelen kullanıcı isteğinden alınan verilerle mi oluşturuluyor? Aradaki servis, gelen veriyi olduğu gibi mi aktarıyor, yoksa sadece beklediği alanları alıp yeniden mi oluşturuyor (allow-listing)? İkinci yöntem çok daha güvenlidir.
3. Vaka Analizi: Dağıtık Akışlarda Güvenin Kırılması (OAuth 2.0)
OAuth 2.0, servisler arası karmaşık ve dağıtık güven ilişkilerine mükemmel bir örnektir. Bu akışta en az üç taraf vardır: sizin uygulamanız (Client Application), kullanıcı (Resource Owner) ve kimlik sağlayıcı (Authorization Server, örn: Google, Facebook). Bu partiler arasındaki iletişimde yapılan en küçük bir varsayım hatası, hesap ele geçirmeyle sonuçlanabilir.
Aşağıdaki video, OAuth implementasyonlarındaki bu tür hataları pratik laboratuvar ortamında inceliyor.
Web Security 0x1A | OAuth Zafiyetleri
Bu videoda Mehmet İnce, PortSwigger laboratuvarları üzerinden OAuth 2.0 akışlarındaki yaygın zafiyetleri çözüyor. Bu zafiyetler, farklı servislerin birbirleriyle iletişim kurarken yaptıkları güven varsayımlarının nasıl istismar edilebileceğini gösteriyor.
İlk olarak bu bölümü izleyin. Burada, kimlik sağlayıcıda (provider) kimlik doğrulama başarılı olduktan sonra, sağlayıcının kullanıcının profil bilgilerini (e-posta vb.) istemci uygulamasına bir POST isteği ile gönderdiği bir akış inceleniyor. Ancak istemci uygulaması, bu bilgilerin gerçekten sağlayıcıdan gelip gelmediğini kriptografik olarak doğrulamak yerine, gelen POST isteğindeki e-posta adresine körü körüne güveniyor. Saldırgan bu son isteği yakalayıp e-posta adresini değiştirerek başka bir kullanıcının hesabına giriş yapabiliyor. Bu, "verinin kaynağı güvenilirdir" varsayımının klasik bir ihlalidir. Daha da ilginç bir örnek için bu bölümü izleyin. Bu senaryoda, bir kullanıcının sosyal medya hesabını kendi uygulama hesabına bağlaması anlatılıyor. Akışın sonunda, kimlik sağlayıcıdan dönen ve kullanıcıyı uygulamaya yönlendiren URL, bir yetkilendirme kodu (code) içeriyor. Ancak bu son istekte CSRF koruması (state parametresi) bulunmuyor. Saldırgan, kendi sosyal medya hesabıyla başlattığı bu akışın sonundaki URL'i yakalayıp, bu URL'i bir kurbana (örneğin admin kullanıcısına) tıklatıyor. Kurban linke tıkladığında, saldırganın sosyal medya hesabı, kurbanın uygulama hesabına bağlanmış oluyor. Bu, servisler arası bir akışta durum (state) yönetimindeki bir zayıflığın, başka bir kullanıcının kimliği üzerinden eylem yapmaya nasıl olanak tanıdığını gösteren mükemmel bir örnektir.
Kod İnceleme Görevi: Uygulamanızdaki OAuth/OIDC callback endpoint'ini (/auth/callback gibi) inceleyin.
stateparametresini kullanıyor mu? Kullanıyorsa, gelenstatedeğerinin oturumda saklanan değerle eşleştiğini doğruluyor mu?- Kimlik sağlayıcıdan gelen
id_tokenveyaaccess_token'ı doğruluyor mu, yoksa sadece içindeki bilgilere güveniyor mu? - Gelen token'daki
aud(audience) talebinin kendiclient_id'si ile eşleştiğini kontrol ediyor mu? Bu, token'ın başka bir uygulama için üretilip sizin uygulamanızda kullanılmasını engeller.
Sonuç
Bu dersimizde, mikroservis mimarilerinin getirdiği yeni saldırı yüzeyini ve bu mimarilerdeki örtük güven ilişkilerinin nasıl tehlikeli varsayımlara yol açabileceğini gördük. Artık bir kod tabanını incelerken sadece tekil fonksiyonlara değil, servislerin birbirleriyle nasıl konuştuğuna ve bu konuşmalarda hangi güvenlik varsayımlarını yaptığına odaklanmanız gerektiğini biliyorsunuz.
Temel Çıkarımlar:
- Körü Körüne Güven Öldürür: Mikroservis mimarisinde temel prensip "Zero Trust" (Sıfır Güven) olmalıdır. Ağ içinden gelmesi, bir isteği güvenilir yapmaz. Her servis, aldığı her isteği sanki dış dünyadan geliyormuş gibi doğrulamalıdır.
- Varsayımları Avlayın: Kod analizi yaparken sürekli "Bu servis, çağrıldığı diğer servis hakkında ne varsayıyor?" sorusunu sorun. Verinin temizlendiğini mi, arayanın kimliğinin doğru olduğunu mu, yoksa bir parametrenin sadece kendisi tarafından eklendiğini mi varsayıyor?
- Sistem Bütününü Düşünün: Bu tür zafiyetleri bulmak, tek bir kod parçasına bakarak değil, tüm sistemin mimarisini ve servisler arası veri akışını anlayarak mümkündür. Bu, sizin gibi saldırı ve mimari geçmişi olan bir uzman için en büyük avantajdır.
- Kimlik ve Yetkiyi Ayırın: Bir servisin kimliğini doğrulamak (Authentication) yeterli değildir. O servisin istediği işlemi yapmaya yetkisi olup olmadığını da kontrol etmek (Authorization) gerekir. Dahili servisler arası iletişimde bu ikinci adım genellikle atlanır.
Önceki derslerde bir kod tabanının haritasını çıkarmayı, giriş ve çıkış noktalarını bulmayı ve bugün de servisler arası güven ilişkilerini analiz etmeyi öğrendik. Elimizdeki bu bilgilerle, bir sonraki dersimizde devasa bir kod tabanında nereye odaklanacağımıza karar vereceğiz. "Review kapsamını saldırı yüzeyi, kod karmaşıklığı ve değişiklik geçmişine göre önceliklendirmek" başlıklı derste, analiz eforumuzu en riskli bölgelere nasıl yönlendireceğimizi ele alacağız.