Skip to main content

Welcome to a Grasp lesson

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

Lesson 4

Güvenli Kod Keşfi: Giriş Noktaları ve Tehlikeli Hedefler

Recommended resources

Merhaba, önceki dersimizde modern yazılım mimarilerindeki örtük güven sınırlarını ve bu sınırların ihlal edildiği "Confused Deputy" gibi karmaşık zafiyet desenlerini incelemiştik. Bir kod tabanının güvenlik haritasını çıkarırken bu mantıksal sınırları belirlemenin önemini anladık. Artık bu haritadaki en kritik coğrafi özellikleri, yani verinin sisteme girdiği ve potansiyel olarak zarar verdiği somut noktaları tespit etmeye hazırız.

Bu derste, bir önceki derste öğrendiğimiz soyut güven sınırları kavramını ete kemiğe büründüreceğiz. Güvenlik açısından kritik giriş noktalarını (entry points) ve verinin işlendiğinde zafiyete yol açabileceği tehlikeli hedefleri (sinks) sistematik olarak nasıl keşfedeceğimizi öğreneceğiz. Bu beceri, "uzman gözünü" geliştirmenin ve otomatize araçların ötesine geçerek manuel kod analizinin temelini oluşturan en önemli adımlardan biridir. Bu, bir sonraki modülümüz olan "Manuel Veri Akışı ve Taint Analizi" için de sağlam bir zemin hazırlayacaktır.

Giriş Noktaları ve Tehlikeli Hedefler: Veri Akışının Başlangıcı ve Sonu

Güvenli kod analizinin merkezinde, verinin yolculuğunu izleme fikri yatar. Bu yolculuğun iki temel durağı vardır:

  • Giriş Noktası (Entry Point): Güvenilmeyen bir kaynaktan (kullanıcı, harici bir servis, dosya sistemi vb.) gelen verinin, analiz ettiğimiz kod bileşenine ilk girdiği yerdir. Burası, verinin "kirli" veya "tainted" olarak kabul edildiği başlangıç noktasıdır.
  • Tehlikeli Hedef (Sink): Kirli verinin, bir güvenlik zafiyetini tetikleyebilecek şekilde kullanıldığı bir fonksiyon veya operasyondur. Örneğin bir SQL sorgusunu çalıştıran, bir komutu yürüten veya HTML'i doğrudan sayfaya yazan bir fonksiyon, potansiyel bir tehlikeli hedeftir.

Bir güvenlik açığı, genellikle bir giriş noktasından bir tehlikeli hedefe uzanan ve bu yol üzerinde yeterli doğrulama veya temizleme (sanitization) yapılmayan bir veri akışı yolunun varlığıyla ortaya çıkar.

Bu görsel, bir SAST aracı olan CodeQL'in bulgularını göstermektedir. Burada "source" sütunu giriş noktasını (`req.body`), "sink" sütunu ise tehlikeli hedefi (dinamik bir SQL sorgusu) temsil eder. Analiz, bu ikisi arasında bir veri akışı yolu tespit etmiştir.

Sistematik Keşif Teknikleri

Büyük ve karmaşık bir kod tabanında bu noktaları bulmak, samanlıkta iğne aramaya benzeyebilir. Ancak sistematik yaklaşımlar kullanarak bu süreci yönetilebilir hale getirebiliriz. İki temel strateji vardır:

1. Yukarıdan Aşağıya (Top-Down): Giriş Noktasından Hedefe

Bu yaklaşımda, potansiyel giriş noktalarını bularak başlar ve verinin bu noktalardan itibaren kod içinde nasıl ilerlediğini takip etmeye çalışırız.

Giriş Noktalarını Nasıl Buluruz?

  • Routing Tanımları: Web framework'leri, gelen HTTP isteklerini işleyecek olan kod parçacıklarına (controller, view vb.) yönlendiren merkezi yönlendirme (routing) mekanizmalarına sahiptir. Bu dosyaları incelemek (urls.py - Django, @RestController anotasyonları - Spring, routes/*.js - Express) uygulamanın tüm HTTP tabanlı giriş noktalarını haritalamanın en etkili yoludur.
  • İstek İşleme Anahtar Kelimeleri: Kod tabanında request.getParameter, request.body, request.query, $_POST, querystring.parse gibi isteğe bağlı verileri okuyan fonksiyonlar için arama yapın.
  • Diğer Kaynaklar: Sadece HTTP istekleri değil, aynı zamanda fs.readFile, os.getenv, System.getProperty, mesaj kuyruğu dinleyicileri (@RabbitListener, kafka.consumer().on('data', ...)) gibi dosya sisteminden, ortam değişkenlerinden veya asenkron mesajlardan veri okuyan noktalar da kritik giriş noktalarıdır.

