Windows Sistemde Brute Force Saldırısı Tespiti

Bir sabah işe geldiğinde sunucunun erişim loglarında binlerce başarısız giriş denemesi görmen, her sysadmin’in korkulu rüyasıdır. Brute force saldırıları, saldırganların şifre tahmin etmeye çalıştığı en eski ve hâlâ en yaygın saldırı yöntemlerinden biridir. Windows ortamında bu saldırıları tespit etmek, doğru araçları ve log analizi bilgisini gerektiriyor. Bu yazıda, gerçek dünya senaryoları üzerinden Windows sistemlerde brute force tespitini adım adım inceleyeceğiz.

Windows Güvenlik Logları: Temeli Anlamak

Windows, güvenlik olaylarını Event Viewer üzerinden takip eder. Brute force tespitinin kalbi, Security Event Log‘larıdır. Buradaki en kritik Event ID’leri bilmek, saldırıyı erken fark etmenin anahtarıdır.

En sık kullandığım Event ID’ler şunlar:

  • 4625: Başarısız oturum açma girişimi (brute force’un ana göstergesi)
  • 4624: Başarılı oturum açma (saldırı sonrası erişim var mı diye kontrol edersin)
  • 4648: Açık kimlik bilgileriyle oturum açma girişimi
  • 4771: Kerberos ön kimlik doğrulama başarısız (domain ortamında)
  • 4776: NTLM kimlik doğrulama başarısız
  • 4740: Kullanıcı hesabı kilitlendi (brute force’un sonucu)
  • 4778: Oturum yeniden bağlandı (RDP brute force sonrası)

Logların anlamlı olması için önce Audit Policy ayarlarının doğru yapılandırılmış olması gerekiyor. Şunu çalıştırarak mevcut durumu görebilirsin:

auditpol /get /category:"Logon/Logoff"
auditpol /get /category:"Account Logon"

Eğer “No Auditing” görüyorsan, bu ayarları aktif etmen şart:

auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Account Lockout" /success:enable /failure:enable
auditpol /set /subcategory:"Credential Validation" /success:enable /failure:enable
auditpol /set /subcategory:"Kerberos Authentication Service" /success:enable /failure:enable

Bu ayarlar olmadan loglar kayıt altına alınmaz ve saldırıyı göremezsin. Bir müşterimde bu ayarların devre dışı olduğunu keşfettiğimde, aylar önce yaşanmış olası saldırıların hiçbir izinin kalmadığını gördüm. O gün bu ayarları her sunucuda kontrol etmeyi alışkanlık hâline getirdim.

PowerShell ile Hızlı Brute Force Analizi

Event Viewer GUI’si güzel ama yüzlerce sunucu varken işe yaramaz. PowerShell, büyük log kümelerini hızlıca analiz etmek için en güçlü silahın. Aşağıdaki betik, son 24 saat içindeki başarısız giriş denemelerini IP adresine göre grupluyor:

$startTime = (Get-Date).AddHours(-24)

Get-WinEvent -FilterHashtable @{
    LogName = 'Security'
    Id = 4625
    StartTime = $startTime
} | ForEach-Object {
    $xml = [xml]$_.ToXml()
    [PSCustomObject]@{
        TimeCreated = $_.TimeCreated
        IpAddress   = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'IpAddress'} | Select-Object -ExpandProperty '#text'
        Username    = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'TargetUserName'} | Select-Object -ExpandProperty '#text'
        WorkStation = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'WorkstationName'} | Select-Object -ExpandProperty '#text'
        LogonType   = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'LogonType'} | Select-Object -ExpandProperty '#text'
    }
} | Group-Object IpAddress | Sort-Object Count -Descending | Select-Object -First 20 | Format-Table Name, Count -AutoSize

Bu betiği çalıştırdığında, hangi IP adresinin kaç başarısız giriş yaptığını saniyeler içinde görürsün. Eğer tek bir IP’den 500’den fazla deneme geliyorsa, bu kesinlikle brute force’tur.

Logon Type değerleri de çok önemli:

  • 2: Interactive (fiziksel konsol)
  • 3: Network (dosya paylaşımı, SMB)
  • 10: RemoteInteractive (RDP)
  • 8: NetworkCleartext (genellikle IIS veya FTP)

RDP Brute Force Tespiti: En Yaygın Senaryo

