WMI ile Windows Güvenlik Olaylarını Sorgulama

Windows ortamlarında güvenlik olaylarını takip etmek, bir sistem yöneticisinin günlük rutininin en kritik parçalarından biridir. Event Viewer’ı açıp elle log taramak bazen işe yarasa da, özellikle birden fazla sunucuyu yönetiyorsanız bu yaklaşım hızla yetersiz kalır. İşte tam bu noktada WMI (Windows Management Instrumentation) devreye giriyor. WMI, Windows’un derinliklerine programatik olarak erişmenizi sağlayan güçlü bir altyapıdır ve güvenlik olaylarını sorgulamak için son derece esnek bir yol sunar. Bu yazıda WMI ile güvenlik olaylarını nasıl sorgulayacağınızı, pratik senaryolar üzerinden ele alacağız.

WMI Nedir ve Neden Güvenlik İçin Kullanılır?

WMI, Microsoft’un Windows işletim sistemi üzerine inşa ettiği bir yönetim altyapısıdır. Temelde WBEM (Web-Based Enterprise Management) standardının Microsoft implementasyonudur. Sistem bilgilerinden süreç yönetimine, ağ konfigürasyonundan olay günlüklerine kadar neredeyse her şeye WMI üzerinden erişebilirsiniz.

Güvenlik perspektifinden bakıldığında WMI’ın avantajları şunlardır:

  • Merkezi sorgulama: Tek bir noktadan uzak makinelerin güvenlik olaylarını sorgulayabilirsiniz
  • WQL desteği: SQL’e benzer bir sorgu diliyle esnek filtreleme yapabilirsiniz
  • Otomasyon dostu: PowerShell, Python veya VBScript ile kolayca entegre edilebilir
  • Real-time izleme: WMI event subscription ile anlık olay yakalama mümkündür

Ancak şunu da belirtmek gerekir: WMI güçlü bir araçtır ama kötüye kullanımı da yaygındır. Saldırganlar da WMI’ı persistence mekanizması olarak kullanır, dolayısıyla WMI aktivitelerini izlemek de başlı başına bir güvenlik gerekliliğidir.

Temel WMI Güvenlik Sorguları

Win32_NTLogEvent ile Başlamak

En temel yaklaşım Win32_NTLogEvent sınıfını kullanmaktır. Bu sınıf, Windows olay günlüklerindeki kayıtlara doğrudan erişim sağlar.

# PowerShell ile temel güvenlik log sorgulama
Get-WmiObject -Class Win32_NTLogEvent `
  -Filter "LogFile='Security' AND EventCode=4624" `
  -ComputerName "SERVER01" |
  Select-Object TimeGenerated, EventCode, Message, User |
  Format-List

Bu komut, EVENT ID 4624 yani başarılı oturum açma olaylarını listeler. ComputerName parametresini kendi sunucunuzun adıyla değiştirmeniz yeterli. Uzak makineye bağlanmak için WinRM veya DCOM’un açık olması gerektiğini unutmayın.

Sık Kullanılan Güvenlik Event ID’leri

Hangi event ID’lerine odaklanmanız gerektiğini bilmek, sorguları anlamlı kılar:

  • 4624: Başarılı oturum açma
  • 4625: Başarısız oturum açma girişimi
  • 4648: Açık kimlik bilgileriyle oturum açma (pass-the-hash için kritik)
  • 4672: Ayrıcalıklı oturum açma (admin hesapları)
  • 4688: Yeni süreç oluşturma
  • 4698: Zamanlanmış görev oluşturma
  • 4720: Yeni kullanıcı hesabı oluşturma
  • 4732: Güvenlik grubuna üye ekleme
  • 4771: Kerberos ön kimlik doğrulama başarısız
  • 7045: Yeni servis kurulumu

Başarısız Giriş Denemelerini Sorgulama

Bir sisteme brute force saldırısı yapılıp yapılmadığını anlamak için 4625 event ID’sini sorgulamak temel başlangıç noktasıdır:

# Son 24 saat içindeki başarısız giriş denemelerini listele
$zaman = (Get-Date).AddHours(-24)
$zamanWMI = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($zaman)