2. Aşağıdan Yukarıya (Bottom-Up): Hedef'ten Giriş Noktasına

Bu yaklaşımda, bilinen tehlikeli fonksiyonları (sinks) bularak işe başlarız ve bu fonksiyonlara ulaşan verinin kaynağının güvenilmeyen bir giriş noktası olup olmadığını geriye doğru izleyerek araştırırız. Kapsamlı pentest ve SAST tecrübeniz sayesinde, hangi fonksiyonların tehlikeli olduğunu zaten biliyorsunuz. Bu strateji, bu bilginizi doğrudan koda uygulamanızı sağlar.

Tehlikeli Hedefleri Nasıl Buluruz?

  • Tehlikeli Anahtar Kelimeler: Kod tabanında zafiyete yol açabilecek fonksiyonlar için arama yapın.
    • Kod Enjeksiyonu: eval, new Function, pickle.loads, exec, ProcessBuilder, JXPathContext
    • SQL Enjeksiyonu: executeQuery, createNativeQuery, db.exec
    • XSS: innerHTML, dangerouslySetInnerHTML, Response.Write (sanitization olmadan)
    • Dosya Sistemi Zafiyetleri: fs.writeFile, os.rename, new File()
    • SSRF: HttpClient.execute, requests.get, http.request
  • Geriye Doğru İzleme: Bir tehlikeli hedef bulduğunuzda, kullandığınız IDE'nin "Find Usages", "Call Hierarchy" gibi özelliklerini veya grep gibi araçları kullanarak bu fonksiyonu kimin çağırdığını bulun. Bu işlemi, verinin kaynağının bir giriş noktası olduğunu doğrulayana veya güvenli bir kaynaktan geldiğini teyit edene kadar tekrarlayın.
Bu görsel, bir Python/Django uygulamasında "Unsafe Deserialization" (Güvensiz Deserialization) zafiyetini gösteren bir eğitim senaryosudur. Kodda görülen `pickle.loads(posts_data)` ifadesi, "aşağıdan yukarıya" yaklaşımında hemen tespit edeceğiniz klasik bir tehlikeli hedeftir. Bir sonraki adım, `posts_data` değişkeninin kaynağını izlemektir.

Her iki yaklaşım da kendi başına değerlidir ve genellikle en etkili sonuçlar için birlikte kullanılırlar. Bazen bir giriş noktasından yola çıkıp veriyi takip eder, bazen de kritik bir "sink" bulup kaynağını araştırırsınız.


Vaka Analizi: GeoServer RCE (CVE-2024-36401)

Şimdi bu teknikleri gerçek bir zafiyet üzerinde uygulayalım. Java tabanlı GeoServer uygulamasında bulunan kritik bir uzaktan kod yürütme (RCE) zafiyeti, giriş noktası ve tehlikeli hedefin nasıl birleştiğini mükemmel bir şekilde göstermektedir.

Aşağıdaki analiz yazısını okuyarak bu zafiyetin anatomisini çıkaralım.

CVE-2024-36401: GeoServer RCE Güvenlik Açığı Analizi - OPSWAT

Bu blog yazısı, GeoServer'daki bir RCE zafiyetinin kök nedenini adım adım açıklıyor. Yazıyı okurken, "giriş noktası" ve "tehlikeli hedef" kavramlarını aklınızda tutarak bu zafiyet zincirini kendiniz yeniden oluşturmaya çalışın.

