İçeriğe atla
0 XP 0
13 dkderinleşmeyle 14 dk50 XP6 etkinlik

Splunk SPL temelleri

Bu derste
  • SPL ile Splunk'ta başarısız girişleri süzer, kaynağa göre sayar, zaman çizelgesine döker ve bilinen adres listesiyle zenginleştirirsin.
  • join yerine neden stats, ham arama yerine ne zaman tstats seçildiğini de göreceksin.

Puan bütün etkinlikleri cevaplayınca hesaba yazılır. Bu dersi tamamlayınca +50 XP alacaksın. Giriş yapmadan ilerlersen puan yalnız bu tarayıcıda durur.

Altay Kargo'nun SOC ekibi her gün yüz milyonlarca satır kayıt alır. Bu kadar veriyi elle okumak mümkün değildir. Splunk kullanan ekipler kayda SPL ile soru sorar. SPL, Search Processing Language adının kısaltmasıdır ve Linux borusuyla aynı mantığı taşır.

Soldaki komutun çıktısı, boru işaretiyle sağdaki komutun girdisi olur. Bu derste önce Splunk'ın veriyi nerede ve nasıl tuttuğunu göreceksin. Sonra bir kaba kuvvet denemesini arayacak, sayacak ve zaman çizelgesine dökeceksin.

Hangi komutun pahalı olduğunu ve sorgunun en çok nerede hata yaptığını da öğreneceksin. Ders boyunca hep aynı soruya döneceksin: gece vardiyasında kim, hangi adresten, kaç kez giriş denedi?

Splunk veriyi nerede tutar

Splunk'ta veri üç rol arasında akar. Forwarder, izlenen sunucuda çalışan küçük bir ajandır. Dosyayı ya da olay günlüğünü okur ve indexer'a yollar.

Indexer gelen akışı olaylara böler, her olayın zaman damgasını çıkarır ve diske yazar. Yazarken bir de terim dizini kurar; aramalar en çok bu dizin sayesinde hızlanır. Search head, analistin sorgu yazdığı arayüzdür. Sorguyu indexer'lara dağıtır ve gelen sonuçları birleştirir.

Küçük kurulumlarda üç rol tek makinede durur. Büyük kurulumlarda her biri ayrı bir kümedir. Bu ayrım sorgu yazarken işine yarar. Sorgunun ilk satırı indexer'da çalışır ve diskten ne okunacağına karar verir.

Kaynaklarsunucu, uçToplayıcıagentSIEMnormalleştirmeKuraltespitAlarmanalist
Kaynaktan alarma uzanan akış. Splunk'ta toplayıcı rolünü forwarder üstlenir; indexer veriyi yazar, search head sorguyu çalıştırır.

Her olay Splunk'a girerken birkaç varsayılan alan alır. _time olayın zaman damgasıdır ve her arama onu kullanır. host olayı üreten makinenin adıdır. source olayın okunduğu dosya ya da kanaldır.

sourcetype kaydın biçimini söyler; Splunk satırı bu bilgiye göre ayrıştırır. index verinin yazıldığı mantıksal kovadır. _raw ise olayın ham metnini taşır. Bu alanlar diske yazılırken dizine girer ve aramada en ucuz süzgeçlerdir.

src_ip ya da user gibi alanlar çoğu kurulumda arama anında çıkarılır. Splunk her olayın ham metnini okur ve deseni yeniden uygular. Aynı soruyu index ve sourcetype ile daraltırsan okunan veri belirgin biçimde azalır.

Etkinlik 1 / 6

Splunk'ın varsayılan alanını taşıdığı bilgiyle eşleştir.

Soldan bir tane seç, sağdan eşini seç. Kullanılmış bir seçeneği yeniden seçersen yeni öğeye taşınır.

İlk arama: süz, say, sırala

En sade arama alan-değer eşleşmesidir: index=guvenlik sourcetype=linux_secure "Failed password". Terimler arasına işleç yazmazsan Splunk AND varsayar. Yani yan yana duran terimlerin hepsi aynı olayda geçmelidir.

