CVE Takibi ve Linux Sistemlerde Yama Yönetimi
Bir gece yarısı telefon çalıyor ve ekibindeki birisi “hocam şu log’lara bir bak, garip bir şeyler var” diyor. Bakıyorsun, üç ay önce kapatılmış olması gereken bir CVE üzerinden sisteme sızılmış. Yama uygulanmamış, takip edilmemiş, kimse haberdar değil. Bu senaryo maalesef kurumsal dünyada çok yaygın. CVE takibi ve yama yönetimi, sysadmin’lerin en çok ertelediği ama en kritik konuların başında geliyor. Bu yazıda hem teorik altyapıyı hem de gerçek dünyada nasıl uygulayacağını adım adım anlatacağım.
CVE Nedir, Neden Önemli?
CVE (Common Vulnerabilities and Exposures), yazılım ve donanımlardaki güvenlik açıklarını standart bir formatta kataloglayan bir sistemdir. MITRE Corporation tarafından yönetilir ve her açığa CVE-YYYY-NNNNN formatında benzersiz bir kimlik atanır. Örneğin Log4Shell açığı CVE-2021-44228 olarak kayıtlıdır.
CVSS (Common Vulnerability Scoring System) puanı ise bir açığın ne kadar tehlikeli olduğunu 0-10 arasında skorlar:
- 0.1-3.9: Düşük (Low)
- 4.0-6.9: Orta (Medium)
- 7.0-8.9: Yüksek (High)
- 9.0-10.0: Kritik (Critical)
Bir sysadmin olarak CVSS puanı 7 ve üzeri olan her şeyi acil olarak ele alman gerekiyor. Kritik açıklar için ise saatler içinde aksiyon almak şart.
Linux Sistemlerde Açık Tespiti
Mevcut Paket Açıklarını Kontrol Etmek
Debian/Ubuntu tabanlı sistemlerde unattended-upgrades ve apt araçları temel güvenlik bilgisi sunar:
# Güvenlik güncellemelerini listele
apt list --upgradable 2>/dev/null | grep -i security
# Daha detaylı bilgi için
apt-get upgrade --dry-run | grep -i security
# Belirli bir paketin CVE bilgisini sorgula
apt-get changelog openssh-server | head -50
Red Hat/CentOS/Rocky Linux tarafında ise yum ve dnf çok daha güçlü güvenlik araçları sunar:
# Sadece güvenlik yamalarını listele
dnf check-update --security
# Kritik güncellemeleri filtrele
dnf updateinfo list --security --severity=Critical
# Belirli bir CVE için yama var mı kontrol et
dnf updateinfo list | grep CVE-2023-4911
# Yüklü paketlerin güvenlik geçmişini gör
dnf updateinfo info --security
OpenSCAP ile Uyumluluk Taraması
OpenSCAP, sistemini belirli güvenlik standartlarına göre tarayan güçlü bir araçtır. CIS Benchmark veya DISA STIG profilleriyle sisteminizi değerlendirebilirsiniz:
# OpenSCAP kurulumu (RHEL/Rocky)
dnf install openscap-scanner scap-security-guide -y
# Mevcut profilleri listele
oscap info /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml | grep "Profile"
# CIS L2 profiliyle tarama yap
oscap xccdf eval
--profile xccdf_org.ssgproject.content_profile_cis_server_l1
--report /tmp/scap-report.html
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
# HTML raporu oluştur ve insan okunabilir formata getir
oscap xccdf generate report /tmp/scap-results.xml > /tmp/report.html
Trivy ile Konteyner ve Sistem Taraması
Eğer Docker veya Kubernetes kullanıyorsan Trivy vazgeçilmez bir araç:
# Trivy kurulumu
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# Sistem paketlerini tara
trivy fs --security-checks vuln /
# Belirli bir Docker imajını tara
trivy image nginx:latest
# Sadece kritik ve yüksek açıkları filtrele
trivy image --severity HIGH,CRITICAL ubuntu:22.04
# JSON formatında çıktı al (otomasyon için)
trivy image --format json --output /tmp/trivy-report.json myapp:latest
CVE Takip Sistemi Kurmak
Vuls ile Otomatik CVE Taraması
Vuls, agentless çalışan ve sistemlerdeki CVE’leri otomatik takip eden açık kaynaklı bir araçtır. Birden fazla sunucuyu merkezi olarak yönetmek için idealdir:
# Vuls kurulumu için Go ortamı hazırla
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
# Vuls'u derle ve kur
go install github.com/future-architect/vuls@latest
# NVD veritabanını indir (bu biraz zaman alır)
go install github.com/kotakanbe/go-cve-dictionary@latest
go-cve-dictionary fetch nvd
# OVAL veritabanını indir
go install github.com/kotakanbe/goval-dictionary@latest
goval-dictionary fetch ubuntu 20.04 22.04
# Temel Vuls yapılandırması
cat > /etc/vuls/config.toml << 'EOF'
[cveDict]
type = "sqlite3"
sqliteDBPath = "/var/lib/cve-dictionary/cve.sqlite3"
[ovalDict]
type = "sqlite3"
sqliteDBPath = "/var/lib/goval-dictionary/oval.sqlite3"
[servers]
[servers.webserver01]
host = "192.168.1.10"
port = "22"
user = "vuls"
keyPath = "/root/.ssh/vuls_key"
[servers.dbserver01]
host = "192.168.1.20"
port = "22"
user = "vuls"
keyPath = "/root/.ssh/vuls_key"
EOF
# Tarama başlat
vuls scan
vuls report -format-full-text
Otomatik CVE Bildirim Scripti
Kritik CVE’leri anında haber almak için basit ama etkili bir script yazalım:
#!/bin/bash
# /usr/local/bin/cve-check.sh
# Her gece çalışacak CVE takip scripti
SEVERITY_THRESHOLD=7
SLACK_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
EMAIL="[email protected]"
LOG_FILE="/var/log/cve-check.log"
DATE=$(date '+%Y-%m-%d %H:%M')
echo "[$DATE] CVE kontrolü başladı" >> "$LOG_FILE"
# Debian/Ubuntu için güvenlik güncellemelerini topla
if command -v apt &>/dev/null; then
UPDATES=$(apt-get upgrade --dry-run 2>/dev/null | grep -c "^Inst.*security")
if [ "$UPDATES" -gt 0 ]; then
DETAILS=$(apt-get upgrade --dry-run 2>/dev/null | grep "^Inst.*security" | head -20)
MESSAGE="*[$HOSTNAME]* $UPDATES adet güvenlik güncellemesi bekliyor!n```n$DETAILSn```"
# Slack bildirimi gönder
curl -s -X POST -H 'Content-type: application/json'
--data "{"text":"$MESSAGE"}"
"$SLACK_WEBHOOK"
# E-posta bildirimi gönder
echo -e "Sunucu: $HOSTNAMEnTarih: $DATEnBekleyen güncellemeler:nn$DETAILS" |
mail -s "[$HOSTNAME] Güvenlik Güncellemesi Gerekli" "$EMAIL"
echo "[$DATE] $UPDATES güvenlik güncellemesi tespit edildi ve bildirim gönderildi" >> "$LOG_FILE"
fi
fi
# RHEL/Rocky için
if command -v dnf &>/dev/null; then
CRITICAL=$(dnf check-update --security --severity=Critical -q 2>/dev/null | grep -v "^$" | wc -l)
if [ "$CRITICAL" -gt 0 ]; then
echo "[$DATE] KRİTİK: $CRITICAL kritik güvenlik güncellemesi!" >> "$LOG_FILE"
# Slack ve mail bildirimi burada da eklenebilir
fi
fi
echo "[$DATE] CVE kontrolü tamamlandı" >> "$LOG_FILE"
# Script'i çalıştırılabilir yap ve cron'a ekle
chmod +x /usr/local/bin/cve-check.sh
# Her gece 02:00'da çalıştır
echo "0 2 * * * root /usr/local/bin/cve-check.sh" >> /etc/cron.d/cve-check
Yama Yönetimi Stratejisi
Test-Staging-Production Pipeline
Yamayı direkt production’a uygulamak ciddi riskler taşır. Doğru yaklaşım şu sırayla gitmektir:
- Test ortamı: Yama önce burada uygulanır, fonksiyonel testler çalıştırılır
- Staging ortamı: Production kopyasında doğrulama yapılır
- Production: Onaylanan yama uygulanır, rollback planı hazırda olur
Ansible ile Otomatik Yama Yönetimi
Yüzlerce sunucuyu elle yamalamak hem zaman kaybı hem de hata riski demektir. Ansible bu işi güvenle otomatize eder:
# patch-management.yml
---
- name: Linux Sunucularına Güvenlik Yamalarını Uygula
hosts: all
become: yes
vars:
reboot_required: false
patch_log: "/var/log/ansible-patches.log"
tasks:
- name: Mevcut tarihi kaydet
command: date '+%Y-%m-%d %H:%M:%S'
register: patch_date
changed_when: false
- name: Debian/Ubuntu - Güvenlik yamalarını uygula
apt:
upgrade: yes
update_cache: yes
only_upgrade: yes
dpkg_options: 'force-confold,force-confdef'
when: ansible_os_family == "Debian"
register: apt_result
- name: RHEL/Rocky - Güvenlik yamalarını uygula
dnf:
name: '*'
state: latest
security: yes
update_only: yes
when: ansible_os_family == "RedHat"
register: dnf_result
- name: Reboot gerekip gerekmediğini kontrol et (Debian)
stat:
path: /var/run/reboot-required
register: reboot_file
when: ansible_os_family == "Debian"
- name: Gerekiyorsa sistemi yeniden başlat
reboot:
msg: "Güvenlik yamaları sonrası yeniden başlatılıyor"
connect_timeout: 5
reboot_timeout: 300
pre_reboot_delay: 10
post_reboot_delay: 30
when: reboot_file.stat.exists is defined and reboot_file.stat.exists
- name: Yama logunu kaydet
lineinfile:
path: "{{ patch_log }}"
line: "{{ patch_date.stdout }} - Yama tamamlandı: {{ inventory_hostname }}"
create: yes
# Sadece belirli sunucu grubuna uygula
ansible-playbook patch-management.yml -l webservers --check # önce dry-run
ansible-playbook patch-management.yml -l webservers # sonra gerçek uygulama
# Belirli bir CVE için yama uygula
ansible-playbook patch-management.yml -l dbservers
--extra-vars "target_cve=CVE-2023-4911"
Kernel Güncellemesi ve Canlı Yama
Kernel güncellemesi için genellikle yeniden başlatma gerekir. Ancak kritik üretim sistemleri için kpatch veya ticari çözümler (Ksplice, KernelCare) canlı yama imkanı sunar:
# kpatch kurulumu ve kullanımı (RHEL/Rocky)
dnf install kpatch kpatch-dnf -y
# Mevcut canlı yamaları listele
kpatch list
# Otomatik canlı yama (dnf ile entegre)
dnf kpatch upgrade
# Yama durumunu kontrol et
kpatch info
# Mevcut kernel sürümünü ve yüklü yamaları göster
uname -r
rpm -qa | grep kpatch
Gerçek Dünya Senaryosu: Log4Shell Müdahalesi
Aralık 2021’de Log4Shell açığı (CVE-2021-44228) patlak verdiğinde, CVSS skoru 10.0 olan bu açık tüm dünyada panik yarattı. Bu tür bir senaryoda nasıl hareket etmeli?
#!/bin/bash
# log4shell-check.sh
# Sistemde Log4j kullanımını tespit et
echo "=== Log4Shell (CVE-2021-44228) Tespit Taraması ==="
echo "Tarih: $(date)"
echo ""
# JAR dosyalarını tara
echo "[+] JAR dosyaları aranıyor..."
find / -name "*.jar" -type f 2>/dev/null | while read jar; do
if unzip -l "$jar" 2>/dev/null | grep -q "JndiLookup.class"; then
echo "UYARI: Etkilenmiş sınıf bulundu: $jar"
# JAR içindeki log4j sürümünü tespit et
VERSION=$(unzip -p "$jar" META-INF/MANIFEST.MF 2>/dev/null | grep -i "implementation-version" | cut -d' ' -f2)
echo " Sürüm: $VERSION"
fi
done
# Maven/Gradle bağımlılıklarını kontrol et
echo ""
echo "[+] Maven pom.xml dosyaları aranıyor..."
find / -name "pom.xml" 2>/dev/null | xargs grep -l "log4j" 2>/dev/null | head -20
# Çalışan processlerde log4j kullanımı
echo ""
echo "[+] Çalışan processlerde log4j kontrolü..."
for pid in $(ls /proc | grep -E '^[0-9]+$'); do
if ls -la /proc/$pid/fd 2>/dev/null | grep -q "log4j"; then
echo "PID $pid log4j kullanıyor:"
cat /proc/$pid/cmdline 2>/dev/null | tr '' ' '
echo ""
fi
done
echo ""
echo "=== Tarama tamamlandı ==="
Yama Takip ve Raporlama
Merkezi Yama Veritabanı
Küçük bir SQLite veritabanıyla tüm yama geçmişini takip edebilirsiniz:
#!/bin/bash
# patch-tracker.sh - Yama kayıt sistemi
DB="/var/lib/patch-tracker/patches.db"
mkdir -p /var/lib/patch-tracker
# Veritabanını oluştur
sqlite3 "$DB" << 'EOF'
CREATE TABLE IF NOT EXISTS patches (
id INTEGER PRIMARY KEY AUTOINCREMENT,
hostname TEXT NOT NULL,
cve_id TEXT,
package_name TEXT NOT NULL,
old_version TEXT,
new_version TEXT,
applied_date TEXT NOT NULL,
applied_by TEXT,
status TEXT DEFAULT 'applied',
notes TEXT
);
CREATE TABLE IF NOT EXISTS pending_patches (
id INTEGER PRIMARY KEY AUTOINCREMENT,
hostname TEXT NOT NULL,
cve_id TEXT,
package_name TEXT NOT NULL,
severity TEXT,
detected_date TEXT NOT NULL,
deadline TEXT
);
EOF
# Yama kaydı ekle
add_patch() {
local cve=$1
local package=$2
local old_ver=$3
local new_ver=$4
sqlite3 "$DB" "INSERT INTO patches (hostname, cve_id, package_name, old_version, new_version, applied_date, applied_by)
VALUES ('$(hostname)', '$cve', '$package', '$old_ver', '$new_ver', '$(date +%Y-%m-%d)', '$(whoami)');"
echo "Yama kaydedildi: $package ($old_ver -> $new_ver)"
}
# Son 30 günün yama raporunu göster
show_report() {
echo "=== Son 30 Günün Yama Raporu ==="
sqlite3 -column -header "$DB"
"SELECT hostname, cve_id, package_name, old_version, new_version, applied_date
FROM patches
WHERE applied_date >= date('now', '-30 days')
ORDER BY applied_date DESC;"
}
case "$1" in
add) add_patch "$2" "$3" "$4" "$5" ;;
report) show_report ;;
*) echo "Kullanim: $0 {add|report}" ;;
esac
İzleme ve Alarm Mekanizmaları
Prometheus ve Alertmanager kullanıyorsan, bekleyen güvenlik güncellemelerini metrik olarak export edebilirsin:
#!/bin/bash
# security-metrics.sh
# Node Exporter textfile collector için güvenlik metrikleri
METRICS_FILE="/var/lib/node_exporter/textfile_collector/security.prom"
# Bekleyen güvenlik güncellemesi sayısı
if command -v apt &>/dev/null; then
PENDING=$(apt-get upgrade --dry-run 2>/dev/null | grep -c "^Inst.*security" || echo 0)
CRITICAL=$(apt-get upgrade --dry-run 2>/dev/null | grep -c "^Inst.*critical" || echo 0)
fi
if command -v dnf &>/dev/null; then
PENDING=$(dnf check-update --security -q 2>/dev/null | grep -v "^$" | wc -l || echo 0)
CRITICAL=$(dnf check-update --security --severity=Critical -q 2>/dev/null | grep -v "^$" | wc -l || echo 0)
fi
# Son yeniden başlatmadan bu yana geçen gün
UPTIME_DAYS=$(awk '{print int($1/86400)}' /proc/uptime)
# Metrikleri yaz
cat > "$METRICS_FILE" << EOF
# HELP security_pending_updates Bekleyen güvenlik güncellemesi sayısı
# TYPE security_pending_updates gauge
security_pending_updates{hostname="$(hostname)"} ${PENDING:-0}
# HELP security_critical_updates Kritik güvenlik güncellemesi sayısı
# TYPE security_critical_updates gauge
security_critical_updates{hostname="$(hostname)"} ${CRITICAL:-0}
# HELP system_uptime_days Son yeniden başlatmadan bu yana geçen gün
# TYPE system_uptime_days gauge
system_uptime_days{hostname="$(hostname)"} $UPTIME_DAYS
EOF
echo "Metrikler güncellendi: $METRICS_FILE"
En İyi Pratikler
Yıllar içinde öğrendiğim ve gerçekten işe yarayan pratikler şunlar:
- SLA tanımla: Kritik CVE’ler için 48 saat, yüksek için 7 gün, orta için 30 gün gibi net süreler belirle ve buna uy
- Değişiklik penceresi kullan: Yamaları rastgele değil, belirlenmiş maintenance window’larda uygula
- Rollback planın her zaman hazır olsun: Snapshot al, yedeği kontrol et, sonra yamala
- Bağımlılıkları izle: Bir paketi güncellemek başka bir şeyi bozabilir, bağımlılık grafiğini anla
- Kernel güncellemesini erteleme: Kernel yamaları en çok ertelenen ama en kritik olanlar, reboot korkusunu yenmek gerekiyor
- CVE kaynaklarını takip et: NVD (nvd.nist.gov), CERT/CC, vendor security bulletinleri ve distro security mailing listleri
- Önceliklendirme yap: Her açığı aynı aciliyetle ele almanın anlamı yok, risk değerlendirmesi yaparak önceliklendir
- Dokümante et: Hangi yamayı ne zaman neden uyguladığını kayıt altına al, audit süreçlerinde hayat kurtarır
Sonuç
CVE takibi ve yama yönetimi, “yapılacaklar listesinin en altında kalan” bir konu olmaktan çıkıp güvenlik stratejisinin merkezine alınması gereken bir süreç. Tek bir yamayı atlaman, sistemine aylar sonra sızmaya yetebilir ve bu tür olayların ortalama tespit süresi hala 200 günün üzerinde.
Bu yazıda anlattığım araçları ve script’leri kullanarak başlangıç düzeyinde bir CVE takip altyapısı kurabilirsin. Küçük ortamlar için Vuls + Ansible + Slack bildirimleri yeterli bir çözüm sunar. Daha büyük ortamlarda Tenable, Qualys veya Rapid7 gibi ticari araçları değerlendirebilirsin.
En önemli şey ise şu: Otomatize edemediğin şeyi tutarlı şekilde yapamazsın. Yama yönetimini elle takip etmeye çalışmak kaçınılmaz olarak açıklar bırakır. Sistematik, otomatize ve belgelenmiş bir süreç kur, düzenli olarak test et ve ekibinle paylaş. Gece saat 03:00’da telefon almak istemiyorsan, bu işi ciddiye almanın tam zamanı.