İlk olarak, arka plan bölümünü okuyarak zafiyetin özetini ve CVSS puanını öğrenin. Zafiyetin "XPath ifadeleri olarak güvenli olmayan şekilde değerlendirilmesinden" kaynaklandığına dikkat edin. Ardından, nasıl ortaya çıktığı ile ilgili bölümü okuyun. Burada commons-jxpath kütüphanesinin kilit rolünü göreceksiniz. Bu, bizim tehlikeli hedefimizdir (sink). İstismar iş akışı bölümü, giriş noktasını netleştirir: GetPropertyValue işlemine gönderilen bir POST isteği. Özellikle, valueReference parametresinin, eğer bilinen bir özellik değilse bir XPath ifadesi olarak yorumlandığı "geri dönüş mekanizması" kritiktir. JXPath'in nasıl çalıştığını anlatan bölüm, tehlikeli hedefin neden tehlikeli olduğunu açıklar. JXPath, Java fonksiyonlarının (exec() gibi) doğrudan XPath sorguları içinden çağrılmasına izin verir. Son olarak, tüm iş akışını adım adım takip edin ve saldırı simülasyonunu inceleyin. Bu bölümler, kullanıcı girdisinin (valueReference parametresi) nasıl doğrulanmadan tehlikeli hedefe (JXPathContext ve iteratePointers()) ulaştığını gösterir.

Bu vaka analizinde gördüğümüz gibi:

  • Giriş Noktası: /geoserver/wfs endpoint'ine yapılan POST isteğindeki valueReference parametresi.
  • Tehlikeli Hedef: commons-jxpath kütüphanesinin, doğrulama olmaksızın bir string'i XPath ifadesi olarak yorumlayıp çalıştıran mekanizması.
  • Zafiyet Yolu: Uygulamanın, beklenen bir özellik adı bulamadığında, kullanıcıdan gelen girdiyi güvenli olmayan bir şekilde bu "yorumlayıcı" hedefe iletmesi.

Farklı Dillerden Pratik Örnekler

Giriş noktası ve tehlikeli hedef desenleri, dil ve framework'e göre farklılık gösterir. Şimdi JavaScript ve Python gibi yetkin olduğunuz dillerden çeşitli örneklere bakalım.

Aşağıdaki video, farklı dillerdeki kod parçacıklarında çeşitli zafiyetleri hızlıca tespit edip açıklıyor. Her bir örnekte giriş noktasına ve tehlikeli hedefe odaklanın.

ChatGPT vs Hacker ! SonarSource Kaynak Kod Analizi ile Zafiyet Tespiti Challenge'ı

Bu videoda Mehmet İnce, SonarSource tarafından hazırlanan bir "challenge"ı çözerek farklı kodlardaki zafiyetleri analiz ediyor. Her bir zafiyet, temel bir giriş noktası/tehlikeli hedef ilişkisine dayanır.