Mantıksal işleçler AND, OR ve NOT büyük harfle yazılır. Küçük harfli or yazarsan Splunk onu işleç değil, aranacak bir kelime sayar. Sorgu hata vermez, yalnız beklediğin olayları getirmez.

NOT yalnız hemen ardındaki terime uygulanır; birden çok terimi dışlamak için parantez kullanırsın. search komutu OR'u AND'den önce değerlendirir. where ve eval ise AND'i önce değerlendirir. Karmaşık bir koşulda parantez yazarsan bu farkı düşünmen gerekmez.

Boru işaretinden sonra gelen komutlar sonucu biçimlendirir. stats sayar ve toplar. table yalnız seçtiğin sütunları gösterir. eval hesaplanmış yeni bir alan üretir.

sort sıralar, where sonucu bir koşulla daraltır. Komut adlarında büyük küçük harf önemli değildir. Arama terimleri ve alan=değer aramasındaki değerler de varsayılan olarak harfe duyarsızdır.

status=failed ile status=FAILED aynı olayları getirir. Alan adları ise harfe duyarlıdır: src_ip ile SRC_IP iki ayrı alandır. where ve eval içindeki metin karşılaştırmaları da harfe duyarlıdır. Aramada tek bir yazımı istersen CASE() yönergesini kullanırsın.

index=guvenlik sourcetype=linux_secure "Failed password" earliest=-24h
| rex "for (invalid user )?(?<hesap>\S+) from (?<src_ip>[0-9.]+) port"
| stats count AS deneme, dc(hesap) AS farkli_hesap by src_ip
| sort -deneme
| head 5

src_ip          deneme  farkli_hesap
203.0.113.19       120           118
198.51.100.77       96             2
10.20.30.44          3             1
Başarısız SSH girişlerini kaynak adrese göre sayan sorgu ve çıktısı.

Sorguyu satır satır oku. İlk satır aramayı guvenlik indeksine, linux_secure biçimine ve son yirmi dört saate daraltır. linux_secure, Linux kimlik doğrulama kaydı için yaygın kullanılan biçim adıdır.

İkinci satırda rex devreye girer. rex ham metne düzenli ifade uygular ve adlı yakalama gruplarını alana çevirir. (?<src_ip>...) grubu, from kelimesinden sonraki adresi src_ip alanına yazar.

(invalid user )? kısmı isteğe bağlıdır. Sistemde olmayan bir ad denendiğinde araya giren iki kelimeyi yutar.

stats iki değer hesaplar: count deneme sayısını, dc(hesap) kaç farklı hesabın denendiğini verir. sort -deneme büyükten küçüğe dizer, head 5 ilk beş satırı bırakır.

Çıktıyı okurken iki sütuna birlikte bak. 203.0.113.19 yüz yirmi deneme yapmış ve neredeyse her denemede başka bir hesap seçmiş. Bu desen parola püskürtmedir: birkaç yaygın parola, uzun bir hesap listesine denenir.

198.51.100.77 ise iki hesaba doksan altı deneme yapmış. Bu da parola tahminidir. 10.20.30.44 iç ağdan gelen üç denemedir ve büyük olasılıkla parolasını unutan bir çalışana aittir.

MITRE ATT&CK iki deseni T1110 tekniğinin altında ayrı adlandırır. T1110.001 parola tahmini, T1110.003 parola püskürtmedir. Sorgu senin yerine karar vermez, ama kararın dayanacağı sayıları önüne koyar.

Etkinlik 2 / 6

index=guvenlik sourcetype=kimlik "Failed password" | stats count by src_ip sorgusu ne üretir?

Zaman penceresi ve zaman çizelgesi

SPL her aramayı bir zaman penceresiyle sınırlar. Arayüzdeki zaman seçici bunu görsel olarak yapar. Sorgunun içinde ise earliest ve latest değiştiricilerini yazarsın.

