Skip to main content

Welcome to a Grasp lesson

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

Lesson 1

Bilinmeyen Kod Tabanı Mimarisi Haritalama

Merhaba, "İleri Seviye Güvenli Kod Analizi" kursumuza hoş geldiniz. Bu yolculukta, SAST ve DAST gibi otomatize araçların ötesine geçerek, bir uzmanın sezgisel ve mantıksal çıkarım yeteneklerini kullanarak kod tabanlarındaki derin güvenlik zafiyetlerini nasıl ortaya çıkaracağını keşfedeceğiz. Amacımız, kodun altında yatan desenleri tanıma, varsayımları sorgulama ve birden çok bulguyu birleştirerek karmaşık istismar zincirleri oluşturma yeteneğinizi keskinleştirmektir.

Bu ilk modül, "Uzman Gözüyle Kod Analizi: Strateji ve Mimari", büyük ve yabancı bir kod tabanına yaklaşırken nasıl bir strateji izleyeceğimizi ele alacak. Bu ilk dersimizde, herhangi bir derinlemesine analizden önce yapılması gereken en temel adımı öğreneceğiz: bilinmeyen bir kod tabanının mimarisini, routing tanımlarını, middleware zincirlerini ve konfigürasyon dosyalarını analiz ederek haritalamak. DevSecOps ve güvenli mimari tasarımı alanındaki tecrübeniz, bir uygulamanın nasıl yapılandırılması gerektiği konusunda size sağlam bir temel sunuyor. Bu derste ise bu süreci tersine çevirecek ve mevcut koddan mimariyi nasıl "kurtaracağımızı" ve bu haritayı güvenlik analizi için nasıl kullanacağımızı göreceğiz.

Stratejik Başlangıç: Yukarıdan Aşağıya Yaklaşım

Büyük bir kod tabanıyla ilk karşılaştığınızda, rastgele dosyalara dalmak yerine, bir şehrin haritasını çıkarmak gibi, önce uygulamanın genel yapısını anlamak en etkili yöntemdir. Bu yukarıdan aşağıya (top-down) yaklaşım, analizinizi yönlendirecek ve çabalarınızı en kritik alanlara odaklamanızı sağlayacaktır. Bu mimari haritayı oluşturmanın üç temel direği vardır: konfigürasyon dosyaları, routing tanımları ve middleware zincirleri.

1. Konfigürasyon Dosyaları: Uygulamanın DNA'sı

Konfigürasyon dosyaları, bir uygulamanın çalışma zamanı iskeletini ve dış dünya ile olan ilişkilerini tanımlar. Veritabanı bağlantılarından harici servislere, güvenlik ayarlarından özellik bayraklarına (feature flags) kadar her şeyi içerirler. Bu dosyalar, uygulamanın güven sınırlarının nerede çizildiğini anlamak için paha biçilmez bir başlangıç noktasıdır.

