← İçindekiler Güvenli Kodlama EğitimiGüvenlik Testi ve DevSecOps
2021’de Codecov adlı bir CI/CD aracı tedarik zinciri saldırısına uğradı. Saldırgan, Codecov’un betiğini değiştirdi ve binlerce şirketin pipeline’ından gizli anahtarları çaldı. Saldırı 2 ay fark edilmedi. O şirketlerin CI/CD pipeline’larında güvenlik testi vardı ama pipeline’ın kendisi test edilmiyordu.
Güvenli kod yazmak yetmez. Yazılan kodun güvenli olduğunu otomatik olarak kanıtlamak da şarttır. DevSecOps, güvenliği geliştirme sürecinin doğal bir parçası yapar: geliştirici kod yazarken, CI/CD hattı çalışırken, üretime dağıtırken güvenlik testleri otomatik çalışır.
Özlü kural: Güvenlik testi, “bitti” deyince başlayan bir denetim değil, “başladı” deyince çalışan bir sürece gömülmeli. Geliştirici kod gönderdiği an, güvenlik testi çalışmalı ve açık varsa dağıtım durmalı.
Hızlı ipucu: pip install bandit && bandit -r src/ komutunu bugün çalıştır. HIGH seviyeli bulgular, düzeltilmeyi bekliyor.
56.1 SAST (Static Application Security Testing)
SAST, kaynak kodu çalıştırmadan analiz eder. Kodu tarar ve bilmiş güvenlik açığı kalıpları arar. “Bu os.system() çağrısı kullanıcı girdisi içeriyor, bu bir command injection riski” der.
Python SAST Aracı: Bandit
# Bandit kurulumu
pip install bandit
# Tek dosyayi tara
bandit app.py
# Tum projeyi tara
bandit -r src/
# Sonucu JSON olarak kaydet
bandit -r src/ -f json -o bandit-report.json
Bandit çıktısı örneği:
Issue: [B602:user-input-call-subprocess] subprocess call with shell=True
Severity: HIGH Confidence: HIGH
Location: app/utils.py:45
More Info: https://bandit.readthedocs.io/en/latest/plugins/b602_subprocess_popen_shell_true.html
45 subprocess.call("convert " + filename, shell=True)
Bu bulgu, “satır 45’te shell=True ile kullanıcı girdisi kullanılıyor, command injection riski var” der. Severity (önem) ve Confidence (güven) dereceleri, hangi bulguların öncelikli düzeltilmesi gerektiğini gösterir.
SAST araçları false positive (yanlış alarm) üretir. Bandit’in her bulgusu gerçek bir açık değildir. Önemli olan: HIGH severity + HIGH confidence bulgularını öncelikli düzelt. LOW confidence bulguları incele ama panik yapma. False positive oranını zamanla azaltmak için baseline dosyası oluştur ve bilinen false positive’leri dışla.
Diğer SAST Araçları:
| Araç | Dil | Tip | Özellik |
|---|---|---|---|
| Bandit | Python | Açık kaynak | Hızlı, basit |
| Semgrep | Çoklu | Açık kaynak | Özel kural yazılabilir |
| SonarQube | Çoklu | Ücretsiz/Ücretli | Code quality + security |
| Fortify | Çoklu | Ücretli | Kurumsal, detaylı |
| CodeQL | Çoklu | GitHub | GitHub Advanced Security |
56.2 DAST (Dynamic Application Security Testing)
DAST, çalışan uygulamayı dışarıdan tarar. Kaynak koda ihtiyacı yoktur. Uygulamaya HTTP istekleri gönderir, SQL injection, XSS, CSRF gibi açıkları canlı test eder. “Kara kutu” testidir: saldırganın bakış açısıyla.
OWASP ZAP
# OWASP ZAP kurulumu (Docker)
docker run -t owasp/zap2docker-stable zap-baseline.py \
-t https://staging.example.com \
-r zap-report.html
# Tam tarama (daha yavas, daha detayli)
docker run -t owasp/zap2docker-stable zap-full-scan.py \
-t https://staging.example.com \
-r zap-report.html
ZAP raporu şunları bulur:
- SQL injection açıkları (forma
' OR 1=1gönderir, yanıtı analiz eder) - XSS açıkları (forma
<script>alert(1)</script>gönderir) - Missing security headers (HSTS, X-Frame-Options, CSP)
- Broken authentication
- Session management zafiyetleri
SAST vs DAST:
| Özellik | SAST | DAST |
|---|---|---|
| Ne tarar | Kaynak kod | Çalışan uygulama |
| Ne zaman | Commit/push anında | Staging/pre-prod |
| Hız | Saniyeler/dakikalar | Saatler |
| False positive | Yüksek | Düşük |
| Açık tipi | Kod kalıbı | Çalışan zafiyet |
| Dil gerekli | Evet | Hayır (kara kutu) |
İkisini birlikte kullan. SAST erken yakalar (geliştirme aşaması), DAST gerçek açığı doğrular (staging aşaması).
56.3 SCA (Software Composition Analysis)
SCA, projenin kullandığı üçüncü parti kütüphanelerdeki bilinen açıkları tarar. Modern uygulamanın %80’i açık kaynak kütüphanelerden oluşur. Senin yazdığın kod güvenli olabilir ama bağımlılıklarında bilinen bir açık varsa, tüm sistemin tehlikededir.
Python Bağımlılık Tarama
# pip-audit: Python bağımlılıklarını CVE veritabanıyla karsilastirir
pip install pip-audit
pip-audit
# Cikti ornegi:
# Found 2 known vulnerabilities in 1 package:
# flask == 1.1.0
# * CVE-2023-30861 HIGH Flask versions prior to 2.2.5 contain...
# CVE-2023-36801 MEDIUM Flask versions prior to 3.0.0 contain...
# safety: Alternatif tarama aracı
pip install safety
safety check --requirements requirements.txt
requirements.txt Analiz:
# Tum bağımlılıkları güncel mi kontrol et
pip list --outdated
# Bilinen aciklara sahip paketler
pip-audit --requirement requirements.txt
# SBOM (Software Bill of Materials) uret
pip install cyclonedx-bom
cyclonedx-py -r -o sbom.json
# SBOM, projenin tum bağımlılık agacini cikarır
# Yeni bir CVE yayinlandiginda "bu kutuphane bizde var mi?" diye SBOM'a bakarsin
Log4Shell (CVE-2021-44228) krizinde SBOM’u olan şirketler 30 dakika içinde etkilenip etkilenmediklerini belirledi. SBOM’u olmayan şirketler günlerce manuel olarak tüm projeleri taradı. SBOM, bağımlılık kriz anında hayati önem taşır. Bu bölümün SCA kısmında SBOM üretimini ve kullanımını detaylıca işledik.
56.4 Fuzzing
Fuzzing, programa rastgele (veya yarı-rastgele) veri gönderip çökme veya beklenmeyen davranış bulma tekniğidir. SAST ve DAST bulamayan açıkları bulur çünkü “bunu denemek kimse aklına gelmez” türünden girdileri otomatik üretir.
# Basit fuzzing ornegi (atheris kutuphanesi)
import atheris
import sys
def test_parser(data: bytes):
"""Parser fonksiyonunu fuzz et"""
try:
# Rastgele veriyi parser'a ver
parsed = my_parser(data)
assert parsed is not None
except (ValueError, TypeError):
pass # Beklenen hatalar
# Beklenmeyen crash'ler yakalanir ve raporlanir
# Fuzzing baslat
atheris.Setup(sys.argv, test_parser)
atheris.Fuzz()
Fuzzing türleri:
| Tür | Nasıl çalışır | Örnek |
|---|---|---|
| Dumb fuzz | Tamamen rastgele byte’lar | /dev/urandom |
| Smart fuzz | Formatı bilir, kurallı üretir | JSON grammar ile |
| Coverage-guided | Hangi girdi yeni kod yol açar, onu takip eder | AFL, libFuzzer |
| Grammar-based | Dilbilgisi kurallarına göre üretir | SQL ifadeleri |
AFL (American Fuzzy Lop) ve libFuzzer, en bilinen coverage-guided fuzzing araçlarıdır. Güvenlik açığı araştırmacıları, fuzzing ile sıfırıncı gün (zero-day) açıklar bulur.
Fuzzing production'da mı, test'te mi çalışır?
Asla production’da. Fuzzing, programa kasıtlı olarak geçersiz/bozuk veri gönderir. Bu, production veritabanını bozabilir, hizmet çökertebilir. Fuzzing her zaman test/staging ortamında, izole edilmiş bir sanal makinede çalıştırılır. CI pipeline’ına eklenebilir ama her zaman ayrı bir job olarak, uzun süreli (gece boyu) çalışacak şekilde.
56.5 CI/CD Güvenlik Pipeline’ı
DevSecOps’un kalbi CI/CD pipeline’ıdır. Her commit, her pull request otomatik olarak güvenlik testinden geçer. Manuel denetime gerek yoktur.
GitHub Actions Örneği
# .github/workflows/security.yml
name: Security Pipeline
on: [push, pull_request]
permissions:
contents: read # En az yetki prensibi
jobs:
# 1. SAST: Statik kod analizi
bandit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # SHA ile sabitlemek daha guvenli
- name: Bandit ile Python kod tara
run: |
pip install bandit
bandit -r src/ -f json -o bandit-report.json || true
- name: HIGH severity varsa basarisiz ol
run: |
if grep -q '"issue_severity": "HIGH"' bandit-report.json; then
echo "HIGH severity guvenlik acigi bulundu!"
exit 1
fi
# 2. SCA: Bagimlilik taramasi
dependency-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: pip-audit calistir
run: |
pip install pip-audit
pip-audit --requirement requirements.txt
# 3. Secret tarama (commit hash ile pinle, @main ASLA)
secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Tam git history
- name: TruffleHog ile secret tara
uses: trufflesecurity/[email protected] # @main DEGIL, spesifik surum
# 4. Container tarama (Docker image)
container-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Docker image olustur
run: docker build -t app:${{ github.sha }} .
- name: Trivy ile image tara
uses: aquasecurity/[email protected] # @master DEGIL, spesifik surum
with:
image-ref: app:${{ github.sha }}
severity: CRITICAL,HIGH
exit-code: 1 # CRITICAL/HIGH varsa pipeline durur
Bu pipeline’da:
banditkodu statik olarak tararpip-auditbağımlılıkları kontrol edertrufflehogsecret sızıntısı arartrivyDocker image’ı tarar
Herhangi bir adımda HIGH/CRITICAL bulunursa pipeline durur. Kod üretime ulaşamaz.
Pipeline’ı kademeli kur. İlk hafta sadece “report” modunda çalıştır (uyarı ver ama pipeline’ı durdurma). Ekip tooling alıştığında “enforced” moda geç (pipeline’ı durdur). Bu, “security team broke my build” kültürel direncini azaltır.
56.6 Container ve IaC Güvenliği
Modern altyapı, Docker container ve Terraform/CloudFormation gibi Infrastructure as Code (IaC) üzerine kuruludur. Bunlarda da güvenlik açığı olabilir.
Docker Image Tarama
# KOTU Dockerfile
FROM python:3.11 # full image, cok buyuk, fazla saldiri yuzeyi
RUN apt-get update # build sirasinda root olarak calisir
COPY . /app # .env dosyasi da kopyalanir!
CMD ["python", "app.py"] # root user olarak calisir
# IYI Dockerfile
FROM python:3.11-slim@sha256:<digest> # Digest ile sabitle (tag degil)
RUN useradd -m appuser # root olmayan kullanici olustur
COPY --chown=appuser:appuser . /app
# .dockerignore ile .env, .git, __pycache__ dislanmali
USER appuser # root'tan cik, appuser olarak calis
HEALTHCHECK --interval=30s CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
CMD ["python", "app.py"]
Trivy ile container tarama:
# Docker image'i bilinen aciklar icin tara
trivy image app:latest
# Sadece CRITICAL ve HIGH aciklari goster
trivy image --severity CRITICAL,HIGH app:latest
# Cikti ornegi:
# app:latest (debian 11.8)
# Total: 23 (HIGH: 5, CRITICAL: 1)
#
# CRITICAL: openssl (CVE-2023-5363)
# HIGH: curl (CVE-2023-48695)
# HIGH: git (CVE-2023-45323)
IaC Tarama (Terraform)
# tfsec: Terraform kodunu guvenlik acisindan tara
tfsec src/terraform/
# Cikti ornegi:
# [AWS018] AWS S3 bucket is not encrypted
# src/terraform/storage.tf:12
# Impact: S3 bucket verileri sifresiz saklaniyor
# Resolution: server_side_encryption_configuration ekle
# checkov: Alternatif IaC tarayici
checkov -d src/terraform/
Distroless image nedir, neden daha güvenli?
Distroless image, içinde işletim sistemi paket yöneticisi (apt, yum), shell, debug araçları BARINDIRMAYAN minimal Docker image’dir. Sadece uygulama çalışması için gereken paylaşılan kütüphaneler ve uygulamanın kendisi vardır. Avantajı: saldırgan container’a girse bile shell yok, package manager yok, yeni araç indiremez. Saldırı yüzeyi minimumdadır. Google Distroless ve Chainguard Images en bilinen sağlayıcılardır.
SBOM'u pipeline'a nasıl eklerim?
CI/CD pipeline’ında her build’de SBOM üret ve artifact olarak sakla. Syft (container image için) veya cyclonedx (dil bazlı) araçlarını kullan. SBOM’u güncel tut: her yeni build’de yeni SBOM üret, eskisini arşivle. Yeni bir CVE yayınlandığında, en son SBOM’u al, etkilenen paket var mı diye sorgula. SBOM’u olmayan bir proje, bağımlılık krizinde günlerce manuel arama yapar.
- SAST, SCA, secret tarama pipeline'a entegre
- Docker image'da root yerine non-root kullanıcı kullan
- Slim veya distroless base image kullan
- Her build'de SBOM üret
- .env dosyasını Docker COPY ile kopyala
- Latest tag kullan (sürüm sabit değil)
- Pipeline'ı sadece report modda bırak (enforced'a geçmezsen anlamı yok)
- SAST false positive'lerini görmezden gel
Bir geliştirici, yeni bir özellik için requests kütüphanesinin eski bir sürümünü ekledi. Bu sürümde bilinen bir açık var (CVE-2024-1234, CVSS 9.8). Ekip hızlı shipping için pipeline’ı atladı, kodu direkt main branch’e merge etti. 1 hafta sonra otomatik bir tarayıcı, şirketin public API’sinde bu açığı buldu. Saldırgan, açığı sömürerek sunucuda kod çalıştırdı. SCA pipeline olsaydı, merge anında “requests 2.20.0’da CRITICAL açık, 2.31.0’a yükselt” derdi ve merge’i engellerdi. Pipeline, birkaç saniyelik gecikme kurtarır; ama milyonlarca liralık ihlal masrafını önler.
- SAST (Bandit/Semgrep) her PR’da otomatik çalışıyor
- SCA (pip-audit) bağımlılıkları CVE veritabanıyla kontrol ediyor
- Secret tarama (TruffleHog) pre-commit hook ve pipeline’da
- DAST (OWASP ZAP) staging ortamında haftalık çalışıyor
- Docker image’lar Trivy ile taranıyor
- IaC (Terraform) tfsec/checkov ile denetleniyor
- Container non-root kullanıcı ile çalışıyor
- SBOM her build’de üretiliyor ve saklanıyor
- Pipeline enforced modda (HIGH/CRITICAL = durdur)
- False positive’ler için baseline tanımlı
Gerçek olay: 2021’de Codecov adlı bir CI/CD aracı tedarik zinciri saldırısına uğradı. Saldırgan, Codecov’un bash uploader betiğini ele geçirdi ve binlerce şirketin CI/CD pipeline’ına sızdı. Sızan veriler arasında API anahtarları, token’lar ve gizli değişkenler vardı. Saldırı 2 ay fark edilmedi. Ders: CI/CD pipeline’ı güvenlik testi yapan bir araç bile olsa, kendisi de saldırı hedefidir. Tedarik zinciri güvenliği şarttır.
Benzetme: DevSecOps, bir otomobil fabrikasının kalite kontrol bandına benzer. Her parça (kod) monte edilirken (commit), kalite kontrol (SAST) kontrol eder. Boya sonrası (test), denetmen (DAST) aracı test eder. Yola çıkmadan (dağıtım), son muayene (secret scan) yapılır. Hiçbir adım atlanamaz. Atlanan adım, yolda kalmanın garantisidir.