Gerçek hayatta en sık karşılaştığım senaryo RDP brute force’udur. Özellikle 3389 portunu internete açık bırakan sistemler, botu saniyeler içinde kendine çekiyor. Bir prodüksiyon sunucusunda şunu yaşadım: Gece boyunca Rusya kökenli IP’lerden 47.000 başarısız RDP denemesi gelmiş, sabah iş yerinde sistemin yavaşladığını fark ettik.

RDP başarısız girişlerini özellikle filtrelemek için:

$rdpFailures = Get-WinEvent -FilterHashtable @{
    LogName = 'Security'
    Id = 4625
} | Where-Object {
    $xml = [xml]$_.ToXml()
    $logonType = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'LogonType'} | Select-Object -ExpandProperty '#text'
    $logonType -eq '10'
} | ForEach-Object {
    $xml = [xml]$_.ToXml()
    [PSCustomObject]@{
        Zaman    = $_.TimeCreated
        IP       = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'IpAddress'} | Select-Object -ExpandProperty '#text'
        Kullanici = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'TargetUserName'} | Select-Object -ExpandProperty '#text'
    }
}

$rdpFailures | Group-Object IP | Sort-Object Count -Descending | Select-Object -First 15

Brute force sonrası başarılı giriş olup olmadığını kontrol etmek kritik. Şüpheli IP’den başarılı giriş var mı diye bak:

$suspiciousIP = "185.234.xx.xx"  # Şüpheli IP adresini buraya yaz

Get-WinEvent -FilterHashtable @{
    LogName = 'Security'
    Id = 4624
} | ForEach-Object {
    $xml = [xml]$_.ToXml()
    $ip = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'IpAddress'} | Select-Object -ExpandProperty '#text'
    if ($ip -eq $suspiciousIP) {
        Write-Host "UYARI: Şüpheli IP'den başarılı giriş!" -ForegroundColor Red
        Write-Host "Zaman: $($_.TimeCreated)"
        $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'TargetUserName'} | Select-Object -ExpandProperty '#text'
    }
}

Domain Controller Üzerinde Brute Force Tespiti

Active Directory ortamında işler biraz daha karmaşık. Kerberos ve NTLM protokolleri devreye giriyor. Domain Controller loglarında 4771 (Kerberos başarısız) ve 4776 (NTLM başarısız) olaylarını takip etmen gerekiyor.

# Son 1 saatte kilitlenmiş hesapları bul
Import-Module ActiveDirectory

Search-ADAccount -LockedOut | Select-Object Name, SamAccountName, LockedOut, LastLogonDate, DistinguishedName | Format-List

# Belirli bir kullanıcının kilit kaynağını bul
$lockedUser = "testkullanici"
Get-ADUser $lockedUser -Properties LockedOut, BadLogonCount, BadPasswordTime, LastBadPasswordAttempt | 
    Select-Object Name, LockedOut, BadLogonCount, LastBadPasswordAttempt

Hesap kilitleme kaynağını bulmak için Microsoft’un LockoutStatus aracını kullanabilirsin ama PowerShell ile de yapılabilir:

# Tüm DC'lerde kilitleme kaynağını ara
$username = "hedef_kullanici"
$DCs = Get-ADDomainController -Filter *

foreach ($DC in $DCs) {
    $events = Get-WinEvent -ComputerName $DC.Name -FilterHashtable @{
        LogName = 'Security'
        Id = 4740
    } -ErrorAction SilentlyContinue

    foreach ($event in $events) {
        $xml = [xml]$event.ToXml()
        $lockedUser = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'TargetUserName'} | Select-Object -ExpandProperty '#text'
        if ($lockedUser -eq $username) {
            $caller = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'SubjectUserName'} | Select-Object -ExpandProperty '#text'
            $callerComp = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'SubjectDomainName'} | Select-Object -ExpandProperty '#text'
            Write-Host "DC: $($DC.Name) | Kullanici: $lockedUser | Kaynak: $caller@$callerComp | Zaman: $($event.TimeCreated)"
        }
    }
}

Windows Firewall ile Anlık Engelleme

Saldırıyı tespit ettin, peki ne yapacaksın? İlk adım, saldırgan IP’yi engellemek. Windows Firewall üzerinden bunu otomatikleştirebilirsin:

# Tek IP engelleme
$saldirganIP = "185.234.xx.xx"
New-NetFirewallRule -DisplayName "Brute Force Block - $saldirganIP" `
    -Direction Inbound `
    -Action Block `
    -RemoteAddress $saldirganIP `
    -Protocol TCP `
    -LocalPort 3389,445,443,80 `
    -Description "Brute force tespiti nedeniyle otomatik engelleme"

