Kaynak Kodu Güvenlik Denetimi: SAST, DAST, SCA ve Güvenli Kod İncelemesi

Hızlı Cevap

Kaynak kodu güvenlik denetimi; kodu statik (SAST), dinamik (DAST), enstrümante (IAST) ve bileşen (SCA) yöntemlerle analiz ederek zafiyetleri henüz üretime çıkmadan bulma sürecidir. En etkili sonuç, otomatik araçların manuel güvenli kod incelemesiyle birleştirildiği, kaynak akış (taint) analizine dayalı, CI/CD'ye entegre bir yaklaşımdır.

Kaynak Kodu Güvenlik Denetimi Nedir?

Kaynak kodu güvenlik denetimi (secure code review / source code security audit), bir uygulamanın yazılı kodunu ve bağımlılıklarını güvenlik açıkları açısından sistematik biçimde inceleme disiplinidir. Amaç, bir zafiyetin saldırgan tarafından kullanılabilir hale gelmeden, yani henüz geliştirme veya derleme aşamasındayken tespit edilip kapatılmasıdır. Bu yaklaşım, sektörde "shift-left" (güvenliği sola kaydırma) olarak adlandırılır: güvenlik kontrolleri yazılım yaşam döngüsünün mümkün olan en erken noktasına çekilir.

Kaynak kodu denetimi, bir web sitesine dışarıdan yapılan zafiyet taramasından temelde farklıdır. Dış tarama saldırganın gördüğü yüzeyi test eder; kaynak kodu denetimi ise zafiyetin kök nedenini, yani hatalı yazılmış satırı doğrudan gösterir. Genel sızma testi ve dış yüzey taraması için web sitesi güvenlik testi ve yapay zeka ile otomatik zafiyet tarama içeriklerimize bakabilirsiniz. Bu makale özellikle uygulama güvenliği (AppSec) ve kod düzeyindeki analize odaklanır.

Bir kaynak kodu denetimi tipik olarak beş ana sütun üzerine kurulur:

  • SAST (Static Application Security Testing): Kodu çalıştırmadan statik analiz.
  • DAST (Dynamic Application Security Testing): Çalışan uygulamayı dışarıdan test.
  • IAST (Interactive Application Security Testing): Çalışma anında enstrümante analiz.
  • SCA (Software Composition Analysis): Üçüncü taraf bileşen ve bağımlılık analizi.
  • Manuel güvenli kod incelemesi: Uzman gözüyle iş mantığı ve tasarım denetimi.

Bu sütunların hiçbiri tek başına yeterli değildir. Her biri farklı bir zafiyet sınıfını yakalar ve farklı bir kör nokta bırakır. Olgun bir AppSec programı, bu yöntemleri katmanlı biçimde birleştirir.

SAST: Statik Uygulama Güvenlik Testi

SAST, kaynak kodunu, byte kodunu veya derlenmiş ikili dosyayı çalıştırmadan, "beyaz kutu" yaklaşımıyla inceleyen yöntemdir. Araç, kodu bir soyut sözdizimi ağacına (AST) ve kontrol/veri akış grafiklerine dönüştürür, ardından bilinen zafiyet kalıplarını ve güvensiz veri akışlarını arar.

SAST'in en güçlü yanı, kapsama genişliğidir: kodun çalışma sırasında ulaşılamayan, nadir koşullarda tetiklenen yollarını da görebilir. Geliştirici, kod yazarken IDE içinde anında uyarı alabilir.

SAST'in tipik olarak yakaladığı zafiyetler:

  • SQL Injection ve diğer enjeksiyon türleri (CWE-89, CWE-78)
  • Cross-Site Scripting / XSS (CWE-79)
  • Sabit kodlanmış sırlar, parolalar, API anahtarları (CWE-798)
  • Güvensiz kriptografi kullanımı (CWE-327)
  • Path traversal (CWE-22)
  • Hatalı hata yönetimi ve bilgi sızıntısı