Aranacak tipik dosyalar ve bilgiler şunlardır:

  • Spring Boot (Java): application.properties veya application.yml. Bu dosyalarda veritabanı bağlantı dizeleri (spring.datasource.url), harici API endpoint'leri, ve Spring Security gibi modüllerin temel yapılandırmaları bulunur. Örneğin, server.servlet.session.cookie.secure=true gibi bir ayarın varlığı veya yokluğu anında bir güvenlik kontrol noktası sunar.
  • Django (Python): settings.py. Veritabanı yapılandırması (DATABASES), kurulu uygulamalar (INSTALLED_APPS), ve özellikle güvenlik için kritik olan middleware listesi (MIDDLEWARE) burada yer alır.
  • Express.js (Node.js): Genellikle .env dosyaları ve bu dosyalardan değerleri çeken config.js gibi modüller. process.env aracılığıyla erişilen bu değişkenler, veritabanı parolaları, JWT sırları ve diğer hassas bilgileri içerir.
  • ASP.NET Core (C#): appsettings.json ve ortama özel varyantları (appsettings.Development.json). ConnectionStrings, Logging ve özel uygulama ayarları bu dosyalarda bulunur.

Bu dosyaları analiz ederek, uygulamanın hangi veritabanlarına, hangi mesaj kuyruklarına veya hangi üçüncü parti API'lere (örneğin, bir ödeme ağ geçidi) bağlandığını hızlıca tespit edebiliriz. Bu, uygulamanın dış güven sınırlarını ve potansiyel veri çıkış noktalarını belirlemenin ilk adımıdır.

2. Routing Tanımları: Uygulamanın Giriş Kapıları

Uygulamanın genel yapısını anladıktan sonra, saldırı yüzeyini oluşturan herkese açık giriş noktalarını (entry points) bulmamız gerekir. Routing tanımları, HTTP isteklerini (URL'ler ve metotlar) bu istekleri işleyecek olan kod parçacıklarına (genellikle Controller sınıfları) eşler.

Bu tanımları bulma yöntemleri, kullanılan framework'e göre değişir:

  • Annotation/Attribute Tabanlı (Spring Boot, ASP.NET Core):

    • Spring Boot: @RestController veya @Controller ile etiketlenmiş sınıfları arayın. Bu sınıfların içindeki @GetMapping, @PostMapping, @RequestMapping gibi annotation'lar, URL yollarını ve kabul edilen HTTP metotlarını doğrudan gösterir.
    • ASP.NET Core: [ApiController] ve [Route] attribute'ları ile işaretlenmiş Controller sınıfları ve içlerindeki [HttpGet], [HttpPost] gibi attribute'lar incelenmelidir.
  • Kod Tabanlı/Declarative (Django, Express.js):

    • Django: Projedeki urls.py dosyaları merkezi bir rol oynar. Ana urls.py dosyası genellikle include() fonksiyonu ile diğer uygulamaların urls.py dosyalarına dallanır ve hiyerarşik bir URL ağacı oluşturur.
    • Express.js: app.get(...), app.post(...) veya app.use('/api', router) gibi ifadeler, route'ların nasıl tanımlandığını gösterir. app.use ile bağlanan router nesnelerini takip ederek tüm endpoint haritasını çıkarabilirsiniz.

Bu analizin sonunda, GET /api/users/{id}, POST /api/orders gibi tüm erişilebilir endpoint'lerin bir listesine sahip olmalısınız. Bu liste, kod analizindeki önceliklendirmeniz için temel bir çerçeve sunar.

Aşağıdaki görsel, tipik bir Spring Boot projesinin dizin yapısını göstermektedir. controller paketi, az önce bahsettiğimiz routing tanımlarının bulunduğu yerdir. config paketi ise genellikle konfigürasyon sınıflarını içerir.

Bu görsel, bir Spring Boot projesindeki `controller`, `service`, `repository` ve `config` gibi standart paketlerin amacını ve birbirleriyle olan ilişkisini özetlemektedir. Analize başlarken bu yapı, aradığınız bileşenleri nerede bulacağınıza dair size bir yol haritası sunar.

3. Middleware Zincirleri: Kapıdaki Nöbetçiler

Middleware (veya Spring'deki adıyla Filter), bir isteğin asıl iş mantığına (controller'a) ulaşmasından önce veya bir yanıtın istemciye gönderilmesinden hemen önce araya giren kod parçacıklarıdır. Kimlik doğrulama, yetkilendirme, loglama, rate limiting ve gelen verinin ön doğrulaması gibi kritik güvenlik fonksiyonları neredeyse her zaman middleware katmanında uygulanır.

Bu şema, middleware katmanının istemci (Client) ile uygulamanın iş mantığı (Process) arasında nasıl bir aracı görevi gördüğünü göstermektedir. Gelen istekler, bu katmandaki çeşitli bileşenlerden (örn. kimlik doğrulama, oturum yönetimi) geçerek işlenir.

Bir middleware zincirinin analizi, sadece hangi kontrollerin yapıldığını değil, aynı zamanda hangi sırayla yapıldığını da anlamayı gerektirir. Sıralamadaki bir hata, bir güvenlik kontrolünün tamamen atlanmasına neden olabilir.

  • Spring Security: Modern Spring Boot uygulamalarında, SecurityFilterChain tipinde bir @Bean olarak tanımlanır. Bu zincir, http.addFilterBefore() veya http.authorizeHttpRequests() gibi metotlarla yapılandırılır. Filtrelerin sırası, bir kimlik doğrulama filtresinin bir CSRF filtresinden önce mi sonra mı çalıştığı gibi kritik detayları ortaya koyar.
  • Django: settings.py dosyasındaki MIDDLEWARE listesi, middleware'lerin uygulanma sırasını net bir şekilde belirtir. Listenin başındaki middleware'ler isteği ilk karşılar, sonundakiler ise yanıtta en son çalışır.
  • Express.js: Middleware'ler app.use() ile uygulandıkları sırayla çalışır. app.use(authMiddleware) ifadesi, kendisinden sonra tanımlanan tüm route'lar için bu middleware'i etkinleştirir. Route'a özel middleware'ler ise app.get('/admin', adminOnlyMiddleware, ...) şeklinde doğrudan belirtilebilir.

Middleware analizi sırasında sormanız gereken kilit sorular şunlardır:

  • Hassas endpoint'lere erişimden önce kimlik doğrulama ve yetkilendirme middleware'leri çalışıyor mu?
  • Tüm endpoint'ler için CSRF koruması veya temel güvenlik başlıkları (security headers) gibi genel güvenlik önlemleri uygulanıyor mu?
  • Veri doğrulama (validation) middleware'i, potansiyel olarak tehlikeli verinin iş mantığına ulaşmasından önce mi çalışıyor?

Haritayı Birleştirmek: Pratik Bir Örnek

Bu üç unsuru birleştirdiğimizde, uygulamanın güvenlik duruşuna dair bütüncül bir resim ortaya çıkar. Örneğin, bir Spring Boot e-ticaret uygulamasını inceliyorsunuz:

  1. Konfigürasyon (application.yml): PostgreSQL veritabanı bağlantısı ve bir üçüncü parti kargo API'si için cargo.api.url adında bir URL görüyorsunuz. Bu, iki önemli dış entegrasyonu işaret eder.
  2. Routing (OrderController.java): @PostMapping("/orders") ile eşleşen bir createOrder metodu buluyorsunuz. Bu, yeni sipariş oluşturmak için kullanılan birincil giriş noktasıdır.
  3. Middleware (SecurityConfig.java): Bir SecurityFilterChain bean'i, /orders/** yoluna erişim için hasRole('USER') kuralını uygulayan bir yetkilendirme filtresi tanımlıyor.

Bu üç bilgiyi birleştirerek şu sonuca varırsınız: Bir sipariş oluşturmak için (POST /orders), kullanıcının kimliğini doğrulamış ve USER rolüne sahip olması gerekir. Bu işlem, PostgreSQL veritabanı ile etkileşime girecek ve potansiyel olarak kargo API'sine bir istek gönderecektir. Bu basit harita, olası bir IDOR zafiyetini (kullanıcı başkasının siparişini etkileyebilir mi?), SSRF riskini (kargo API'sine yapılan istek manipüle edilebilir mi?) veya iş mantığı hatalarını (sipariş durumu nasıl yönetiliyor?) araştırmak için nereye odaklanmanız gerektiğini size net bir şekilde söyler.


Sonuç

Bu derste, bilinmeyen bir kod tabanını analiz etmeye yönelik stratejik ve yapılandırılmış bir yaklaşım olan "mimari haritalama" tekniğini öğrendik. Bu sürecin üç temel direği olan konfigürasyon dosyaları, routing tanımları ve middleware zincirleri'nin nasıl analiz edileceğini inceledik. Bu yukarıdan aşağıya yaklaşım, rastgele kod okumak yerine, çabalarınızı doğrudan uygulamanın saldırı yüzeyine ve kritik güvenlik kontrollerinin uygulandığı noktalara yönlendirmenizi sağlar.

Temel Çıkarımlar:

  • Kod analizine her zaman uygulamanın mimarisini anlayarak başlayın.
  • Konfigürasyon dosyaları uygulamanın dış dünya ile olan ilişkilerini ve temel ayarlarını ortaya koyar.
  • Routing tanımları uygulamanın herkese açık giriş noktalarını (saldırı yüzeyini) belirler.
  • Middleware zincirleri kimlik doğrulama ve yetkilendirme gibi temel güvenlik kontrollerinin nerede ve nasıl uygulandığını gösterir.

Gelecek derste, bu mimari haritayı elimize aldıktan sonraki adımı atacağız. Kodun derinliklerine dalmak için hangi stratejinin daha uygun olduğuna karar vereceğiz. Çağrı grafi (call-graph) ve veri akışı (data-flow) odaklı kod analizi stratejilerini karşılaştırarak hedef kod tabanına en uygun yaklaşımı nasıl seçeceğimizi öğreneceğiz.