İçeriğe atla
Yazılar

4624'ten DCSync’e: bir lateral movement avcısı inşa etmek

crabwalk: MITRE ATT&CK’e maplenen, ground-truth corpus’a karşı doğrulanmış açık kaynak bir DFIR aracı

7 dk okuma
İçindekiler
  1. Problem: lateral movement triyajı neden zor?
  2. Mevcut araçlardan farkı
  3. Nasıl çalışıyor: dört aşamalı bir hat
  4. 1) parse — gürültüyü at, normalize et
  5. 2) sessions — asıl zekâ burada
  6. 3) hunt — kural motoru
  7. 4) report + layer — çıktıyı insana sun
  8. Rigor: doğrulama olmadan bu bir oyuncak olurdu
  9. Tasarım kararları ve öğrendiklerim
  10. Denemek isterseniz
  11. Kapanış

Bir kuruma sızıldıktan sonra her SOC ve DFIR ekibi aynı soruyu sorar: Saldırgan ilk nereye düştü, oradan nereye gitti?

Bu sorunun cevabı tek bir logda yatmaz. 4624/4672 logon desenlerini, RDP oturum zincirlerini, uzaktan kurulan servisleri, zamanlanmış görevleri ve host’lar arası WinRM/WMI çalıştırmalarını üst üste koyup birleştirmeniz gerekir. Onlarca makinenin Windows Event Log’unu elle tarayıp bu ipuçlarını zihninizde bir zaman çizelgesine dizmek, olay müdahalesinin en yavaş ve en hataya açık kısmıdır.

crabwalk tam bu triyaj adımını otomatikleştirmek için yazdığım bir araç. Windows EVTX loglarını parse ediyor; logon, servis, zamanlanmış görev ve PowerShell aktivitesini tek bir saldırı zaman çizelgesinde korele ediyor; ve bulduğu her şeyi MITRE ATT&CK tekniklerine haritalıyor. Adı da buradan geliyor: yengeçler yana yürür — saldırganlar da lateral (yanal) hareket eder.

Bu yazıda aracı neden bu şekilde tasarladığımı, mevcut araçlardan nerede ayrıldığını ve iç mimarisini adım adım anlatacağım.

(Repo: https://github.com/IlkerUnver00/crabwalk — MIT lisanslı, Python.)


Problem: lateral movement triyajı neden zor?

Modern bir saldırıda ilk erişim çoğu zaman sadece başlangıçtır. Asıl hasar, saldırganın ağ içinde yatay olarak ilerleyip ayrıcalık yükseltmesiyle oluşur. Bu hareketin izi Windows olay loglarına dağınık halde düşer:

  • Logon desenleri — 4624 (başarılı logon), tipi (network, RDP, batch), 4672 (ayrıcalıklı logon), 4648 (açık kimlik bilgisiyle logon).
  • Uzaktan çalıştırma — 7045/4697 (servis kurulumu, PsExec deseni), 4698/4702 (zamanlanmış görev), WMI ve WinRM aktivitesi.
  • Kimlik bilgisi kötüye kullanımı — pass-the-hash, Kerberoasting, DCSync.

Sorun şu ki bu olayların hiçbiri tek başına anlam ifade etmez. “Bir servis kuruldu” tek başına gürültüdür; ama uzak bir oturumdan hemen sonra kurulan bir servis PsExec ile lateral movement demektir. Anlam, olayların aralarındaki ilişkide ve sıralamasında gizlidir. İşte bu yüzden per-event (olay bazlı) bakış bu problemi tam çözmez.


Mevcut araçlardan farkı

Bu alanda güçlü araçlar zaten var — Chainsaw ve Hayabusa gibi. Bunlar EVTX üzerinde genel Sigma kurallarını olay bazında çalıştırır: her olayı ayrı ayrı bir imzayla eşleştirirler. Son derece işe yarar, ama tek bir olaya bakarlar.

crabwalk daha dar ama daha derin bir şey yapıyor: imza eşleştirmesi değil, durum bilgili (stateful), host’lar arası korelasyon. Yani tek tek olayları değil, olayların oluşturduğu oturum zincirlerini takip ediyor. “A host’undan B’ye geçildi, B’de ayrıcalık yükseltildi, oradan C’ye bir servis kuruldu” gibi bir hikâyeyi, olayları birbirine bağlayarak kuruyor.

Bu ayrımı aklımda hep şöyle tuttum: Chainsaw “bu olay şüpheli mi?” sorusunu sorar; crabwalk “bu olaylar birlikte bir lateral movement anlatıyor mu?” sorusunu sorar.


Nasıl çalışıyor: dört aşamalı bir hat

crabwalk bir boru hattı (pipeline) olarak tasarlandı. Dört CLI komutu, ham logdan okunabilir bir rapora kadar akışı taşıyor:

crabwalk parse    C:\evidence\logs --out timeline.jsonl
crabwalk sessions C:\evidence\logs --out sessions.json
crabwalk hunt     C:\evidence\logs --out findings.json
crabwalk hunt     C:\evidence\logs --report report.html --layer navigator.json

1) parse — gürültüyü at, normalize et