Somut Örnek: Sabit Kodlanmış Sır (CWE-798)

Aşağıdaki gibi bir kod, SAST'in klasik bir bulgusudur:

# KÖTÜ: API anahtarı kaynak koda gömülmüş
DB_PASSWORD = "P@ssw0rd_Prod_2024"
AWS_SECRET = "AKIA...REDACTED..."

def connect():
    return psycopg2.connect(host="db.prod", password=DB_PASSWORD)

Doğrusu, sırrı ortam değişkeni veya bir gizli yönetim çözümünden (vault) okumaktır:

# DOĞRU
import os
DB_PASSWORD = os.environ["DB_PASSWORD"]

SAST'in Zayıf Yönü: Yanlış Pozitif

SAST araçlarının en bilinen sorunu yüksek yanlış pozitif (false positive) oranıdır. Araç bir kalıbı görür ama çalışma zamanındaki bağlamı bilmez; örneğin bir kullanıcı girdisinin daha sonra başka bir katmanda temizlendiğini fark etmeyebilir. Bağlamı zayıf bir SAST aracı, geliştirici ekibini yüzlerce alarmla boğabilir ve bu da "alarm yorgunluğu" yaratarak gerçek bulguların gözden kaçmasına yol açar.

DAST: Dinamik Uygulama Güvenlik Testi

DAST, uygulamayı çalışır durumdayken, kaynak koduna erişmeden, "kara kutu" yaklaşımıyla test eder. Tıpkı bir saldırgan gibi HTTP istekleri gönderir, yanıtları analiz eder ve gerçekten sömürülebilir davranışları arar.

DAST'in en güçlü yanı, bulduğu zafiyetin gerçek ve çalışır olmasıdır; yani yanlış pozitif oranı SAST'e göre çok daha düşüktür. Ayrıca yapılandırma hataları, çalışma zamanı davranışları ve kimlik doğrulama/oturum sorunları gibi yalnızca canlı sistemde görünen problemleri yakalar.

DAST'in zayıf yönleri:

  • Zafiyetin kök nedenini (hangi kod satırı) göstermez, yalnızca belirtiyi gösterir.
  • Kodun çalışma sırasında ulaşılamayan yollarını test edemez.
  • Tarama yavaştır ve genellikle döngünün geç aşamasında çalışır.

DAST genellikle web sitesi güvenlik testi süreçlerinin bir parçasıdır ve SAST'i tamamlar: SAST nerede hata olduğunu, DAST ise bu hatanın gerçekten sömürülebilir olup olmadığını söyler.

IAST: Etkileşimli Uygulama Güvenlik Testi

IAST, SAST ile DAST'in arasında bir köprüdür. Uygulamanın içine yerleştirilen bir ajan (enstrümantasyon), test veya gerçek kullanım sırasında verinin uygulama içinde nasıl aktığını gözlemler. Böylece hem çalışma zamanı bağlamına (DAST gibi) hem de kod düzeyindeki kök nedene (SAST gibi) erişim sağlar.

IAST'in avantajı, çok düşük yanlış pozitif oranıyla zafiyetin tam satırını gösterebilmesidir. Dezavantajı ise yalnızca test sırasında fiilen çalıştırılan kod yollarını kapsamasıdır; test senaryosu bir yolu tetiklemezse, o yol denetlenmez. Ayrıca her dil ve çatı (framework) için ajan desteği bulunmayabilir.

SCA: Yazılım Bileşen Analizi ve Tedarik Zinciri

Modern uygulamaların kodunun büyük çoğunluğu aslında ekip tarafından yazılmaz; açık kaynak kütüphaneler ve üçüncü taraf bileşenlerden gelir. SCA (Software Composition Analysis), bu bağımlılıkları envanterler, bilinen zafiyetleri (CVE) eşler ve lisans risklerini denetler.