# Birden fazla IP'yi toplu engelleme
$IPListesi = @("185.234.xx.xx", "91.108.xx.xx", "194.165.xx.xx")
foreach ($ip in $IPListesi) {
    New-NetFirewallRule -DisplayName "BF_Block_$ip" `
        -Direction Inbound `
        -Action Block `
        -RemoteAddress $ip `
        -Enabled True
    Write-Host "$ip engellendi." -ForegroundColor Green
}

Otomatik Tespit ve Yanıt Betiği

Gerçek dünyada manuel analiz yapmak yerine, periyodik çalışan bir betikle otomatik tespit sistemi kurabilirsin. Şu betik, her 15 dakikada Task Scheduler ile çalışacak şekilde ayarlanabilir:

# BruteForceDetect.ps1
param(
    [int]$EsikDeger = 50,        # Kaç başarısız giriş brute force sayılır
    [int]$DakikaAraligi = 15,    # Kaç dakika geriye bak
    [string]$LogDosyasi = "C:LogsBruteForceAlerts.log",
    [string]$EmailAlici = "[email protected]"
)

$baslangic = (Get-Date).AddMinutes(-$DakikaAraligi)

$basarisizGirisler = Get-WinEvent -FilterHashtable @{
    LogName = 'Security'
    Id = 4625
    StartTime = $baslangic
} -ErrorAction SilentlyContinue | ForEach-Object {
    $xml = [xml]$_.ToXml()
    [PSCustomObject]@{
        IP = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'IpAddress'} | Select-Object -ExpandProperty '#text'
        Kullanici = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'TargetUserName'} | Select-Object -ExpandProperty '#text'
        Zaman = $_.TimeCreated
    }
}

$grupluIP = $basarisizGirisler | Group-Object IP | Where-Object {$_.Count -ge $EsikDeger} | Sort-Object Count -Descending

foreach ($grup in $grupluIP) {
    $mesaj = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | BRUTE FORCE TESPIT | IP: $($grup.Name) | Deneme: $($grup.Count) | Sure: Son $DakikaAraligi dk"
    Add-Content -Path $LogDosyasi -Value $mesaj
    Write-Host $mesaj -ForegroundColor Red

    # Otomatik engelleme
    $mevcutKural = Get-NetFirewallRule -DisplayName "BF_Auto_$($grup.Name)" -ErrorAction SilentlyContinue
    if (-not $mevcutKural) {
        New-NetFirewallRule -DisplayName "BF_Auto_$($grup.Name)" `
            -Direction Inbound -Action Block `
            -RemoteAddress $grup.Name -Enabled True | Out-Null
        Add-Content -Path $LogDosyasi -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | OTOMATiK ENGELLEME | IP: $($grup.Name)"
    }
}

Bu betiği Task Scheduler’a eklemek için:

$action = New-ScheduledTaskAction -Execute "PowerShell.exe" `
    -Argument "-NonInteractive -ExecutionPolicy Bypass -File C:ScriptsBruteForceDetect.ps1"

$trigger = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Minutes 15) -Once -At (Get-Date)

$settings = New-ScheduledTaskSettingsSet -RunOnlyIfNetworkAvailable -StartWhenAvailable

Register-ScheduledTask -TaskName "BruteForceDetection" `
    -Action $action `
    -Trigger $trigger `
    -Settings $settings `
    -RunLevel Highest `
    -Description "Her 15 dakikada brute force tespiti yapar"

Gerçek Dünya Senaryosu: Kurumsal Ağda Saldırı Soruşturması

Bir finans şirketinde yaşanan olayı örnek verebilirim. Saat 03:47’de monitoring sistemi alarm verdi. Sabah 08:00’da ofise geldiğimde şunları yaptım:

İlk adım, son 6 saatin genel durumuna bakmak:

# Hızlı durum değerlendirmesi
$son6Saat = (Get-Date).AddHours(-6)

$ozet = Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=$son6Saat} |
    ForEach-Object {
        $xml = [xml]$_.ToXml()
        [PSCustomObject]@{
            IP = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'IpAddress'} | Select-Object -ExpandProperty '#text'
            Kullanici = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'TargetUserName'} | Select-Object -ExpandProperty '#text'
            Saat = $_.TimeCreated.Hour
        }
    }