Stored XSS (Java): Bu bölümde, kullanıcıdan alınan yorum verisinin (comment) giriş noktası olduğunu göreceksiniz. Veri, bazı replace işlemlerinden geçse de nihayetinde ham bir şekilde HTML tablosuna yazılıyor, bu da tehlikeli hedefi oluşturuyor. Verinin kullanıldığı bağlamın (HTML) temizleme (sanitization) için neden önemli olduğuna dikkat edin. Open Redirect / SSRF (C#): Buradaki zafiyet daha karmaşık. Giriş noktası, URL'deki pet (path) parametresidir. Tehlikeli hedef ise, bu pet kullanılarak oluşturulan bir URL'ye HttpClient ile istek gönderen koddur. Zafiyeti daha da kritik hale getiren şey, kullanıcının Authorization başlığının da bu isteğe eklenmesidir. Bu, basit bir yönlendirme zafiyetini, kimlik bilgisi sızdıran bir SSRF'ye dönüştürür. Authentication Bypass (JavaScript): Bu örnekte zafiyet çok daha incedir. Giriş noktası req.url'dir. Tehlikeli hedef ise startsWith('/api') kontrolünün kendisidir. Zafiyet, startsWith metodunun büyük/küçük harfe duyarlı (case-sensitive) olmasından kaynaklanır. Bir saldırgan /API gibi bir yolla bu kontrolü atlayabilir. Burada "sink", bir veri işleme fonksiyonu değil, bir güvenlik kararının verildiği mantıksal bir ifadedir. Insecure Cryptography (Python - AES ECB): Bu bölüm ileri seviye bir konsepti ele alıyor. Giriş noktası, şifrelenecek olan JSON verisidir. Tehlikeli hedef ise AES.new() fonksiyonunun MODE_ECB (Electronic Codebook) modu ile çağrılmasıdır. ECB modu, aynı girdi bloklarının her zaman aynı çıktı bloklarını üretmesi nedeniyle desenlerin korunmasına yol açar ve güvensiz kabul edilir. Burada tehlikeli hedef, fonksiyonun kendisinden çok, onun güvensiz konfigürasyonudur. Bu, kod analizinde sadece fonksiyon adlarına değil, onların nasıl kullanıldığına da dikkat etmemiz gerektiğini gösteren harika bir örnektir.


Kod Görselleştirmenin Rolü

Manuel grep ve IDE aramaları güçlü olsa da, çok büyük ve size yabancı kod tabanlarında sistemin bütününü görmek zor olabilir. Kod görselleştirme araçları, giriş noktalarını ve potansiyel veri akış yollarını daha üst seviyeden görmemize yardımcı olabilir.

Kod Görselleştirme: Karmaşık Kodları Diyagramlara Nasıl ...

Bu makale, kod görselleştirmenin karmaşık sistemleri anlamadaki rolünü açıklıyor. Özellikle bağımlılık grafikleri, giriş noktalarını ve tehlikeli hedefleri bulmada bize yardımcı olabilir.

Lütfen Bağımlılık Grafikleri bölümünü ve devamındaki Mimari Sınırları Ortaya Çıkarma alt başlığını okuyun. Bir bağımlılık grafiğinin, sistemin dışından (örneğin bir web framework'ü) gelen bağlantıları göstererek giriş noktalarını nasıl görselleştirebileceğini düşünün. Benzer şekilde, veritabanı sürücüleri veya OS kütüphaneleri gibi harici bağımlılıklara giden çok sayıda bağlantı, potansiyel tehlikeli hedeflerin (sink) yoğunlaştığı alanları gösterebilir.

Bağımlılık veya çağrı grafikleri, hangi modüllerin dış dünya ile iletişim kurduğunu (giriş noktaları) ve hangi modüllerin tehlikeli olabilecek alt seviye API'leri (dosya sistemi, ağ, veritabanı vb.) çağırdığını (tehlikeli hedefler) hızlıca belirlemek için bir başlangıç noktası sunabilir.


Sonuç

Bu derste, güvenli kod analizinin temel yapı taşları olan giriş noktalarını ve tehlikeli hedefleri tanımladık ve bunları bir kod tabanında bulmak için sistematik yöntemler öğrendik.

Temel Çıkarımlar:

  • İki Temel Strateji: Kod analizine ya bilinen giriş noktalarından başlayıp veriyi ileriye doğru takip ederek (yukarıdan aşağıya) ya da bilinen tehlikeli hedeflerden başlayıp verinin kaynağını geriye doğru araştırarak (aşağıdan yukarıya) yaklaşabiliriz.
  • Desen Tanıma: "Uzman gözü", belirli diller ve framework'ler için tipik giriş noktası desenlerini (request.body, @RequestParam) ve tehlikeli hedef fonksiyonlarını (eval, pickle.loads, executeQuery) hızlıca tanıma becerisidir.
  • Bağlam Her Şeydir: Bir fonksiyonun "tehlikeli" olup olmadığı, ona sağlanan veriye ve kullanıldığı bağlama bağlıdır. Benzer şekilde, bir "giriş noktası"ndan gelen her veri zafiyete yol açmaz; önemli olan, bu verinin tehlikeli bir hedefe ulaşmadan önce doğru şekilde doğrulanıp doğrulanmadığıdır.
  • Gerçek Dünya Zafiyetleri: Analiz ettiğimiz GeoServer RCE örneğinde de gördüğümüz gibi, kritik zafiyetler genellikle bir giriş noktasından bir tehlikeli hedefe uzanan basit ama gözden kaçırılmış bir veri akışı yolundan kaynaklanır.

Artık bir veri akışının başlangıç ve bitiş noktalarını nasıl bulacağımızı biliyoruz. Bir sonraki dersimizde, bu dersin doğal bir devamı olarak, bu iki nokta arasındaki yolculuğun tamamını nasıl izleyeceğimizi öğreneceğiz. "Manuel Veri Akışı ve Taint Analizi" modülünün ilk dersinde, bir verinin birden fazla fonksiyon ve modül sınırı boyunca nasıl takip edileceğini ve bu süreçte karşılaşılan karmaşıklıkları nasıl yöneteceğimizi ele alacağız.