SCA'nın kritik olmasının nedeni, son yılların en yıkıcı saldırılarının tedarik zinciri (supply chain) üzerinden gelmesidir. Log4Shell (Log4j, CVE-2021-44228) gibi bir zafiyet, hiç güvensiz kod yazmamış olmanıza rağmen uygulamanızı uzaktan kod çalıştırmaya açık hale getirebilir.

SCA tipik olarak şunları üretir:

  • SBOM (Software Bill of Materials): Uygulamadaki tüm bileşenlerin ayrıntılı listesi. CycloneDX veya SPDX formatında üretilir.
  • CVE eşlemesi: Her bağımlılığın bilinen zafiyetlerle karşılaştırılması.
  • Transitif bağımlılık analizi: Doğrudan değil, bağımlılığın bağımlılığı olarak gelen riskli bileşenlerin tespiti.
  • Lisans uyumluluğu: GPL gibi bulaşıcı lisansların ticari kullanımda yarattığı riskler.

Somut Örnek: Zafiyetli Bağımlılık

<!-- pom.xml içinde zafiyetli bir sürüm -->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.14.1</version> <!-- CVE-2021-44228 / Log4Shell -->
</dependency>

SCA aracı bu sürümü işaretler ve yamalı sürüme (2.17.1+) yükseltmeyi önerir. OWASP Dependency-Check, bu işi yapan en bilinen açık kaynak araçlardan biridir.

Manuel Güvenli Kod İncelemesi

Otomatik araçlar kalıp tanımada üstündür ama iş mantığı zafiyetlerini neredeyse hiç göremez. Bir kullanıcının kendi hesabı yerine başkasının siparişini görüntülemesine izin veren bir yetkilendirme hatası (IDOR / CWE-639), söz dizimsel olarak tamamen "temiz" görünür; hiçbir SAST aracı onu kalıp olarak yakalayamaz çünkü sorun mantıktadır, sözdiziminde değil.

Manuel güvenli kod incelemesi şunlara odaklanır:

  • Yetkilendirme ve erişim kontrol mantığı (yatay/dikey yetki yükseltme)
  • İş akışı atlatma ve durum makinesi hataları
  • Kriptografik tasarım kararları (sadece kullanım değil, tasarım)
  • Çok adımlı işlemlerdeki yarış koşulları (race condition, TOCTOU)
  • Güven sınırları ve mimari kararlar

OWASP Code Review Guide, bu sürecin metodolojisini sağlayan referans kaynaktır. En verimli yaklaşım, otomatik araçların ürettiği bulguları bir uzmanın doğruladığı ve araçların kaçırdığı mantık hatalarını manuel olarak avladığı hibrit modeldir.

Karşılaştırma: SAST vs DAST vs IAST vs SCA

Özellik SAST DAST IAST SCA
Yaklaşım Statik (beyaz kutu) Dinamik (kara kutu) Enstrümante (gri kutu) Bileşen analizi
Kod erişimi gerekir mi Evet Hayır Evet (ajan) Evet (manifest)
Uygulama çalışır mı Hayır Evet Evet Hayır
Ne bulur Enjeksiyon, sabit sır, güvensiz kripto, XSS kaynağı Çalışan XSS, yapılandırma hatası, oturum sorunu Kök nedenli çalışma zamanı zafiyeti Zafiyetli bağımlılık (CVE), lisans riski
Ne kaçırır İş mantığı, çalışma zamanı bağlamı Kök neden, erişilmeyen yollar Test edilmeyen kod yolları Kendi yazdığınız kodun zafiyetleri
Yanlış pozitif Yüksek Düşük Çok düşük Orta (kullanılmayan bağımlılık)
Ne zaman Geliştirme / commit anı Test / staging QA / fonksiyonel test Her commit ve sürekli
Döngüdeki yeri En erken (sol) Geç Orta Sürekli

