ELK Stack ile Güvenlik Log Analizi ve SIEM Kurulumu
Şirkette SIEM çözümü için bütçe yoksa ne yaparsın? Splunk’ın lisans maliyetlerine bakınca çoğu KOBİ ve hatta orta ölçekli enterprise firmaların geri adım attığını görüyoruz. İşte tam bu noktada ELK Stack devreye giriyor. Elasticsearch, Logstash ve Kibana üçlüsü, doğru yapılandırıldığında ticari SIEM çözümlerine ciddi rakip olabiliyor. Ben bu yazıda size kurumsal bir ortamda ELK’ı SIEM olarak nasıl kullandığımızı, hangi tuzaklarla karşılaştığımızı ve günün sonunda ne elde ettiğimizi aktaracağım.
ELK Stack’i Neden SIEM Olarak Kullanmalısınız?
Açık kaynak demek “bedava” demek değil, bunu baştan söyleyeyim. ELK Stack’i ayakta tutmak ciddi operasyonel maliyet gerektiriyor. Ama ticari alternatiflere kıyasla veri hacmine göre lisanslama olmadığı için özellikle log yoğun ortamlarda çok daha avantajlı. Günde 50 GB log üreten bir ortamda Splunk lisansı yılda yüz binlerce dolara gidebiliyor.
Güvenlik açısından ELK’ın güçlü yanları:
- Gerçek zamanlı log toplama ve indeksleme: Olaylar saniyeler içinde aranabilir hale geliyor
- Esnek sorgulama: KQL (Kibana Query Language) ile karmaşık korelasyon sorguları yazabiliyorsunuz
- Elastic Security modülü: Artık neredeyse hazır SIEM özellikleri sunuyor
- Beats ailesi: Filebeat, Winlogbeat, Auditbeat gibi hafif ajanlar ile her platformdan log toplayabiliyorsunuz
- Özelleştirilebilir alarmlar: Watcher veya Kibana Alerts ile tetikleyici kurallar tanımlayabiliyorsunuz
Mimari Tasarım: Güvenlik Odaklı ELK Kurulumu
Prodüksiyon ortamında güvenlik log analizi için önerdiğim minimal mimari şu şekilde:
[Log Kaynakları] -> [Beats Ajanları] -> [Logstash Cluster] -> [Elasticsearch Cluster] -> [Kibana]
|
[Kafka Buffer]
Kafka katmanını neden ekliyorum? Logstash cluster’ı devre dışı kaldığında veya yoğun trafik anlarda logları kaybetmemek için. Güvenlik loglarında veri kaybı kabul edilemez.
Elasticsearch Güvenlik Yapılandırması
İlk kurulumda çoğu kişinin atladığı kritik nokta: Elasticsearch’ü varsayılan ayarlarla bırakmak. elasticsearch.yml dosyasında şunlar olmazsa olmaz:
# /etc/elasticsearch/elasticsearch.yml
cluster.name: siem-cluster
node.name: es-node-01
# Güvenlik ayarları - MUTLAKA açık olmalı
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12
# HTTP SSL
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: http.p12
# Audit logging - kimin ne sorguladığını takip etmek için
xpack.security.audit.enabled: true
xpack.security.audit.logfile.events.include: ["access_denied", "authentication_failed", "connection_denied", "tampered_request", "run_as_denied", "anonymous_access_denied"]
# JVM heap - log analizinde bellek kritik
# -Xms16g
# -Xmx16g
network.host: 0.0.0.0
http.port: 9200
# Shard ve replica ayarları
index.number_of_shards: 3
index.number_of_replicas: 1
Logstash Pipeline Yapılandırması
Güvenlik loglarını işlerken Logstash pipeline tasarımı kritik. Burada ayrı pipeline’lar kullanmak yönetimi kolaylaştırıyor:
# /etc/logstash/conf.d/security-pipeline.conf
input {
beats {
port => 5044
ssl => true
ssl_certificate => "/etc/logstash/certs/logstash.crt"
ssl_key => "/etc/logstash/certs/logstash.key"
ssl_certificate_authorities => ["/etc/logstash/certs/ca.crt"]
ssl_verify_mode => "force_peer"
}
kafka {
bootstrap_servers => "kafka-01:9092,kafka-02:9092"
topics => ["security-logs", "windows-events", "firewall-logs"]
group_id => "logstash-siem"
codec => json
}
}
filter {
# Windows Event Log işleme
if [agent][type] == "winlogbeat" {
mutate {
add_field => { "log_source" => "windows" }
}
# Başarısız giriş denemelerini işaretle
if [event][code] == 4625 {
mutate {
add_tag => ["failed_login"]
add_field => { "security_event" => "authentication_failure" }
}
}
# Hesap kilitleme
if [event][code] == 4740 {
mutate {
add_tag => ["account_lockout"]
add_field => { "security_event" => "account_locked" }
add_field => { "severity" => "high" }
}
}
# Yeni servis kurulumu
if [event][code] == 7045 {
mutate {
add_tag => ["new_service"]
add_field => { "security_event" => "service_installed" }
add_field => { "severity" => "medium" }
}
}
}
# Linux auth log işleme
if [log][file][path] =~ "/var/log/auth.log" or [log][file][path] =~ "/var/log/secure" {
grok {
match => {
"message" => [
"%{SYSLOGTIMESTAMP:timestamp} %{HOSTNAME:hostname} sshd[%{NUMBER:pid}]: Failed password for %{USERNAME:failed_user} from %{IP:src_ip} port %{NUMBER:src_port}",
"%{SYSLOGTIMESTAMP:timestamp} %{HOSTNAME:hostname} sshd[%{NUMBER:pid}]: Accepted %{WORD:auth_method} for %{USERNAME:user} from %{IP:src_ip} port %{NUMBER:src_port}"
]
}
}
if "_grokparsefailure" not in [tags] {
geoip {
source => "src_ip"
target => "geoip"
}
mutate {
add_field => { "log_source" => "linux_auth" }
}
}
}
# IP reputation check için basit liste
if [src_ip] {
translate {
field => "src_ip"
destination => "threat_intel"
dictionary_path => "/etc/logstash/threat_intel/known_bad_ips.yml"
fallback => "unknown"
}
if [threat_intel] != "unknown" {
mutate {
add_tag => ["threat_intel_match"]
add_field => { "severity" => "critical" }
}
}
}
# Timestamp normalizasyonu
date {
match => ["timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss"]
target => "@timestamp"
}
}
output {
if "failed_login" in [tags] or "account_lockout" in [tags] {
elasticsearch {
hosts => ["https://es-01:9200", "https://es-02:9200"]
index => "siem-auth-events-%{+YYYY.MM.dd}"
user => "logstash_writer"
password => "${LOGSTASH_ES_PASSWORD}"
ssl => true
cacert => "/etc/logstash/certs/ca.crt"
}
}
elasticsearch {
hosts => ["https://es-01:9200", "https://es-02:9200"]
index => "siem-logs-%{+YYYY.MM.dd}"
user => "logstash_writer"
password => "${LOGSTASH_ES_PASSWORD}"
ssl => true
cacert => "/etc/logstash/certs/ca.crt"
}
}
Kritik Güvenlik Senaryoları ve Korelasyonlar
Brute Force Saldırısı Tespiti
Gerçek hayatta en çok karşılaştığımız saldırı türlerinden biri. Kibana’da şu KQL sorgusu ile anlık tespiti yapabilirsiniz:
event.code: 4625 AND @timestamp > now-15m
Ama bunu daha da güçlendirmek için Kibana’da Transform kullanıyoruz. Aynı kaynak IP’den belirli bir sürede kaç başarısız giriş denemesi geldiğini hesaplayan bir transform:
PUT _transform/brute_force_detection
{
"source": {
"index": "siem-auth-events-*",
"query": {
"bool": {
"filter": [
{ "term": { "security_event": "authentication_failure" } },
{ "range": { "@timestamp": { "gte": "now-1h" } } }
]
}
}
},
"pivot": {
"group_by": {
"src_ip": { "terms": { "field": "src_ip" } },
"target_host": { "terms": { "field": "hostname" } }
},
"aggregations": {
"failed_attempts": { "value_count": { "field": "event.code" } },
"unique_users": { "cardinality": { "field": "failed_user" } },
"last_attempt": { "max": { "field": "@timestamp" } }
}
},
"dest": {
"index": "siem-brute-force-summary"
},
"frequency": "5m"
}
Winlogbeat ile Windows Event Log Toplama
Active Directory ortamlarında kritik event ID’leri izlemek şart. Winlogbeat yapılandırması:
# winlogbeat.yml
winlogbeat.event_logs:
- name: Security
event_id: 4624, 4625, 4634, 4648, 4672, 4720, 4726, 4728, 4740, 4756, 7045
level: critical, error, warning, information
- name: System
event_id: 7034, 7035, 7036, 7040, 7045
- name: Application
ignore_older: 72h
- name: Microsoft-Windows-PowerShell/Operational
event_id: 4103, 4104, 4105, 4106
- name: Microsoft-Windows-Sysmon/Operational
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
output.logstash:
hosts: ["logstash-01:5044", "logstash-02:5044"]
loadbalance: true
ssl.certificate_authorities: ["/etc/beats/certs/ca.crt"]
ssl.certificate: "/etc/beats/certs/winlogbeat.crt"
ssl.key: "/etc/beats/certs/winlogbeat.key"
PowerShell event ID 4104 özellikle önemli. Obfuscated PowerShell komutlarını yakalamak için bu event’i izlemek gerekiyor. Ransomware saldırılarının büyük çoğunluğu PowerShell üzerinden geliyor.
Linux Auditbeat ile Sistem Çağrısı İzleme
# auditbeat.yml
auditbeat.modules:
- module: auditd
audit_rules: |
# Kimlik bilgilerini okuyan işlemler
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
# Sudo kullanımı
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers
# Kritik binary değişiklikleri
-w /usr/bin/passwd -p x -k passwd_modification
-w /usr/sbin/useradd -p x -k useradd
-w /usr/sbin/userdel -p x -k userdel
# Ağ bağlantıları
-a always,exit -F arch=b64 -S connect -k network_connect
# Cron değişiklikleri
-w /var/spool/cron -p wa -k cron
-w /etc/cron.d/ -p wa -k cron
- module: file_integrity
paths:
- /bin
- /usr/bin
- /sbin
- /usr/sbin
- /etc
recursive: true
exclude_files:
- '(?i).sw[nop]$'
- '~$'
- '/proc$'
- module: system
datasets:
- host
- login
- package
- process
- socket
- user
state.period: 12h
user.detect_password_changes: true
Kibana’da SIEM Dashboard Oluşturma
Dashboard tasarımında en önemli nokta: SOC analistinin ekrana bakıp 30 saniyede durumu anlaması gerekiyor. Karmaşık, bilgi yükleyen dashboardlar yerine hedefli, aksiyon alınabilir görünümler tercih edin.
Mutlaka bulunması gereken bileşenler:
- Security Overview: Son 24 saatte kritik event sayısı, trend grafiği
- Authentication Map: Coğrafi dağılım haritası, anormal konumlardan girişler
- Top Threatened Assets: En çok hedef alınan sunucular/kullanıcılar
- Failed Logins by User: Kilitlenme eşiğine yaklaşan hesaplar
- Threat Intelligence Hits: Bilinen kötü IP’lerden gelen trafikler
Kibana Watcher ile Otomatik Alarm
PUT _watcher/watch/brute_force_alert
{
"trigger": {
"schedule": {
"interval": "5m"
}
},
"input": {
"search": {
"request": {
"indices": ["siem-auth-events-*"],
"body": {
"query": {
"bool": {
"filter": [
{ "term": { "security_event": "authentication_failure" } },
{ "range": { "@timestamp": { "gte": "now-10m" } } }
]
}
},
"aggs": {
"by_ip": {
"terms": { "field": "src_ip", "size": 10 },
"aggs": {
"attempt_count": { "value_count": { "field": "src_ip" } }
}
}
}
}
}
}
},
"condition": {
"script": {
"source": "return ctx.payload.aggregations.by_ip.buckets.stream().anyMatch(b -> b.attempt_count.value > 20);"
}
},
"actions": {
"send_alert": {
"webhook": {
"method": "POST",
"url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
"body": "{"text": "SIEM Alert: Brute force saldırısı tespit edildi! Kaynak IP: {{#ctx.payload.aggregations.by_ip.buckets}}{{key}}: {{attempt_count.value}} deneme {{/ctx.payload.aggregations.by_ip.buckets}}"}"
}
}
}
}
Index Lifecycle Management ile Log Saklama Politikası
Güvenlik loglarını ne kadar saklayacaksınız? Hukuki gereklilikler açısından 1 yıl minimum, bazı sektörlerde 3-5 yıl zorunlu olabiliyor. ILM ile hem maliyeti kontrol altında tutabilir hem de compliance gereksinimlerini karşılayabilirsiniz:
# ILM policy oluşturma
curl -X PUT "https://localhost:9200/_ilm/policy/siem-log-policy"
-H "Content-Type: application/json"
-u elastic:$ES_PASSWORD
--cacert /etc/elasticsearch/certs/ca.crt
-d '{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_age": "1d",
"max_size": "50gb"
},
"set_priority": { "priority": 100 }
}
},
"warm": {
"min_age": "7d",
"actions": {
"shrink": { "number_of_shards": 1 },
"forcemerge": { "max_num_segments": 1 },
"set_priority": { "priority": 50 },
"allocate": {
"require": { "data": "warm" }
}
}
},
"cold": {
"min_age": "30d",
"actions": {
"set_priority": { "priority": 0 },
"allocate": {
"require": { "data": "cold" }
}
}
},
"delete": {
"min_age": "365d",
"actions": {
"delete": {}
}
}
}
}
}'
Performans ve Ölçeklendirme Notları
Birkaç yıl önce ilk kurulumda yaptığımız hatalar:
- Mapping explosion: Her yeni log formatı için dinamik mapping açık bırakıldığında Elasticsearch shard başına binlerce field oluşturabilir.
dynamic: strictya dadynamic: falsekullanın, sadece bilinen fieldları kabul edin. - Shard boyutu: Güvenlik loglarında shard başına 30-50 GB ideal. Çok küçük shardlar overhead yaratır, çok büyük shardlar recovery süresini uzatır.
- Heap ayarları: JVM heap’i toplam RAM’in yarısına eşitleyin ama 32 GB’ı geçmeyin. 32 GB üzerinde compressed ordinary object pointer optimizasyonu devre dışı kalıyor.
- Logstash worker sayısı:
pipeline.workersdeğerini CPU core sayısına eşitleyin. Log parsing CPU bound bir işlem.
Güvenlik Operasyonu: Günlük Rutin
ELK SIEM’i kurduktan sonra asıl iş başlıyor. Sabah mesaiye geldiğimde ilk yaptığım şeyler:
- Gece boyunca tetiklenen Watcher alarmlarını kontrol etmek
- Threat intelligence match sayısına bakmak, artış var mı?
- Yeni servis kurulumu event’lerini gözden geçirmek (Windows Event 7045)
- Kritik sunuculara gece yarısı yapılan başarılı girişleri incelemek
- Auditbeat’ten gelen dosya bütünlüğü değişikliklerine bakmak
Bu rutini Kibana’da otomatikleştirmek mümkün. Scheduled reporting ile her sabah e-posta ile özet rapor alabilirsiniz. Elastic Security’nin ML tabanlı anomali tespiti de zamanla ortamınızı öğrenerek gürültüyü azaltıyor.
Sonuç
ELK Stack ile gerçek bir SIEM kurmak, Kibana’yı açıp birkaç dashboard oluşturmaktan çok daha fazlasını gerektiriyor. Doğru pipeline tasarımı, normalize edilmiş veri modeli, güvenli iletişim kanalları ve düzenli bakım olmadan sisteminiz ya veri kaybeder ya da arama yapılamaz hale gelir.
Ama doğru yapılandırıldığında ne elde ediyorsunuz? Günde milyonlarca event içinden saniyeler içinde anlamlı korelasyonlar çıkarabildiğiniz, tehdit avı yapabildiğiniz, uyumluluk raporları üretebildiğiniz bir platform. Üstelik veri hacminize göre lisans ödemeden.
En büyük tavsiyem: Başlangıçta kapsamı dar tutun. Tüm logları bir anda almaya çalışmak yerine en kritik kaynakları önce alın, bunları düzgün çalıştırın, sonra genişletin. Büyük patlamayla başlayıp yönetilemez hale gelen birçok ELK SIEM projesi gördüm. Küçük ama sağlam temelli bir kurulum her zaman daha değerlidir.