İlk adım EVTX dosyalarını (tek dosya ya da tüm klasör) parse edip zamana göre sıralı, normalize bir olay akışına dönüştürmek. Burada bilinçli bir tercih yaptım: varsayılan olarak her şeyi değil, sadece lateral movement için anlamlı olayları tutuyorum — 10 farklı log kanalında ~45 olay ID’lik özenle seçilmiş bir katalog. (--all, --event-id, --channel ile bu davranışı ezebilirsiniz.) Böylece 37 bin kayıtlık bir corpus, önemli olan birkaç yüz olaya iniyor.

2) sessions — asıl zekâ burada

crabwalk’un kalbi oturum takip modeli. Her host için LogonId yaşam döngülerini yeniden kuruyorum: bir oturum ne zaman açıldı, hangi tip logon’du, ne zaman kapandı. Ardından bu oturumların üzerine kenarları (edge) çiziyorum:

  • Inbound uzak logon kenarları — 4624/RDP ile “dışarıdan bu host’a girildi”.
  • Outbound açık-kimlik kenarları — 4648 ile “bu host’tan başka bir host’a kimlik bilgisiyle gidildi”.
  • Ayrıcalık backfill — 4672’den gelen ayrıcalık bilgisini ilgili oturuma geri işliyorum.

Sonuç, host’tan host’a hareket haritası:

sessions   : 20 total | 12 remote | 3 privileged+remote
edges      : 13 shown (2 machine-account edges hidden, --include-machine)
HOST-TO-HOST MOVEMENT
2019-03-18 11:27:23Z  EXAMPLE.CORP\administrator  PC01 -> WIN-77LTAPHIQ1R  explicit-credentials
2019-03-19 00:02:04Z  EXAMPLE\Administrator       10.0.2.17 -> WIN-77LTAPHIQ1R  network priv

Bu tablo tek başına bile bir analistin dakikalarını saniyeye indiriyor: kim, ne zaman, nereden nereye gitti — hepsi tek bakışta.

3) hunt — kural motoru

Oturum ve kenar durumunun üzerine 11 tespit kuralı çalıştırıyorum. Her bulgu tekilleştiriliyor (dedup), önem sırasına göre sıralanıyor ve ATT&CK teknik ID’leriyle etiketleniyor:

Kural Başlık ATT&CK
CW-001 Uzak logon sonrası servis kurulumu T1021.002, T1543.003
CW-002 Host’lar arası RDP zinciri T1021.001
CW-003 Pass-the-hash göstergeleri T1550.002
CW-004 Uzak oturumdan zamanlanmış görev T1053.005
CW-005 Yönetimsel paylaşımda çalıştırılabilir T1021.002, T1570
CW-006 WMI üzerinden process başlatma T1047
CW-007 WinRM üzerinden uzaktan çalıştırma T1021.006
CW-008 Şüpheli PowerShell script block T1059.001
CW-009 Olay logu temizlenmesi T1070.001
CW-010 Kerberoasting (RC4 servis bileti) T1558.003
CW-011 DCSync (dizin replikasyonu) T1003.006

Kuralların çoğu tek bir olaya değil, bir olay + bir duruma bakıyor. Örneğin CW-001, bir servis kurulumunu ancak uzak bir oturumla ilişkilendirebiliyorsa PsExec deseni olarak işaretliyor; bilinen araç servis adlarını gördüğünde önemi “critical”a çekiyor. CW-006 ise WmiPrvSE’nin çocuğu olan process’leri takip ediyor — bir shell doğduğunda alarm veriyor:

[HIGH] 2019-08-30 12:54:08Z  CW-006  Process spawned via WMI
    host: MSEDGEWIN10   user: MSEDGEWIN10\IEUser   ATT&CK: T1047
    WmiPrvSE.exe (WMI) spawned 'rundll32 ...comsvcs.dll, MiniDump 4868 ...'

Bu tek bulguda hem WMI ile uzaktan çalıştırma (T1047) hem de comsvcs.dll MiniDump ile LSASS dump girişimi yakalanıyor — klasik bir credential access hamlesi.

4) report + layer — çıktıyı insana sun

Son aşama iki çıktı üretiyor. --layer ile bulguları tekniğe göre skorlayan bir ATT&CK Navigator layer dosyası çıkıyor; bunu Navigator’da açtığınızda saldırının ATT&CK üzerindeki ısı haritasını görüyorsunuz.