Özetle: bu yöntemler rakip değil, tamamlayıcıdır. SAST geniş ama gürültülü; DAST kesin ama yüzeysel; IAST kesin ama dar; SCA ise kendi kodunuza tamamen kördür ama bağımlılıklarınızı tek gören yöntemdir.

Kaynak Akış (Taint) Analizi ve CPG Mantığı

İleri seviye bir SAST'i sıradan bir kalıp eşleştiriciden ayıran şey, kaynak akış (taint) analizidir. Mantık şudur: güvenilmeyen bir veri "kaynağı" (source) ile tehlikeli bir "hedefe" (sink) kadar izlenir. Eğer kullanıcı girdisi, arada uygun bir temizleme (sanitization) işleminden geçmeden tehlikeli bir fonksiyona ulaşıyorsa, bu sömürülebilir bir zafiyettir.

  • Source (kaynak): Kullanıcıdan gelen, güvenilmeyen veri. Örnek: HTTP parametresi, form alanı, çerez.
  • Sink (hedef): Verinin tehlikeli biçimde kullanıldığı nokta. Örnek: SQL sorgusu, sistem komutu, HTML çıktısı.
  • Sanitizer (temizleyici): Veriyi güvenli hale getiren işlem. Örnek: parametreli sorgu, çıktı kodlama, beyaz liste doğrulaması.

Somut Örnek: SQL Injection Taint Akışı (CWE-89)

# Source: request.args.get -> güvenilmeyen veri
user_id = request.args.get("id")

# Sanitizer YOK, doğrudan string birleştirme
query = "SELECT * FROM users WHERE id = '" + user_id + "'"

# Sink: tehlikeli SQL çalıştırma
cursor.execute(query)   # <-- SQL INJECTION

Doğru biçim, parametreli sorgu (prepared statement) kullanmaktır:

user_id = request.args.get("id")
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

Bu source-to-sink yolunu doğru izleyebilmek için modern motorlar kodu bir Kod Özellik Grafiğine (Code Property Graph, CPG) dönüştürür. CPG; soyut sözdizimi ağacını (AST), kontrol akış grafiğini (CFG) ve veri akış grafiğini (DFG) tek bir birleşik grafte birleştirir. Bu sayede analiz motoru, "şu kullanıcı girdisi, şu fonksiyondan geçip, hiç temizlenmeden şu komuta ulaşıyor mu?" sorusunu graf üzerinde dolaşarak yanıtlayabilir.

KAOS yapay zeka güvenlik motoru, DSET'in yapay zeka destekli ofansif güvenlik ajanıdır ve kaynak kodu tarafında tam olarak bu yaklaşımı kullanır: kodu tree-sitter tabanlı bir Kod Özellik Grafiğine dönüştürerek source-to-sink analizi yapar. Daha da önemlisi KAOS, bulduğu zafiyeti yalnızca raporlamakla kalmaz; mümkün olduğunda kanıt/PoC üreterek doğrular ve böylece yanlış pozitifi belirgin biçimde azaltır. KAOS her zaman yetki dahilinde çalışır. Doğrulama odaklı bu yaklaşımı doğrulanmış zafiyet, yanlış pozitifsiz test içeriğimizde ayrıntılı ele aldık.

Yanlış Pozitif Sorunu ve Nasıl Azaltılır?

Yanlış pozitif, bir AppSec programını öldüren sessiz katildir. Araç yüzlerce alarm üretir, geliştiriciler bunları incelemeye zaman ayıramaz, gerçek zafiyetler gürültünün içinde kaybolur. Yanlış pozitifi azaltmanın kanıtlanmış yolları:

  • Taint analizi kullanın: Basit kalıp eşleştirme yerine source-to-sink akışını doğrulayan motorlar tercih edin. Temizlenmiş bir girdiyi zafiyet sanmazlar.
  • Doğrulama (PoC) ekleyin: Bir bulgu otomatik olarak gerçek bir kanıtla teyit edilebiliyorsa, yanlış pozitif olma ihtimali pratik olarak sıfıra iner.
  • Bağlam farkındalığı: Çerçeveye (framework) özgü kuralları olan araçlar, o çerçevenin yerleşik korumalarını tanır ve gereksiz alarm üretmez.
  • Temel çizgi (baseline) belirleyin: Mevcut bulguları bir kez triyaj edip, yalnızca yeni eklenen bulgulara odaklanın.
  • Önceliklendirme: CVSS skoru, sömürülebilirlik ve varlık kritikliğine göre sıralayın; her şeyi aynı anda düzeltmeye çalışmayın.

DevSecOps: CI/CD Entegrasyonu ve Shift-Left

Güvenlik testlerinin gerçek değeri, otomatikleştirilip yazılım üretim hattına (CI/CD pipeline) gömüldüğünde ortaya çıkar. Bu yaklaşıma DevSecOps denir ve temel ilkesi shift-left'tir: güvenliği döngünün sonunda değil, başında uygulamak.

Tipik bir güvenli üretim hattı şöyle kurgulanır:

  • Commit / pre-commit: Sır taraması (hard-coded secret) ve hızlı SAST kontrolü. Geliştirici daha kod göndermeden uyarılır.
  • Pull request: Tam SAST + SCA taraması. Yeni eklenen kod ve bağımlılıklar denetlenir; kritik bulgu varsa birleştirme (merge) engellenir.
  • Build: SBOM üretimi ve lisans denetimi.
  • Staging / test: DAST veya IAST ile çalışan uygulama testi.
  • Üretim sonrası: Sürekli SCA izlemesi; daha önce temiz olan bir bağımlılıkta yeni bir CVE yayımlandığında otomatik uyarı.

Bu hattın başarılı olması için kapılar (quality gates) doğru ayarlanmalıdır. Her bulguda derlemeyi durdurmak ekibi bıktırır; yalnızca yüksek ve kritik, doğrulanmış bulguların engelleyici olması idealdir. NIST'in SSDF (Secure Software Development Framework) çerçevesi, bu süreçlerin kurumsal düzeyde nasıl yapılandırılacağına dair referans sağlar.

OWASP Top 10 ve CWE Eşlemesi

Kaynak kodu denetiminin bulguları, sektör standardı taksonomilerle eşlenmelidir. Bu, hem raporların evrensel anlaşılır olmasını hem de risk önceliklendirmesini sağlar.

  • OWASP Top 10: Web uygulama güvenliğinin en kritik 10 risk kategorisi. Örnek: A01 Broken Access Control, A03 Injection, A06 Vulnerable and Outdated Components.
  • CWE (Common Weakness Enumeration): MITRE tarafından yürütülen, yazılım zayıflıklarının ayrıntılı sınıflandırması. Örnek: CWE-89 (SQL Injection), CWE-79 (XSS), CWE-502 (Insecure Deserialization).

Örnek eşlemeler:

Zafiyet CWE OWASP Top 10
SQL Injection CWE-89 A03: Injection
Cross-Site Scripting CWE-79 A03: Injection
Sabit kodlanmış sır CWE-798 A07: Identification and Authentication Failures
Güvensiz deserialization CWE-502 A08: Software and Data Integrity Failures
Zafiyetli bağımlılık CWE-1104 A06: Vulnerable and Outdated Components
Yetkilendirme hatası (IDOR) CWE-639 A01: Broken Access Control

Somut Örnek: Güvensiz Deserialization (CWE-502)

import pickle

# KÖTÜ: kullanıcıdan gelen veriyi doğrudan deserialize etmek
def load_session(data):
    return pickle.loads(data)   # <-- uzaktan kod çalıştırmaya açık

Güvensiz pickle gibi mekanizmalar yerine, güvenilmeyen veri için imzalı ve şema-doğrulamalı JSON gibi güvenli serileştirme biçimleri kullanılmalıdır.