Get-WmiObject -Class Win32_NTLogEvent -Filter `
  "LogFile='Security' AND EventCode=4625 AND TimeGenerated >= '$zamanWMI'" |
  Select-Object @{N='Zaman';E={[System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated)}},
                User, ComputerName, Message |
  Sort-Object Zaman -Descending

Burada dikkat edilmesi gereken nokta, WMI’ın tarih formatının standart .NET datetime formatından farklı olmasıdır. ManagementDateTimeConverter sınıfı bu dönüşümü halleder.

Uzak Sistemleri Sorgulamak

Credential ile Uzak WMI Bağlantısı

Production ortamında genellikle birden fazla sunucuyu sorgulamanız gerekir. Bunu güvenli şekilde yapmak için:

# Kimlik bilgilerini güvenli şekilde al ve uzak sistemi sorgula
$credential = Get-Credential -Message "WMI bağlantısı için kimlik bilgisi girin"

$wmiParams = @{
    Class        = "Win32_NTLogEvent"
    Filter       = "LogFile='Security' AND EventCode=4720"
    ComputerName = "DC01", "DC02", "FILESERVER01"
    Credential   = $credential
}

Get-WmiObject @wmiParams |
  Select-Object ComputerName,
                @{N='Zaman';E={[System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated)}},
                Message |
  Where-Object { $_.Zaman -gt (Get-Date).AddDays(-7) } |
  Export-Csv -Path "C:Raporlaryeni_kullanicilar.csv" -NoTypeInformation -Encoding UTF8

Bu örnekte birden fazla sunucudan yeni kullanıcı oluşturma olaylarını tek seferde çekip CSV’ye kaydediyoruz. Domain ortamında haftalık rutin kontroller için harika bir başlangıç noktası.

CIM ile Daha Modern Yaklaşım

PowerShell 3.0 ile birlikte gelen Get-CimInstance komutu, WMI’ın modern versiyonu olan CIM (Common Information Model) üzerinden çalışır. WS-Man protokolünü kullandığı için daha güvenli ve firewall dostu kabul edilir:

# CIM Session ile çoklu sunucu sorgulama
$sunucular = @("DC01", "DC02", "APP01", "FILESERVER01")

$cimOptions = New-CimSessionOption -Protocol Wsman
$cimSession = New-CimSession -ComputerName $sunucular `
                              -SessionOption $cimOptions `
                              -Credential (Get-Credential)

# Ayrıcalıklı oturum açmaları sorgula
$olaylar = Get-CimInstance -ClassName Win32_NTLogEvent `
           -Filter "LogFile='Security' AND EventCode=4672" `
           -CimSession $cimSession

$olaylar | Group-Object PSComputerName | ForEach-Object {
    Write-Host "=== $($_.Name) ===" -ForegroundColor Yellow
    $_.Group | Select-Object -First 5 |
      Select-Object @{N='Zaman';E={$_.TimeGenerated}}, Message |
      Format-List
}

Remove-CimSession $cimSession

CIM session’ları işiniz bittikten sonra mutlaka kapatın. Açık bırakılan session’lar kaynak tüketimine yol açar.

Gerçek Dünya Senaryosu 1: Şüpheli Hesap Aktivitesi

Diyelim ki güvenlik ekibiniz bir uyarı gönderdi: “domain admin hesabı çalışma saatleri dışında aktif görünüyor.” Bu durumu WMI ile nasıl araştırırsınız?

# Belirli bir kullanıcının giriş saatlerini analiz et
$hedefKullanici = "domainadmin_ahmet"
$baslangic = (Get-Date).AddDays(-30)
$baslangicWMI = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($baslangic)

$girisler = Get-WmiObject -Class Win32_NTLogEvent `
  -Filter "LogFile='Security' AND EventCode=4624 AND TimeGenerated >= '$baslangicWMI'" `
  -ComputerName "DC01" |
  Where-Object { $_.InsertionStrings -contains $hedefKullanici.Split('')[1] } |
  ForEach-Object {
      $zaman = [System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated)
      [PSCustomObject]@{
          Tarih  = $zaman.ToString("yyyy-MM-dd")
          Saat   = $zaman.Hour
          DakLe  = $zaman.Minute
          GunTipi = if($zaman.DayOfWeek -in 'Saturday','Sunday') { "Hafta Sonu" } else { "Hafta Ici" }
          Kaynak = $_.ComputerName
      }
  }

# Mesai disi girisler (18:00 - 08:00 arasi)
$mesaiDisi = $girisler | Where-Object { $_.Saat -lt 8 -or $_.Saat -ge 18 -or $_.GunTipi -eq "Hafta Sonu" }

Write-Host "Toplam giris: $($girisler.Count)" -ForegroundColor Cyan
Write-Host "Mesai disi giris: $($mesaiDisi.Count)" -ForegroundColor Red

$mesaiDisi | Sort-Object Tarih, Saat | Format-Table -AutoSize

Bu script ile 30 günlük giriş geçmişini analiz edip mesai dışı aktiviteleri hızla tespit edebilirsiniz. Çıktı şüpheli görünüyorsa IR (Incident Response) sürecini başlatmanız gerekebilir.

Gerçek Dünya Senaryosu 2: Servis Kurulum Tespiti

Kötü amaçlı yazılımlar sıklıkla persistence için servis kurulumu (event 7045) kullanır. Bu olayı WMI ile izleyebilirsiniz:

# Yeni servis kurulumlarını tespit et ve analiz et
$sonBirHafta = (Get-Date).AddDays(-7)
$sonBirHaftaWMI = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($sonBirHafta)

$yeniServisler = Get-WmiObject -Class Win32_NTLogEvent `
  -Filter "LogFile='System' AND EventCode=7045 AND TimeGenerated >= '$sonBirHaftaWMI'" |
  ForEach-Object {
      $strings = $_.InsertionStrings
      [PSCustomObject]@{
          Zaman       = [System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated)
          ServisAdi   = $strings[0]
          DosyaYolu   = $strings[1]
          BaslatmaTipi = $strings[2]
          HesapAdi    = $strings[4]
      }
  }