earliest=-24h latest=now son yirmi dört saati kapsar. -15m son on beş dakikayı alır. -7d@d yedi gün geriye gider ve sonucu günün başına yuvarlar. @ işareti saati keser; böylece dünkü raporla bugünkü rapor aynı sınırdan başlar.

Sorguya yazdığın earliest, zaman seçicideki değeri geçersiz kılar. Dar pencere yalnız doğruluk için gerekli değildir. Splunk veriyi zamana göre ayrılmış kovalarda saklar. Pencere daraldıkça açılması gereken kova sayısı da azalır.

index=guvenlik sourcetype=linux_secure "Failed password" earliest=-6h
| rex "from (?<src_ip>[0-9.]+) port"
| timechart span=5m count by src_ip limit=3

_time             203.0.113.19  198.51.100.77  10.20.30.44  OTHER
2026-09-30 02:00             0              4            0      1
2026-09-30 02:05            61              5            0      0
2026-09-30 02:10            59              4            1      0
2026-09-30 02:15             0              5            0      2
Başarısız denemeleri beş dakikalık dilimlerde adrese göre sayan sorgu ve çıktının ilk dört satırı.

timechart, stats'ın zamana bölünmüş hâlidir. span=5m olayları beş dakikalık dilimlere ayırır. count by src_ip her adres için ayrı bir sütun açar. limit=3 en çok olay üreten üç adresi bırakır, kalanları OTHER sütununda toplar.

Görselleştirme sekmesinde bu tablo bir çizgi grafiğe dönüşür. Şimdi 203.0.113.19 sütununa bak. On dakika boyunca her dilimde altmış civarı deneme var, sonra sessizlik geliyor.

Kısa ve sert bir dalga, otomatik bir aracın izidir. 198.51.100.77 ise düşük ama sürekli bir hızla deniyor. Yavaş deneme, hesap kilitleme eşiğinin altında kalmak için seçilir. Tek bir toplam sayıya bakan analist bu farkı göremez.

Zamanı gruplamanın yanında süzmek için de kullanırsın. eval saat=tonumber(strftime(_time, "%H")) olayın saatini sayı olarak yeni bir alana yazar. Ardından where saat < 7 yazarsan yalnız gece yarısı ile sabah yedi arasındaki olaylar kalır.

İlk ve son görülme zamanı için stats min(_time) AS ilk, max(_time) AS son by hesap yazarsın. Sonuç Unix zamanı olarak gelir, yani 1790735091 gibi bir sayıdır. convert ctime(ilk) ctime(son) bu sayıları okunur tarihe çevirir. Olay notuna "ilk deneme 02.05, son deneme 02.14" yazmak bu iki satırla kolaylaşır.

Etkinlik 3 / 6

Son bir saatteki kayıtları aramak için sorguya earliest=____ eklersin.

Pahalı komutlar ve hızlı yollar

İki kaynaktaki veriyi birleştirmek için SPL'de join komutu vardır. join pahalıdır ve büyük veride sorguyu yavaşlatır. Sağ taraftaki alt aramanın döndürebileceği satır sayısı da sınırlıdır; sınırı aşan satırlar sonuca girmez.

Çoğu durumda aynı sonucu ortak bir alan üzerinden stats ile alırsın. İki aramayı OR ile tek aramada birleştirir, sonra stats ile ortak alana göre gruplarsın. transaction komutu da aynı sınıftadır.

Olayları oturumlara toplar, ama bunun için çok sayıda olayı bellekte tutar. Oturumun süresi gerekiyorsa stats min(_time) ve max(_time) çoğu zaman yeter. Milyonlarca satırlık bir indekste bu tercih dakikalarla saniyeler arasındaki farkı belirler.

tstats ise hız için vardır. Olayları tek tek okumaz, indexer'ın kurduğu tsidx dizin dosyalarına bakar. | tstats count where index=guvenlik by host, sourcetype sorgusu büyük bir indeksi ham olaylara dokunmadan sayar. Baştaki boru işareti şarttır.