Sıkça Sorulan Sorular

SAST mı DAST mı, hangisini seçmeliyim?

Bu bir "ya o ya bu" sorusu değildir. SAST kodun içindeki kök nedeni erken ve geniş kapsamlı bulur; DAST ise çalışan uygulamada zafiyetin gerçekten sömürülebilir olduğunu kanıtlar. Olgun bir program ikisini de kullanır; ideal olanı SAST + SCA'yı her commit'te, DAST/IAST'i ise test aşamasında çalıştırmaktır.

Kaynak kodu güvenlik denetimi ile sızma testi aynı şey mi?

Hayır. Sızma testi genellikle çalışan sistemi dışarıdan, saldırgan perspektifiyle test eder. Kaynak kodu denetimi ise kodun içine bakar ve zafiyetin tam satırını gösterir. İkisi birbirini tamamlar; en iyi sonuç ikisinin birlikte yapılmasıyla alınır.

SCA gerçekten gerekli mi, kendi kodum güvenliyse?

Kesinlikle gerekli. Modern uygulamaların kodunun büyük bölümü açık kaynak bağımlılıklardan gelir. Log4Shell gibi zafiyetler, sizin tek satır güvensiz kod yazmamanıza rağmen uygulamanızı kritik riske sokabilir. SCA, kendi kodunuzun göremediği bu tedarik zinciri riskini yöneten tek yöntemdir.

Yanlış pozitifler neden bu kadar büyük bir sorun?

Çünkü güveni ve verimi yok ederler. Yüzlerce hatalı alarm, geliştiricilerin araca olan güvenini sarsar ve gerçek zafiyetlerin gözden kaçmasına yol açar. Çözüm; kalıp eşleştirme yerine taint analizi ve mümkünse otomatik PoC doğrulaması kullanan araçlardır. KAOS'un doğrulama odaklı yaklaşımı tam da bu sorunu hedefler.

CPG (Kod Özellik Grafiği) neden önemli?

Çünkü gerçek zafiyetler tek bir satırda değil, verinin kaynaktan hedefe yolculuğunda gizlidir. CPG; sözdizimi, kontrol akışı ve veri akışını tek bir grafikte birleştirerek, motorun bu yolu uçtan uca takip etmesini sağlar. Böylece temizlenmemiş bir kullanıcı girdisinin tehlikeli bir fonksiyona ulaşıp ulaşmadığı kesin olarak izlenir.

SBOM nedir ve neden tutulmalı?

SBOM (Software Bill of Materials), uygulamanızdaki tüm yazılım bileşenlerinin ayrıntılı envanteridir. Yeni bir CVE yayımlandığında, hangi uygulamalarınızın etkilendiğini saniyeler içinde belirlemenizi sağlar. Düzenleyici gereksinimler de giderek SBOM tutulmasını zorunlu kılmaktadır.

Sonuç

Kaynak kodu güvenlik denetimi, tek bir araçla çözülen bir görev değil, katmanlı bir disiplindir. SAST geniş kapsamı, DAST kesinliği, IAST kök nedenli çalışma zamanı görünürlüğünü, SCA tedarik zinciri güvenliğini ve manuel inceleme iş mantığı derinliğini getirir. Bunları taint/CPG analiziyle güçlendirip CI/CD'ye gömdüğünüzde, zafiyetleri üretime çıkmadan, en ucuz ve en güvenli noktada kapatırsınız. Yanlış pozitifi düşürmenin anahtarı ise doğrulamadır: bir bulgu kanıtla teyit edilebiliyorsa, hem güven hem de hız kazanırsınız.

DSET Bilişim ve Siber Güvenlik (kuruluş 2003). Kurumsal kaynak kodu güvenlik denetimi ve KAOS CPG analizi için: +90 536 662 38 09.

Kaynaklar