# Supheli yollardan yuklenen servisleri filtrele
$supheliYollar = @("temp", "appdata", "public", "downloads", "tmp")
$supheliServisler = $yeniServisler | Where-Object {
    $yol = $_.DosyaYolu.ToLower()
    $supheliYollar | Where-Object { $yol -like "*$_*" }
}

if ($supheliServisler) {
    Write-Host "UYARI: Supheli konumlardan yuklenen servisler tespit edildi!" -ForegroundColor Red
    $supheliServisler | Format-List
} else {
    Write-Host "Supheli servis kurulumu bulunamadi." -ForegroundColor Green
}

Temp dizinleri veya kullanıcı profili altından kurulan servisler her zaman kırmızı bayraktır. Bu script’i haftalık otomatik çalışacak şekilde zamanlanmış görev olarak ayarlayabilirsiniz.

WMI Event Subscription ile Gerçek Zamanlı İzleme

WMI’ın en güçlü özelliklerinden biri, olay aboneliği (event subscription) ile gerçek zamanlı bildirim yapabilmesidir:

# WMI event subscription ile anlık yeni kullanici tespiti
# (Bu script calismaya devam eder, Ctrl+C ile durdurun)

$sorgu = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_NTLogEvent' AND TargetInstance.EventCode = 4720 AND TargetInstance.LogFile = 'Security'"

$watcher = New-Object System.Management.ManagementEventWatcher
$watcher.Query = New-Object System.Management.WqlEventQuery($sorgu)
$watcher.Scope = New-Object System.Management.ManagementScope("\.rootcimv2")

Write-Host "Yeni kullanici olusturma olaylari izleniyor..." -ForegroundColor Yellow
Write-Host "Durdurmak icin Ctrl+C'ye basin" -ForegroundColor Gray