tstats veri üreten bir komuttur ve aramanın ilk komutu olarak yazılır. Bedeli de vardır: yalnız dizine yazılmış alanları görür. Varsayılan kurulumda bunlar index, host, source, sourcetype ve _time gibi alanlardır; dizin anında çıkarılan özel alanlar da bu listeye girer.

Arama anında çıkarılan src_ip gibi alanlar where içinde kullanılamaz. Hızlandırılmış bir veri modeli varsa tstats onun alanlarını da okur. En sık iki işte kullanılır: kayıt göndermeyi bırakan makineyi bulmak ve veri modeli üstünde geniş tarama yapmak.

index=guvenlik sourcetype=linux_secure "Accepted password" earliest=-24h
| rex "for (?<hesap>\S+) from (?<src_ip>[0-9.]+) port"
| lookup bilinen_adresler.csv ip AS src_ip OUTPUT sahip
| where isnull(sahip)
| table _time host hesap src_ip

_time                host   hesap    src_ip
2026-09-30 02:14:51  web01  destek2  203.0.113.19
Başarılı girişleri bilinen adres listesiyle karşılaştıran sorgu. Listede olmayan tek bir adres kaldı.

Bu sorgu başarısız değil, başarılı girişlere bakar. lookup komutu bilinen_adresler.csv dosyasını bir tablo gibi açar. Dosyada ip ve sahip sütunları vardır; ofis çıkışları, VPN havuzu ve yedekleme sunucusu burada durur.

ip AS src_ip, dosyadaki ip sütununu olaydaki src_ip alanıyla eşler. OUTPUT sahip, eşleşme bulunursa sahip alanını olaya ekler. Eşleşme yoksa alan boş kalır.

where isnull(sahip) yalnız tanınmayan adresten gelen girişleri bırakır. Sonuçta tek satır kaldı: destek2 hesabı gece 02.14'te dış bir adresten girmiş. Önceki tabloda aynı adresin yüz yirmi deneme yaptığını görmüştün. Bu satır püskürtmenin bir hesapta tuttuğunu gösterir ve olay müdahalesini başlatır.

Derinleş:tsidx: Splunk neden bazı aramalarda hızlıdır

Indexer bir olayı yazarken iki şey üretir. Biri sıkıştırılmış ham veridir. Öbürü tsidx adlı zaman serisi dizinidir. tsidx, olaylarda geçen her terimi ve o terimin hangi olaylarda geçtiğini tutar.

"Failed password" araması önce bu dizine bakar. Her kovanın yanında bir de Bloom filtresi durur; terimi kesinlikle taşımayan kovalar hiç açılmaz. Terimle başlayan arama bu yüzden hızlıdır. Baştaki joker ise dizini işe yaramaz kılar.

*password gibi bir terimde Splunk dizindeki terimleri tek tek denemek zorunda kalır. tstats daha da ileri gider: ham veriye hiç dokunmaz, yalnız dizindeki sayıları toplar. Veri modeli hızlandırması aynı fikri arama anında çıkarılan alanlara taşır.

Arka planda zamanlanmış aramalar çalışır ve seçilen alanlar için ek tsidx özetleri üretir. Bu özetler disk ve işlemci harcar. Bu yüzden her veri modeli hızlandırılmaz, yalnız sık sorgulananlar seçilir.

Etkinlik 4 / 6

web indeksinde 500 hata koduna sahip en çok tekrar eden URI'yi bul.

ogrenci@lab

Kaba kuvveti tespit etmek ve önlemek

Kural yazmadan önce örnek veriyi kendin okumayı bilmelisin. Kaba kuvvet dalgası kayıtta üç izle görünür. Birincisi, aynı adres kısa sürede çok sayıda başarısız deneme üretir.

İkincisi, denenen hesap adları ya çok çeşitlidir ya da birkaç değerli hesapta yoğunlaşır. Üçüncüsü, dalganın sonunda aynı adresten başarılı bir giriş gelebilir.