--report ile de tek dosyalık, kendi kendine yeten bir HTML raporu üretiliyor: istatistik kutuları, önem (severity) çubuğu, ATT&CK tablosu, host başına swimlane zaman çizelgesi (satır içi SVG), hareket tablosu ve sıralı bulgu kartları. Dış bağımlılık yok, tek dosya, açık/koyu temaya duyarlı.

crabwalk HTML raporu: dosya, oturum ve bulgu sayılarını gösteren istatistik kutuları, önem çubuğu, ATT&CK kapsam tablosu ve host başına zaman çizelgesi.

Bu “tek dosya, dış asset yok” kararı estetik değil, pratik: DFIR iş istasyonları çoğu zaman izole ve internetsizdir. Raporu bir USB’ye atıp başka bir makinede açabilmelisiniz.


Rigor: doğrulama olmadan bu bir oyuncak olurdu

Bir tespit aracının en tehlikeli hali, ne kaçırdığını bilmeden “çalışıyor gibi görünmesidir”. Bu yüzden crabwalk’u bir ground-truth corpus’a karşı regresyon testine bağladım: EVTX-ATTACK-SAMPLES.

Bu corpus’un güzelliği şu: her örnek dosyanın adı, gösterdiği tekniği söylüyor — LM_renamed_psexecsvc_5145.evtx (T1021.002), sysmon_10_1_memdump_comsvcs_minidump.evtx (T1047), DE_1102_security_log_cleared.evtx (T1070.001) gibi. Test de basitçe şunu doğruluyor: crabwalk bu dosyayı doğru tekniğe maplemek zorunda. Ayrı bir smoke test ise tüm corpus’u (156 dosya, 37 binden fazla kayıt) parse ediyor ve tek bir parse edilemeyen kayıtta bile başarısız oluyor.

Tüm corpus üzerinde crabwalk 9 teknikte 47 bulgu üretiyor — wmiexec’in cmd.exe /Q /c ... 1> \\127.0.0.1\ADMIN$\... imzası, sekurlsa::pth logon’ları ve WMI üzerinden başlatılan bir LSASS dump’ı dahil.

Bu doğrulama süreci bana bedava iki bug da hediye etti: null kayıt zaman damgaları ve #attributes iç içe geçme problemi. İkisini de düzelttim ve olay seviyesinde dedup ekledim. Testler olmasa bu hataları hiç fark etmeyecektim — projenin bana öğrettiği en net ders bu oldu.


Tasarım kararları ve öğrendiklerim

Kod satırlarından çok, birkaç prensip bu aracın karakterini belirledi:

Minimum bağımlılık. DFIR iş istasyonları sıklıkla çevrimdışıdır; pip install’ın internete gitmesini bekleyemezsiniz. Bu yüzden tek çalışma-zamanı bağımlılığı Rust tabanlı evtx parser’ı. Sadelik, burada bir özellik.

Kirli girdi normaldir. Gerçek dünya logları bozuktur. Parse edilemeyen kayıtlar sayılıyor ve raporlanıyor ama asla programı öldürmüyor. Bir olay kanıtını tek bozuk kayıt yüzünden komple kaybetmek kabul edilemez.

Her yerde UTC. Zaman damgaları parse anında UTC’ye normalize ediliyor. Host’lar arası korelasyon yapan bir araçta saat dilimi karmaşası, sessizce yanlış zaman çizelgeleri üretir — bu da en kötü hata türüdür, çünkü doğru görünür.


Denemek isterseniz

pip install -e .
crabwalk hunt C:\evidence\logs --report report.html --layer navigator.json

Corpus’a karşı çalıştırmak için:

git clone --depth 1 https://github.com/sbousseaden/EVTX-ATTACK-SAMPLES.git samples/EVTX-ATTACK-SAMPLES
pytest tests/test_corpus.py -v

Proje MIT lisanslı ve GitHub Actions CI ile Python 3.10–3.12 üzerinde test ediliyor. Kod, açık uçlar ve geri bildirime açık:

👉 https://github.com/IlkerUnver00/crabwalk


Kapanış

crabwalk’u yazma amacım sadece bir araç üretmek değildi; lateral movement’ın Windows loglarına nasıl yansıdığını elimle öğrenmekti. Bir saldırının izini olay olay değil, oturum oturum takip etmek, DFIR’a bambaşka bir açıdan bakmamı sağladı.

Eğer siz de blue team / threat hunting tarafında çalışıyorsanız, bir tespit fikrini alıp ground-truth veriye karşı doğrulayana kadar götürmenin ne kadar öğretici olduğunu tavsiye ederim. Geri bildirimlerinizi, yeni kural fikirlerinizi ve kaçırdığım desenleri duymak isterim — repo’da issue açmaktan çekinmeyin.

Yengeçler yana yürür. Saldırganlar da. Umarım crabwalk onları bir adım önce yakalamanıza yardımcı olur.