try {
    while ($true) {
        $olay = $watcher.WaitForNextEvent()
        $hedef = $olay.TargetInstance
        $zaman = [System.Management.ManagementDateTimeConverter]::ToDateTime($hedef.TimeGenerated)

        Write-Host "`n[ALERT] $($zaman.ToString('HH:mm:ss')) - Yeni kullanici hesabi olusturuldu!" -ForegroundColor Red
        Write-Host "Makine: $($hedef.ComputerName)" -ForegroundColor Cyan
        Write-Host "Mesaj: $($hedef.Message.Substring(0, [Math]::Min(200, $hedef.Message.Length)))" -ForegroundColor White
    }
}
finally {
    $watcher.Dispose()
    Write-Host "WMI watcher kapatildi." -ForegroundColor Gray
}

Bu yaklaşımın production’da kullanımı için dikkat edilmesi gereken noktalar:

  • WITHIN 5: 5 saniyelik polling aralığını temsil eder, düşürmek CPU kullanımını artırır
  • Permanent subscription: Uzun vadeli izleme için __EventFilter, __EventConsumer ve __FilterToConsumerBinding nesneleri kullanılarak kalıcı subscription oluşturulabilir
  • Kalıcı WMI subscription’lar aynı zamanda bir saldırı vektörüdür, bu yüzden bunları da izlemeniz gerekir

WMI Güvenliği ve Audit İzleri

WMI’ın kendisi de bir saldırı yüzeyi oluşturduğundan, WMI aktivitelerini loglamak kritik önem taşır. Bunun için önce audit policy’nin doğru yapılandırıldığından emin olun:

# Mevcut audit policy ayarlarini kontrol et
auditpol /get /category:"Object Access" /r

# WMI aktivite loglamasini etkinlestir (admin yetkisi gerekir)
auditpol /set /subcategory:"Other Object Access Events" /success:enable /failure:enable

# WMI ile mevcut audit ayarlarini sorgula
Get-WmiObject -Namespace rootSecurityCenter2 -Class AntiVirusProduct |
  Select-Object displayName, productState, pathToSignedProductExe

WMI logları Microsoft-Windows-WMI-Activity/Operational kanalında tutulur. Bu kanalı da izleme kapsamınıza dahil etmelisiniz.

Toplu Analiz için Script Örneği

Birden fazla sunucudan güvenlik verisi toplayıp özet rapor oluşturan kapsamlı bir örnek:

# Cok sunuculu guvenlik olay raporu
param(
    [string[]]$Sunucular = @("DC01", "DC02", "APP01"),
    [int]$SonKacSaat = 24,
    [string]$RaporYolu = "C:Raporlarguvenlik_raporu_$(Get-Date -Format 'yyyyMMdd_HHmm').html"
)

$baslangic = (Get-Date).AddHours(-$SonKacSaat)
$baslangicWMI = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($baslangic)

$izlenecekOlaylar = @{
    4625 = "Basarisiz Giris"
    4720 = "Kullanici Olusturma"
    4732 = "Gruba Uye Ekleme"
    7045 = "Servis Kurulumu"
    4698 = "Zamanlanmis Gorev"
}

$tumOlaylar = @()

foreach ($sunucu in $Sunucular) {
    Write-Host "Sorgulanıyor: $sunucu" -ForegroundColor Cyan

    foreach ($eventKod in $izlenecekOlaylar.Keys) {
        $logDosyasi = if ($eventKod -eq 7045) { "System" } else { "Security" }

        try {
            $olaylar = Get-WmiObject -Class Win32_NTLogEvent `
              -Filter "LogFile='$logDosyasi' AND EventCode=$eventKod AND TimeGenerated >= '$baslangicWMI'" `
              -ComputerName $sunucu `
              -ErrorAction Stop

            foreach ($olay in $olaylar) {
                $tumOlaylar += [PSCustomObject]@{
                    Sunucu    = $sunucu
                    EventKod  = $eventKod
                    OlayTipi  = $izlenecekOlaylar[$eventKod]
                    Zaman     = [System.Management.ManagementDateTimeConverter]::ToDateTime($olay.TimeGenerated)
                    Kullanici = $olay.User
                }
            }
        }
        catch {
            Write-Warning "$sunucu - $eventKod sorgulanirken hata: $_"
        }
    }
}

# Ozet istatistikler
Write-Host "`n=== OZET RAPOR ===" -ForegroundColor Yellow
$tumOlaylar | Group-Object OlayTipi | ForEach-Object {
    Write-Host "$($_.Name): $($_.Count) olay" -ForegroundColor White
}

$tumOlaylar | Export-Csv -Path ($RaporYolu -replace '.html', '.csv') `
              -NoTypeInformation -Encoding UTF8

Write-Host "`nRapor kaydedildi: $RaporYolu" -ForegroundColor Green

Performans ve En İyi Uygulamalar

WMI sorguları yanlış kullanıldığında ciddi performans sorunlarına yol açabilir. Şu kurallara uymaya özen gösterin:

  • Filter’ı WMI tarafında kullanın: Get-WmiObject -Filter "..." yerine ardından Where-Object ile filtrelemek çok daha yavaştır. Filtreyi her zaman -Filter parametresinde belirtin
  • Zaman aralığını sınırlayın: Tarih filtresi olmadan büyük log dosyalarını sorgulamak hem yavaş hem de kaynak yoğundur
  • Sadece ihtiyaç duyduğunuz özellikleri çekin: Select-Object ile gereksiz alanları sorgu düzeyinde değil, aktarım sonrasında elden geçirin
  • Bağlantı havuzu kullanın: Çok sayıda sunucuya bağlanırken CimSession kullanmak bağlantı overhead’ini azaltır
  • Hata yönetimini ihmal etmeyin: Uzak bağlantılar her zaman başarıyla sonuçlanmaz, try-catch bloklarını kullanın
  • WMI namespace’lerini tanıyın: Güvenlik logları rootcimv2 altındadır ama bazı özel sorgular için rootSecurityCenter2 veya rootMicrosoftDNS gibi farklı namespace’ler gerekebilir

Sık Karşılaşılan Sorunlar

Sahada WMI ile güvenlik sorgularken en çok şu sorunlarla karşılaşırsınız:

  • “RPC server is unavailable” hatası: Hedef makinede Windows Firewall WMI trafiğini bloke ediyor olabilir. netsh advfirewall firewall set rule group="Windows Management Instrumentation (WMI)" new enable=yes komutu ile açabilirsiniz
  • “Access Denied” hatası: WMI namespace izinlerini veya DCOM izinlerini kontrol edin. wmimgmt.msc ile grafik arayüzden ayarlayabilirsiniz
  • Yavaş sorgular: Zaman filtresi olmadan büyük security loglarını sorgulamak dakikalar sürebilir. Her zaman tarih aralığı belirtin
  • Encoding sorunları: Message alanındaki özel karakterler bazen bozuk gelir. Çıktıyı CSV’ye kaydederken -Encoding UTF8 parametresini kullanın
  • Win32_NTLogEvent vs Get-WinEvent: Modern sistemlerde Get-WinEvent daha hızlı ve yeteneklidir. WMI tabanlı çözümler özellikle eski sistemlerle uyumluluk veya uzaktan programatik erişim gerektiğinde tercih edilmelidir

Sonuç

WMI, Windows güvenlik olaylarını sorgulamak için olgun ve güçlü bir araçtır. Özellikle heterojen ortamlarda, eski PowerShell sürümlerinin bulunduğu sistemlerde veya programatik entegrasyon gerektiren durumlarda değerini kanıtlar. Ancak modern Windows ortamlarında Get-WinEvent ve CIM cmdlet’lerini tercih etmek genellikle daha iyi performans ve daha az baş ağrısı anlamına gelir. WMI’ı iyi anlamak, hem savunma hem de tehdit avcılığı açısından sysadmin’lerin elinde bulundurması gereken bir beceridir. Bu yazıdaki örnekleri kendi ortamınıza uyarlayarak başlayın, zamanla bu sorguları otomatik raporlama sistemlerinize entegre edin. Güvenlik izleme reaktif değil proaktif bir aktivite olmalı ve WMI bu proaktif yaklaşımın önemli yapı taşlarından birini oluşturuyor.

Yorum yapın