Üçüncü iz en tehlikelisidir, çünkü artık bir deneme değil, açılmış bir oturum vardır. İyi bir tespit kuralı bu yüzden iki parçalıdır. Bir parça başarısız denemeleri sayar. Öbür parça aynı adresten sonradan gelen başarılı girişi arar.

Tespit sorgusu saldırıyı durdurmaz, yalnız görünür kılar. Önleme sunucu ve kimlik tarafında kurulur. SSH'ta parola girişini kapatıp yalnız anahtarla giriş açmak kaba kuvveti büyük ölçüde boşa çıkarır.

İnternete açık her hizmette çok faktörlü doğrulama ikinci duvardır. Hesap kilitleme parola tahminini yavaşlatır, ama püskürtmeye karşı zayıftır.

Püskürtmede her hesaba bir iki deneme düşer ve kilit eşiğine hiç ulaşılmaz. Bu yüzden kural yalnız hesap başına değil, kaynak adres başına da sayım yapmalıdır. Önceki sorgudaki dc(hesap) sütunu tam bu işe yarar. Bir adresin kısa sürede onlarca farklı hesabı denemesi, püskürtmenin en açık işaretidir.

Derinleş:Pratik için açık veri: BOTS v3

Splunk, Boss of the SOC adlı yarışmasının veri setlerini açık yayımlar. BOTS v3 yaklaşık 320 MB büyüklüğünde, önceden dizinlenmiş bir settir. Kurulumda dosyayı Splunk'ın uygulama dizinine açar ve Splunk'ı yeniden başlatırsın.

Veri index=botsv3 earliest=0 aramasıyla gelir. earliest=0 şarttır, çünkü olaylar geçmiş bir tarihe aittir ve varsayılan zaman penceresi onları göstermez. Sette linux_secure, bulut denetim kayıtları, ağ akışları ve uç nokta verisi gibi onlarca kaynak türü vardır.

Gerekli eklentilerin sürümünü depodaki listeyle eşlemek önemlidir; yanlış sürümde alanlar çıkarılmaz. Bu derste yazdığın her sorguyu bu veride deneyebilirsin. Önce | tstats count where index=botsv3 by sourcetype ile hangi kaynakların bulunduğunu gör. Sonra tek bir kaynak seç ve onda derinleş.

Şimdi ham satırlara dön. Aşağıdaki parçada aynı dış adres farklı hesap adlarıyla art arda başarısız giriş yapıyor ve sonunda bir hesabı açıyor. Aradaki satırlardan biri ise bir çalışanın kendi masasından yaptığı olağan giriştir.

Hangi satırların dalgaya ait olduğunu işaretlerken üç izi kullan: aynı kaynak, değişen hesap ve sondaki başarı. Bu ayrımı gözle yapabildiğinde sorguya dökmek de kolaylaşır. Önce kaynağa, sonra hesaba, en son sonuca bak.

Etkinlik 5 / 6

Kaba kuvvet denemesine ait satırları işaretle.

Şüpheli satırlara tıkla. Birden fazla olabilir.

Aynı soruyu Microsoft ürünlerinde başka bir dil yanıtlar: KQL (Kusto Query Language). Söz dizimi farklı görünür, ama mantık aynıdır. Veri soldan sağa akan bir borudan geçer; önce süzülür, sonra gruplanır, sonra sıralanır. SPL'de öğrendiğin her adımın KQL'de bir karşılığı vardır.

Sonraki derste SigninLogs tablosunda aynı kaba kuvvet sorusunu yeniden yazacaksın. İki dili yan yana gördüğünde komut adlarını değil, kalıbı öğrenirsin. Kalıp her SIEM'de aynıdır: zaman, kaynak, koşul, gruplama.

Etkinlik 6 / 6

SPL'de stats count by src_ip yazan bir analist aynı sonucu KQL'e taşımak istiyor. Hangi komut kavramsal olarak en yakın karşılıktır?

Bu derste bir hata mı gördün? Bildir