Write-Host "Toplam basarisiz giris: $($ozet.Count)"
Write-Host "Etkilen kullanici sayisi: $(($ozet | Select-Object -Unique Kullanici).Count)"
Write-Host "Kokenli IP sayisi: $(($ozet | Select-Object -Unique IP).Count)"
Write-Host "En cok deneme yapan IP:"
$ozet | Group-Object IP | Sort-Object Count -Descending | Select-Object -First 5 | Format-Table Name, Count

Analiz sonuçta ortaya çıktı: Tek bir Ukrayna IP’sinden gece boyunca 23.000 RDP denemesi yapılmış. Hedef kullanıcı adları arasında “administrator”, “admin”, “backup”, “sa” vardı. Klasik dictionary attack. Neyse ki Account Lockout Policy devredeydi ve hiçbir hesap ele geçirilememişti.

Hesap Kilitleme Politikası ve Ek Önlemler

Brute force’a karşı en etkili teknik kontrol, Account Lockout Policy‘dir. Group Policy üzerinden şu değerleri öneriyorum:

  • Account lockout threshold: 5 başarısız denemede kilitle
  • Account lockout duration: 30 dakika (0 koyarsan admin manuel açması gerekir)
  • Reset account lockout counter after: 15 dakika

Bu ayarları PowerShell ile kontrol edebilirsin:

# Mevcut hesap kilitleme politikasını görüntüle
net accounts

# Fine-grained password policy varsa AD'den çek
Get-ADDefaultDomainPasswordPolicy | Select-Object LockoutDuration, LockoutObservationWindow, LockoutThreshold

# Belirli bir OU için PSO (Password Settings Object) kontrol et
Get-ADFineGrainedPasswordPolicy -Filter * | Select-Object Name, LockoutThreshold, LockoutDuration, Precedence

RDP güvenliği için ek olarak şunları kesinlikle yapmalısın:

  • Network Level Authentication (NLA) aktif et, bu brute force’u önemli ölçüde yavaşlatır
  • RDP portunu 3389’dan farklı bir porta taşı (güçlü bir önlem değil ama bot trafiğini azaltır)
  • Windows Firewall ile sadece belirli IP aralıklarından RDP erişimine izin ver
  • MFA zorunlu kıl; RADIUS tabanlı çözümler veya Azure MFA bu iş için idealdir

Windows Event Forwarding ile Merkezi İzleme

Birden fazla sunucu varsa, logları merkezi bir noktada toplamak şart. Windows Event Forwarding (WEF) ile bu ücretsiz yapılabilir:

# Collector sunucuda WinRM servisini yapılandır
winrm quickconfig
wecutil qc /quiet

# Subscription oluştur (Collector sunucuda çalıştır)
wecutil cs BruteForceSubscription.xml

# Source sunucuların Collector'a log göndermesini GPO ile zorla
# Computer Configuration > Windows Settings > Security Settings > Event Log
# veya direkt registry:
reg add "HKLMSOFTWAREPoliciesMicrosoftWindowsEventLogEventForwardingSubscriptionManager" `
    /v 1 /t REG_SZ /d "Server=http://logserver.sirket.local:5985/wsman/SubscriptionManager/WEC,Refresh=60"

Sonuç

Windows sistemlerde brute force tespiti, tek bir araç veya tek bir ayarla çözülecek bir mesele değil. Doğru audit policy ayarları, düzenli log analizi, otomatik tespit betikleri ve uygun engelleme mekanizmalarının bir arada çalışması gerekiyor.

Özetlemek gerekirse, hemen bugün yapman gereken şeyler şunlar: Audit Policy ayarlarını kontrol et ve eksikse aktif et, kritik sunucularda Account Lockout Policy’nin devrede olduğunu doğrula, RDP portunu internete açık bırakmıyorsan güzel ama bırakmak zorundaysan NLA’yı mutlaka etkinleştir ve periyodik çalışan bir tespit betiği kur.

Brute force saldırıları durmuyor, durdurmayacak da. Saldırganların maliyeti neredeyse sıfır ama senin loglarını doğru okuma becerin onların önündeki en büyük engel. Event ID’leri ezberlemek zorunda değilsin ama bu yazıdaki betikleri adapteyip ortamına entegre edersen, bir sonraki sabah işe geldiğinde senin sistemin saldırıyı çoktan tespit etmiş ve gerekli aksiyonu almış olacak.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir