Active Directory Sağlık Kontrolü: krbtgt Rotasyonu ve Hesap Yaşam Döngüsü
- Murat Akpınar
- Windows , Sistem yönetimi
- 11 Eylül 2026
İçindekiler
Bu seride hogwarts.local ormanını önce sıfırdan kurduk, sonra OU, kullanıcı ve gruplarla içini doldurduk, ardından sertleştirdik ve son olarak denetim araçlarıyla sertleştirmenin gerçekten işe yaradığını ölçtük. Dört yazının sonunda ortada çalışan, sertleştirilmiş ve denetlenmiş bir Active Directory var.
Bir Active Directory çökerek değil, yaşlanarak bozulur. Kurulum günü doğru olan her şey — replikasyon, saat, yedek, ayrıcalıklı grup üyelikleri, atıl hesaplar, Kerberos anahtarları — kendi başına bozulmaz; kimse bakmadığı için bozulur. Bir DC üç hafta önce replikasyonu kesmiştir ve kimse fark etmemiştir. İşten ayrılan bir öğretmenin hesabı iki yıldır açıktır. Domain’in Kerberos ana anahtarı 2011’den beri hiç değişmemiştir. Bunların hiçbiri alarm üretmez; hepsi bir gün birden fatura keser.
Bu yazıda o faturayı kesmeden yakalamanın üç aracını kuracağız: krbtgt hesabının doğru döndürülmesi (ve neden bir kez sıfırlamanın yarım iş olduğu), günlük/haftalık/aylık bir sağlık kontrolü takvimi (çalıştırılabilir tek bir rapor script’iyle), ve hesap yaşam döngüsü — ayrılan çalışanın hesabının hangi gün devre dışı bırakılacağı, hangi gün silineceği ve silmenin neden geri alınamayan tek adım olduğu.
⚠️ Kurgusal lab uyarısı: Aşağıdaki tüm sunucu adları, IP’ler, SID’ler, GUID’ler ve komut çıktıları örnektir — serinin
hogwarts.locallaboratuvarına aittir, gerçek bir ortamdan alınmamıştır. Komutlar ise gerçektir; kendi ortamınızda çalıştırmadan önce etkilerini okuyun. Özelliklekrbtgtrotasyonu ve hesap silme bölümlerindeki komutlar tüm domain’i etkiler.Tanımadığınız kısaltmalar için yazının sonundaki terimler sözlüğüne bakabilirsiniz.
krbtgt: Domain’in Kerberos Ana Anahtarı
Her Active Directory domain’inde CN=Users altında, devre dışı, kimsenin dokunmadığı bir hesap durur: krbtgt. Bu hesabın RID’i her domain’de sabittir (502) ve domain’deki en kritik parola onun parolasıdır — çünkü o parolanın hash’i, KDC’nin dağıttığı biletleri şifrelediği ve imzaladığı anahtardır.
krbtgt Neyi İmzalar: TGT’nin Kaynağı
Bir kullanıcı hogwarts.local‘e giriş yaptığında KDC ona bir TGT (Ticket Granting Ticket) verir. Bu bilet, kullanıcının kim olduğunu ve hangi gruplara üye olduğunu taşır; kullanıcı bir dosya sunucusuna erişmek istediğinde bu TGT’yi KDC’ye gösterip o sunucu için bir servis bileti ister.
Kritik nokta şu: TGT, krbtgt hesabının anahtarıyla şifrelendiği için yalnızca KDC tarafından okunabilir — istemci kendi biletinin içini göremez, değiştiremez. Güvenlik modelinin tamamı bu tek varsayıma yaslanır.
Golden Ticket: Neden Parola Değiştirmek Yetmez
Bu varsayım bir kez bozulduğunda — yani saldırgan krbtgt hesabının parola hash’ini ele geçirdiğinde — kendisi bilet üretebilir. İstediği kullanıcı adıyla, istediği grup üyelikleriyle, istediği geçerlilik süresiyle. Buna Golden Ticket denir ve yıkıcı olmasının nedeni şudur: bilet KDC tarafından üretilmiş gibi görünür, çünkü geçerli anahtarla imzalanmıştır.
Buradan çıkan sonuç sezgilere aykırıdır. Ele geçirilmiş bir ortamda:
- Tüm kullanıcı parolalarını sıfırlamak Golden Ticket’ı durdurmaz — saldırganın kullanıcı parolasına ihtiyacı yok, bilet zaten üretilmiş durumda.
- Domain Admin hesaplarını silmek durdurmaz — saldırgan var olmayan bir kullanıcı adına bile bilet üretebilir.
- Tüm DC’leri yeniden başlatmak durdurmaz.
Golden Ticket’ı geçersiz kılan tek şey, biletin imzalandığı anahtarın değişmesidir: krbtgt parolasının döndürülmesi. Ve burada, bu yazının en çok yanlış yapılan ayrıntısı devreye girer.
Rotasyon Öncesi Ölçüm: krbtgt Kaç Yaşında?
Rotasyona karar vermeden önce mevcut durumu okuyun. krbtgt hesabının parolasının en son ne zaman değiştiğini ve anahtar sürüm numarasını (KVNO, msDS-KeyVersionNumber) sorguluyoruz:
Get-ADUser krbtgt -Properties Created, PasswordLastSet, msDS-KeyVersionNumber |
Select-Object SamAccountName, Created, PasswordLastSet, msDS-KeyVersionNumber
SamAccountName : krbtgt
Created : 20.06.2026 14:12:37
PasswordLastSet : 20.06.2026 14:12:37
msDS-KeyVersionNumber : 2
Created ile PasswordLastSet aynı: bu hesabın parolası domain kurulduğu günden beri hiç değişmemiş. Bizim labımızda bu 84 günlük bir gecikme demek; sizin ortamınızda muhtemelen domain’in kurulduğu yıla kadar gidiyordur. Yaşı gün cinsinden isterseniz:
[int](New-TimeSpan -Start (Get-ADUser krbtgt -Properties PasswordLastSet).PasswordLastSet `
-End (Get-Date)).TotalDays
84
Bu sayı, geçmişte yaşanmış bir ele geçirilmenin hâlâ geçerli olup olmadığını söyler. krbtgt beş yıldır değişmediyse, beş yıl önce sızmış bir saldırganın ürettiği Golden Ticket bugün hâlâ çalışır.
İki Parola Kuralı: Bir Sıfırlama Neden Yarım İştir
Active Directory, krbtgt hesabı için iki parola sürümü tutar: geçerli olan (N) ve bir öncekisi (N-1). KDC, her iki anahtarla şifrelenmiş bileti de kabul eder. Bunun nedeni makul: parola değiştiği anda o sırada dolaşımda olan tüm biletler geçersiz olsaydı, her rotasyon domain çapında bir kesinti olurdu.
Ama güvenlik açısından sonucu şudur: tek bir sıfırlama, çalınmış anahtarı yalnızca “önceki sürüm” konumuna taşır — hâlâ geçerlidir. Anahtarı gerçekten devre dışı bırakmak için iki kez sıfırlamanız gerekir.
graph LR
A["Başlangıç<br/>KVNO 2<br/>hiç döndürülmedi"] --> B["1. sıfırlama<br/>KVNO 3<br/>geçerli: 3 · önceki: 2"]
B --> C["Replikasyon<br/>+ en az 10 saat<br/>(azami TGT ömrü)"]
C --> D["2. sıfırlama<br/>KVNO 4<br/>geçerli: 4 · önceki: 3"]
D --> E["Anahtar 2 artık<br/>kabul edilmiyor"]
Aradaki bekleme süresi keyfi değil, azami TGT ömründen gelir. Varsayılan domain politikasında bir kullanıcı biletinin azami ömrü 10 saat, yenileme ömrü 7 gündür. İlk sıfırlamadan sonra dolaşımdaki biletlerin doğal yoldan sona ermesi için en az bir bilet ömrü beklemek gerekir; bir bilet yenilendiğinde KDC onu güncel anahtarla yeniden düzenlediği için 7 günü beklemek gerekmez. Politikanızı değiştirdiyseniz kendi değerinizi okuyun:
Get-GPOReport -Name "Default Domain Policy" -ReportType Xml |
Select-String -Pattern "MaxTicketAge|MaxRenewAge|MaxServiceAge|MaxClockSkew"
Rotasyonu Yapmak: Microsoft’un New-KrbtgtKeys Script’i
Kendi script’inizi yazmayın; Microsoft bu iş için resmî bir araç yayımlıyor: New-KrbtgtKeys.ps1. Kendi yazacağınız üç satıra göre üç şeyi fazladan yapar ve üçü de önemlidir:
- Rotasyondan önce tüm DC’lerin erişilebilir ve replikasyonun sağlıklı olduğunu doğrular; bir DC ulaşılamıyorsa durur.
- Yalnızca simülasyon modunda çalıştırılabilir (gerçekten sıfırlamadan neyi değiştireceğini gösterir).
- RODC’lerin kendi
krbtgthesaplarını ayrı ayrı ele alır.
Aracı kullanamıyorsanız manuel yol şudur — ama iki uyarıyla:
# UYARI 1: Bu komut tüm domain'i etkiler. Bakım penceresinde çalıştırın.
# UYARI 2: Verdiğiniz parola KULLANILMAZ. krbtgt için AD rastgele bir parola
# üretir; komut yine de bir parola parametresi ister.
Set-ADAccountPassword -Identity krbtgt -Reset `
-NewPassword (Read-Host -AsSecureString -Prompt 'Yer tutucu parola')
# Sıfırlamayı tüm DC'lere it — beklemeyin, itin.
repadmin /syncall DUMBLEDORE-DC01 /AdeP
repadmin /syncall bayrakları: /A bu DC’nin tuttuğu tüm bölümleri (naming context) kapsar, /d sunucuları DN ile adlandırır, /e site sınırlarını aşar, /P değişikliği karşı tarafa iter (çekmez). Tek bir site varsa /e zararsızdır, çok siteli ortamda şarttır.
Doğrulama: Her DC’de KVNO Arttı mı?
Rotasyondan sonra tek bir DC’ye sorup “oldu” demek, hiçbir şey doğrulamaz — sıfırlamayı yaptığınız DC zaten yeni değeri gösterecektir. Doğrulamanın anlamlı olması için soruyu her DC’ye ayrı ayrı sormanız gerekir:
foreach ($dc in (Get-ADDomainController -Filter *).HostName) {
Get-ADUser krbtgt -Server $dc -Properties PasswordLastSet, msDS-KeyVersionNumber |
Select-Object @{n='DC';e={$dc}},
@{n='KVNO';e={$_.'msDS-KeyVersionNumber'}},
PasswordLastSet
}
İstediğimiz çıktı:
DC KVNO PasswordLastSet
-- ---- ---------------
DUMBLEDORE-DC01.hogwarts.local 3 12.09.2026 09:14:02
MCGONAGALL-DC02.hogwarts.local 3 12.09.2026 09:14:02
Birinci sıfırlamadan sonra görmemiz gereken çıktı buysa, görmememiz gereken çıktı da şudur:
DC KVNO PasswordLastSet
-- ---- ---------------
DUMBLEDORE-DC01.hogwarts.local 3 12.09.2026 09:14:02
MCGONAGALL-DC02.hogwarts.local 2 20.06.2026 14:12:37
MCGONAGALL-DC02 hâlâ eski anahtarda. Bu durumda ikinci sıfırlamaya geçmeyin — önce replikasyonu düzeltin (repadmin /showrepl MCGONAGALL-DC02), yeni anahtarın oraya ulaştığını görün, sonra devam edin.
Anahtarın yalnızca kâğıt üzerinde değil gerçekten sahada değiştiğini görmek isterseniz, bir istemcide biletleri temizleyip yeniden alın:
C:\> klist purge
C:\> dir \\FILCH-FS01\Dersler > nul
C:\> klist | findstr /C:"Server:" /C:"KerbTicket"
Server: krbtgt/HOGWARTS.LOCAL @ HOGWARTS.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Server: cifs/FILCH-FS01.hogwarts.local @ HOGWARTS.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
DC’nin Security günlüğünde bu girişin karşılığı Event ID 4768 (Kerberos TGT talep edildi) olur ve başarıyla dönmüş olması gerekir. Bu olayların günlüğe düşmesi için DC’lerde Account Logon → Audit Kerberos Authentication Service denetim alt kategorisi başarı ve başarısızlık için açık olmalıdır; kapalıysa aradığınız satır hiç yazılmaz.
İkinci Sıfırlama: Rotasyon Ne Zaman Biter?
Her DC’de 3 gördükten ve en az bir bilet ömrü (10 saat) bekledikten sonra ikinci sıfırlamayı aynı komutla yapar, aynı repadmin /syncall‘ı çeker ve aynı doğrulama döngüsünü yeniden çalıştırırız. Bu kez beklenen değer 4‘tür:
DC KVNO PasswordLastSet
-- ---- ---------------
DUMBLEDORE-DC01.hogwarts.local 4 12.09.2026 21:30:18
MCGONAGALL-DC02.hogwarts.local 4 12.09.2026 21:30:18
Rotasyon ancak bu tabloyu her DC’de gördüğünüzde bitmiştir. 3‘te durursanız çalınmış anahtar “önceki sürüm” olarak kabul edilmeye devam eder — iş yapılmamıştır, ama yapılmış sanılır ki bu, hiç başlamamış olmaktan tehlikelidir.
Burada Şu Şekilde Batarsınız: İki Sıfırlamayı Arka Arkaya Yapmak
En sık yapılan hata, iki sıfırlamayı arka arkaya çalıştırmaktır — “nasılsa iki kez gerekiyormuş” diye. Sonuç: o anda dolaşımda olan tüm TGT’ler bir anda çöpe gider. İnteraktif kullanıcıların çoğu bunu fark etmez (Windows LSA’daki önbelleğe alınmış kimlikle sessizce yeniden kimlik doğrular), ama fark edenler şunlardır:
- Kerberos ile kimlik doğrulayan servis hesapları ve bunların açık oturumları.
- Zamanlanmış görevler ve uzun süren toplu işler.
- Karşılıklı kimlik doğrulama (mutual authentication) yapan uygulama sunucuları — kesilen bir bağlantı kendiliğinden geri gelmeyebilir.
- Ve en kötüsü: ilk sıfırlamayı almamış bir DC, ikinci sıfırlamadan sonra ne eski ne yeni anahtarla eşleşen bir duruma düşer; o DC’ye yönelen istemciler kimlik doğrulayamaz.
Buna karşılık, iki sıfırlamayı arka arkaya yapmanın doğru olduğu tek bir durum vardır: aktif bir ele geçirilmeden kurtuluyorsanız. Microsoft’un orman kurtarma (AD Forest Recovery) prosedürü tam olarak bunu söyler — çünkü orada kesinti istenen sonuçtur, yan etki değil. Ayrım nettir:
| Durum | Yapılacak | Neden |
|---|---|---|
| Planlı rotasyon (180 günlük takvim) | İki sıfırlama arasında en az 10 saat, tercihen 24 saat | Kullanıcı biletleri doğal yoldan sona ersin |
| Aktif ele geçirilme / orman kurtarma | İki sıfırlama arka arkaya, planlı kesinti penceresinde | Saldırganın biletini 10 saat daha yaşatmak kabul edilemez |
| Tier 0 yetkili bir yönetici işten ayrıldı | Ayrılış prosedürünün parçası olarak rotasyon başlat | Hesabı kapatmak, o kişinin kopyaladığı hash’i geçersiz kılmaz |
RODC’lerin Kendi krbtgt Hesapları Vardır
Salt okunur domain controller (RODC) kullanıyorsanız iş bitmedi. Her RODC’nin kendine ait bir krbtgt_<numara> hesabı vardır ve ana krbtgt‘yi döndürmek onları döndürmez. Listelemek için:
Get-ADUser -Filter 'SamAccountName -like "krbtgt_*"' -Properties msDS-KeyVersionNumber |
Select-Object SamAccountName, msDS-KeyVersionNumber, PasswordLastSet
Bizim hogwarts.local ortamımızda RODC yok, bu yüzden komut boş döner. Sizin ortamınızda dönerse, listelenen her hesap ayrı bir rotasyon işidir; Microsoft’un script’i bunları da kapsar.
Sağlık Kontrolü Takvimi: Günlük, Haftalık, Aylık
krbtgt rotasyonu altı ayda bir yapılan bir iş. Peki aradaki 180 gün? Aşağıdaki takvim, bir AD ortamının sessizce bozulabildiği noktaları sıklığa göre dağıtır. Mantık basit: bir kontrolü ne kadar sık yapmanız gerektiği, o şeyin bozulmasıyla fark edilmesi arasında kaç gün geçebileceğine bağlıdır.
Günlük: Replikasyon Akıyor mu, DC’ler Ayakta mı?
Bunlar otomatikleştirilmesi gereken, insanın her gün bakmayacağı kontrollerdir — izleme sisteminize koyun (Prometheus/Grafana kurulumunu daha önce ele almıştık).
| Kontrol | Komut | Alarm eşiği |
|---|---|---|
| Replikasyon hatası | repadmin /replsummary |
fails sütunu > 0 |
| Replikasyon kuyruğu | repadmin /queue DUMBLEDORE-DC01 |
Kuyruk boşalmıyorsa |
| DC servisleri | Get-Service NTDS,DNS,Netlogon,W32Time,KDC |
Running değilse |
NTDS.dit diskinde alan |
Get-PSDrive C |
%15’in altı |
| Kritik olay kimlikleri | Directory Service günlüğü: 1311, 1388, 1988, 2042, 2095 | Herhangi biri |
repadmin /replsummary sağlıklı bir ortamda şöyle görünür:
Replication Summary Start Time: 2026-09-12 08:00:03
Beginning data collection for replication summary, this may take awhile:
.....
Source DSA largest delta fails/total %% error
DUMBLEDORE-DC01 :22:14 0 / 5 0
MCGONAGALL-DC02 :19:47 0 / 5 0
Destination DSA largest delta fails/total %% error
DUMBLEDORE-DC01 :19:47 0 / 5 0
MCGONAGALL-DC02 :22:14 0 / 5 0
Tabloyu iki yönlü okuyun: Source bloğu “bu DC’den başkalarına akış”, Destination bloğu “başkalarından bu DC’ye akış”. Bir DC’nin yalnızca bir yönde sorunlu olması sık görülür ve tek yöne bakarsanız kaçırırsınız.
Haftalık: dcdiag, Ayrıcalıklı Gruplar, Kilitli Hesaplar
| Kontrol | Komut | Ne arıyoruz |
|---|---|---|
| Kapsamlı DC teşhisi | dcdiag /c /v /e /f:C:\ADReports\dcdiag.txt |
failed test satırları |
| Ayrıcalıklı grup üyeliği | Get-ADGroupMember 'Domain Admins' -Recursive |
Geçen haftaya göre fark |
| Kilitli hesaplar | Search-ADAccount -LockedOut |
Tekrar eden aynı hesap |
| Son yedek yaşı | repadmin /showbackup * |
7 günden eskiyse |
| Saat sapması | w32tm /monitor |
5 dakikaya yaklaşan sapma |
İki noktanın altını çizelim. Birincisi: ayrıcalıklı grup listesini saklamak değil, geçen haftakiyle karşılaştırmak işe yarar. “Domain Admins’te 4 kişi var” bir bilgi değildir; “Domain Admins’te geçen hafta 4 kişi vardı, bu hafta 5” bir olaydır.
İkincisi: Kerberos’un varsayılan saat toleransı 5 dakikadır. w32tm /monitor çıktısında bir DC’nin sapması bu sınıra yaklaşıyorsa, o DC’de kimlik doğrulama rastgele başarısız olmaya başlar ve hata mesajı size saatten hiç söz etmez. Saat hiyerarşisinin nasıl kurulduğunu kurulum yazısında ele almıştık.
C:\> w32tm /monitor
DUMBLEDORE-DC01.hogwarts.local *** PDC ***[192.168.1.231:123]:
ICMP: 0ms delay
NTP: +0.0000000s offset from DUMBLEDORE-DC01.hogwarts.local
RefID: tick.example.com [203.0.113.19]
Stratum: 3
MCGONAGALL-DC02.hogwarts.local [192.168.1.232:123]:
ICMP: 1ms delay
NTP: -0.0341172s offset from DUMBLEDORE-DC01.hogwarts.local
RefID: DUMBLEDORE-DC01.hogwarts.local [192.168.1.231]
Stratum: 4
MCGONAGALL-DC02‘nin RefID‘si PDC’yi gösteriyor, PDC’ninki dış NTP kaynağını: hiyerarşi doğru kurulmuş. Sapma 34 milisaniye, tolerans 5 dakika — rahat.
Aylık: Tombstone, FSMO, SYSVOL, RID Havuzu
Bunlar yılda birkaç kez değişen ama değiştiğinde pahalıya patlayan şeylerdir.
Tombstone ömrü. Bir DC bu süreden uzun süre çevrimdışı kalırsa geri bağlanmamalıdır — bağlanırsa, diğer DC’lerde çoktan silinmiş nesneleri “hâlâ var” diye geri yayar (lingering object). Değerinizi okuyun:
$cfg = (Get-ADRootDSE).configurationNamingContext
Get-ADObject "CN=Directory Service,CN=Windows NT,CN=Services,$cfg" `
-Properties tombstoneLifetime, msDS-deletedObjectLifetime |
Select-Object tombstoneLifetime, msDS-deletedObjectLifetime
tombstoneLifetime msDS-deletedObjectLifetime
----------------- --------------------------
180
Bir tuzak: tombstoneLifetime özniteliği hiç ayarlanmamışsa (boş dönerse) etkin değer 180 değil, 60 gündür. Windows Server 2003 SP1 ve sonrasında kurulan ormanlar 180 ile gelir; daha eski bir ormandan yükseltilmiş ortamlarda bu alan boş kalmış olabilir. Boş görürseniz 60 güne göre plan yapın veya değeri açıkça yazın.
Lingering object bulduysanız — Directory Service günlüğünde Event ID 1988 bunu haber verir ve o bölüm için gelen replikasyonu durdurur — önce ne yapacağını göster, sonra yap:
# Önce advisory_mode: hiçbir şey silmez, yalnızca ne sileceğini olay günlüğüne yazar.
repadmin /removelingeringobjects MCGONAGALL-DC02 `
<DUMBLEDORE-DC01-ObjectGUID> "DC=hogwarts,DC=local" /advisory_mode
# Rapor beklediğiniz gibiyse aynı komutu /advisory_mode olmadan çalıştırın.
FSMO sahipliği. Beş rolün kimde olduğunu bilmek, bir DC’yi emekliye ayırmadan önce sormanız gereken ilk sorudur:
C:\> netdom query fsmo
Şema yöneticisi DUMBLEDORE-DC01.hogwarts.local
Etki alanı adlandırma yöneticisi DUMBLEDORE-DC01.hogwarts.local
PDC DUMBLEDORE-DC01.hogwarts.local
RID havuzu yöneticisi DUMBLEDORE-DC01.hogwarts.local
Altyapı yöneticisi DUMBLEDORE-DC01.hogwarts.local
Komut başarıyla tamamlandı.
SYSVOL replikasyonu. SYSVOL’ün DFSR’a geçmiş olduğunu ve geride kalan iş olmadığını doğrulayın:
# "Eliminated" görmelisiniz — FRS tamamen bırakılmış demektir.
dfsrmig /getglobalstate
# İki yönde de birikmiş iş var mı?
Get-DfsrBacklog -GroupName "Domain System Volume" -FolderName "SYSVOL Share" `
-SourceComputerName DUMBLEDORE-DC01 -DestinationComputerName MCGONAGALL-DC02
Get-DfsrBacklog -GroupName "Domain System Volume" -FolderName "SYSVOL Share" `
-SourceComputerName MCGONAGALL-DC02 -DestinationComputerName DUMBLEDORE-DC01
İki yönü de sorduğumuza dikkat edin: Get-DfsrBacklog tek yönlüdür ve bir yön temiz çıktı diye diğeri temiz değildir. dfsrmig çıktısı Eliminated yerine Prepared veya Redirected gösteriyorsa geçiş yarıda kalmıştır; FRS, Windows Server 2016 ile desteklenmez ve domain fonksiyonel seviyesini yükseltmenizi engeller.
RID havuzu. Her DC, RID Master’dan 500’lük bloklar hâlinde RID alır ve yeni her kullanıcı/grup/bilgisayar bir RID tüketir. Havuzun tavanı yaklaşık 1.07 milyardır ve tükenmesi gerçek bir olaydır — otomasyonla nesne oluşturup silen ortamlarda beklenenden hızlı yaklaşılır:
dcdiag /test:RidManager /v /s:DUMBLEDORE-DC01
Atıl hesap raporu. Bunu bir sonraki bölümde ayrıntısıyla ele alıyoruz; aylık takvimdeki yeri, listeyi üretmek — silmek değil.
Altı Ayda Bir: krbtgt Rotasyonu ve Geri Yükleme Tatbikatı
Altı aylık kutuda iki iş var. Birincisi bu yazının ilk bölümü: krbtgt rotasyonu.
İkincisi daha zorudur çünkü kimse yapmak istemez: yedekten geri yükleme tatbikatı. repadmin /showbackup size son yedeğin ne zaman alındığını söyler:
C:\> repadmin /showbackup *
DUMBLEDORE-DC01
DSA Object GUID: 4b1c7e39-a082-4d15-93f7-6c5e08a1d2b4
DC=hogwarts,DC=local
2026-09-08 02:15:41
CN=Configuration,DC=hogwarts,DC=local
2026-09-08 02:15:41
CN=Schema,CN=Configuration,DC=hogwarts,DC=local
2026-09-08 02:15:41
Bu çıktı yedeğin alındığını kanıtlar, geri yüklenebildiğini kanıtlamaz — ve bu ikisi aynı şey değildir. Alınmış ama hiç denenmemiş bir yedek, olay anında bir yedek değil bir varsayımdır. Tatbikat şöyle yürür:
- DC üzerinde sistem durumu yedeğini alın — ayrı bir birime, sistem diskine değil:
wbadmin start systemstatebackup -backupTarget:E: -quiet - Yedeği izole bir ağa kurulmuş boş bir sunucuya geri yükleyin — üretim ağına asla değil.
- Dizin Hizmetleri Onarım Modu’nda (DSRM) açılıp geri yüklemeyi tamamlayın.
- İzole ağda bir test istemcisiyle domain’e giriş yapın ve
dcdiagçalıştırın. Tatbikatın başarı ölçütü budur: “yedek açıldı” değil, “izole ağda bir kullanıcı gerçekten giriş yapabildi”.
⚠️ Hipervizör anlık görüntüsü (snapshot) bir DC yedeği değildir. Bir DC’yi snapshot’tan geri almak, hipervizör ve DC birlikte VM-GenerationID‘yi desteklemiyorsa USN rollback’e yol açar: DC, başkalarına zaten gönderdiği değişiklik numaralarını yeniden kullanmaya başlar ve ortaya sessiz, kalıcı bir tutarsızlık çıkar. Windows Server 2012 ve üzeri DC’ler bu koruma mekanizmasını destekler, ama hipervizör tarafının da desteklemesi gerekir — sürümünüz için üreticinin dokümanından doğrulayın. USN rollback’in yakalanması hâlinde Directory Service günlüğünde Event ID 2095 görünür ve NTDS gelen replikasyonu durdurur.
Haftalık Sağlık Raporunu Üreten Script
Yukarıdaki haftalık kutuyu tek bir script’e topluyoruz. Hiçbir şey değiştirmez, yalnızca okur ve dosyaya yazar — zamanlanmış görev olarak çalıştırabilirsiniz:
# ===========================================================
# hogwarts.local — Haftalık AD Sağlık Raporu
# Önkoşul: ActiveDirectory modülü (RSAT veya bir DC üzerinde).
# Salt okunur: hiçbir nesneyi değiştirmez.
# Not : Enterprise Admins ve Schema Admins yalnızca orman
# kök domain'inde bulunur; alt domain'de boş döner.
# ===========================================================
Import-Module ActiveDirectory
$Rapor = "C:\ADReports\saglik-{0:yyyy-MM-dd}.txt" -f (Get-Date)
New-Item -ItemType Directory -Path (Split-Path $Rapor) -Force | Out-Null
$DCs = (Get-ADDomainController -Filter *).HostName
function Baslik($metin) { "`n===== $metin =====" }
& {
Baslik "1) Replikasyon ozeti (iki yon)"
repadmin /replsummary
Baslik "2) Replikasyon kuyrugu"
foreach ($dc in $DCs) { "--- $dc"; repadmin /queue $dc }
Baslik "3) krbtgt yasi ve anahtar surumu (HER DC'den ayri ayri)"
# foreach IFADESI boru hattina baglanamaz; ForEach-Object kullaniyoruz.
$DCs | ForEach-Object {
$dc = $_
Get-ADUser krbtgt -Server $dc -Properties PasswordLastSet, msDS-KeyVersionNumber |
Select-Object @{n='DC';e={$dc}},
@{n='KVNO';e={$_.'msDS-KeyVersionNumber'}},
@{n='Gun';e={[int](New-TimeSpan -Start $_.PasswordLastSet -End (Get-Date)).TotalDays}}
} | Format-Table -AutoSize
Baslik "4) Ayricalikli grup uyelikleri (gecen haftayla KARSILASTIRIN)"
$Ayricalikli = 'Domain Admins','Enterprise Admins','Schema Admins','Administrators',
'Account Operators','Backup Operators','Server Operators',
'DnsAdmins','Group Policy Creator Owners'
foreach ($g in $Ayricalikli) {
$uyeler = Get-ADGroupMember -Identity $g -Recursive -ErrorAction SilentlyContinue
"{0,-30} : {1}" -f $g, (($uyeler.SamAccountName | Sort-Object) -join ', ')
}
Baslik "5) Kilitli hesaplar"
Search-ADAccount -LockedOut | Select-Object SamAccountName, LastLogonDate | Format-Table -AutoSize
Baslik "6) Son yedek (her bolum icin)"
repadmin /showbackup *
Baslik "7) Saat sapmasi (Kerberos toleransi 5 dakika)"
w32tm /monitor
} *>&1 | Tee-Object -FilePath $Rapor
"Rapor yazildi: $Rapor"
Raporu üretmek işin kolay yarısı. Zor yarısı, geçen haftakiyle karşılaştırmaktır — özellikle 4. bölümü. Dosyaları tarih adıyla sakladığınız için Compare-Object ile fark alabilirsiniz:
Compare-Object (Get-Content C:\ADReports\saglik-2026-09-05.txt) `
(Get-Content C:\ADReports\saglik-2026-09-12.txt)
Hesap Yaşam Döngüsü: Ayrılan Çalışandan Silmeye
Sağlık kontrollerinin en çok bulgu ürettiği yer hesaplardır — ve en çok yanlış karar verilen yer de burasıdır. Senaryomuz somut: Remus Lupin (rlupin) bir yıllık görevini tamamladı ve okuldan ayrılıyor. Kara Sanatlara Karşı Savunma dersini veriyordu, GG-Teachers ve GG-Course-Defence-Against-the-Dark-Arts gruplarının üyesi, OU=Teachers,OU=Hogwarts altında duruyor.
Sorumuz basit görünüyor: hesabını ne yapacağız? Silmek en temiz çözüm gibi duruyor. Değil.
Atıl Hesabı Bulmak: lastLogonTimestamp’ın 14 Günlük Gecikmesi
Önce atıl hesapları bulmanın standart yolu:
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -UsersOnly |
Where-Object { $_.Enabled } |
Select-Object SamAccountName, LastLogonDate, DistinguishedName |
Sort-Object LastLogonDate
Bu komut lastLogonTimestamp özniteliğini kullanır ve burada, çok sayıda hesabın yanlışlıkla kapatılmasına neden olan bir ayrıntı gizlidir. lastLogonTimestamp replike edilir ama her girişte güncellenmez — yalnızca mevcut değer, ms-DS-Logon-Time-Sync-Interval (varsayılan 14 gün) eksi rastgele bir paydan daha eskiyse yazılır. Amaç replikasyon trafiğini azaltmaktır ve sonucu şudur: öznitelik 14 güne kadar geriden gelebilir.
Bunun pratik karşılığı:
- 90 günlük eşikte sorun yok. 14 günlük sapma, 90 günlük bir aralıkta karar değiştirmez.
- 30 günlük eşikte tehlikeli. 20 gün önce giriş yapmış bir kullanıcı “34 gündür giriş yapmamış” görünüp eşiği geçebilir; eşiğin 14 gün altındaki her hesap için yanlış karar riski vardır.
Kesin cevabı istiyorsanız replike edilmeyen özniteliğe bakmanız gerekir: lastLogon. Bu öznitelik her DC’de ayrı tutulur ve yalnızca o DC’nin gördüğü girişleri bilir — yani doğru cevap, tüm DC’lere sorup en büyüğünü almaktır:
function Get-GercekSonGiris {
param([Parameter(Mandatory)][string]$Kullanici)
$enSon = [datetime]::FromFileTime(0)
foreach ($dc in (Get-ADDomainController -Filter *).HostName) {
$u = Get-ADUser $Kullanici -Server $dc -Properties lastLogon
$t = [datetime]::FromFileTime([int64]$u.lastLogon)
"{0,-32} {1}" -f $dc, $(if ($t.Year -lt 1700) { 'kayit yok' } else { $t })
if ($t -gt $enSon) { $enSon = $t }
}
"--> Gercek son giris: {0}" -f $(if ($enSon.Year -lt 1700) { 'kayit yok' } else { $enSon })
}
Get-GercekSonGiris -Kullanici rlupin
DUMBLEDORE-DC01.hogwarts.local kayit yok
MCGONAGALL-DC02.hogwarts.local 12.09.2026 08:42:11
--> Gercek son giris: 12.09.2026 08:42:11
Tek bir DC’ye sorsaydık rlupin için “hiç giriş yapmamış” cevabını alacaktık — çünkü rlupin hep MCGONAGALL-DC02 üzerinden kimlik doğrulamış; DUMBLEDORE-DC01 onun tek bir girişini bile görmemiş. Bir hesabı silmeden önce tüm DC’lere sorun; tek DC’nin cevabı bir veri değil, bir tesadüftür.
Çıktıdaki tarih bugüne ait: rlupin bu sabah 08:42’de son kez giriş yaptı. Ayrılış prosedürünü işte bu oturum açıkken başlatacağız — ve birazdan göreceğimiz gibi, bu ayrıntı prosedürün en kritik noktası.
0. Gün: Devre Dışı Bırak, Parolayı Sıfırla, Ayrıcalığı Kes
Ayrılış gününde yapılacaklar tek bir script’te toplanır. Sıra önemlidir — özellikle üyelik kaydının her şeyden önce alınması:
$Sam = 'rlupin'
$Karantina = 'OU=Karantina,OU=Hogwarts,DC=hogwarts,DC=local'
$RaporDizin = 'C:\ADReports\Ayrilanlar'
$Tarih = Get-Date -Format 'yyyy-MM-dd'
New-Item -ItemType Directory -Path $RaporDizin -Force | Out-Null
# 1) Uyelikleri ONCE kaydet. Hicbir seye dokunmadan once.
Get-ADPrincipalGroupMembership -Identity $Sam |
Select-Object Name, GroupScope, DistinguishedName |
Export-Csv "$RaporDizin\$Sam-uyelikler-$Tarih.csv" -NoTypeInformation -Encoding UTF8
# 2) Parolayi sifirla — yeni TGT alinmasini engeller.
Set-ADAccountPassword -Identity $Sam -Reset `
-NewPassword (Read-Host -AsSecureString -Prompt 'Atilacak parola')
# 3) Devre disi birak.
Disable-ADAccount -Identity $Sam
# 4) YALNIZCA ayricalikli uyelikleri hemen kaldir. Digerlerine dokunma (asagida neden).
$Ayricalikli = 'Domain Admins','Enterprise Admins','Schema Admins','Administrators',
'Account Operators','Backup Operators','Server Operators','DnsAdmins'
foreach ($g in $Ayricalikli) {
$uye = Get-ADGroupMember -Identity $g -Recursive -ErrorAction SilentlyContinue |
Where-Object SamAccountName -eq $Sam
if ($uye) { Remove-ADGroupMember -Identity $g -Members $Sam -Confirm:$false }
}
# 5) Aciklamaya tarih, gerekce ve silme tarihi yaz.
Set-ADUser -Identity $Sam -Description `
("AYRILDI $Tarih | IK-2026-0417 | silme tarihi: {0:yyyy-MM-dd}" -f (Get-Date).AddDays(90))
# 6) Karantina OU'suna tasi.
Move-ADObject -Identity (Get-ADUser $Sam).DistinguishedName -TargetPath $Karantina
Beşinci adım küçük görünür ama en çok geri dönüşü olan adımdır: üç ay sonra karantinaya bakan kişi, o hesabın neden orada olduğunu ve ne zaman silineceğini nesnenin kendisinden okuyabilmelidir. Açıklamasız bir karantina OU’su, bir süre sonra kimsenin silmeye cesaret edemediği bir mezarlığa döner.
OU=Karantina için iki ayar şart: kalıtımı engelleyin (üstteki OU’lardan gelen GPO’lar buraya uygulanmasın) ve hesap açan otomasyonlarınızın kapsamı dışında tutun.
Devre Dışı Bırakmak Açık Oturumu Anında Kapatmaz
Burada, çoğu ayrılış prosedüründe eksik olan gerçek var. Disable-ADAccount çalıştı, hesap kapandı — ama rlupin o sırada OGRETMEN-PC07 başında oturuyorsa ne olur?
Sabah 08:42’de giriş yapmış ve TGT’sini almış olsun:
C:\> klist
Gecerli Oturum Acma Kimligi: 0:0x3f8a21
Onbellege alinmis bilet: (2)
#0> Client: rlupin @ HOGWARTS.LOCAL
Server: krbtgt/HOGWARTS.LOCAL @ HOGWARTS.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
Start Time: 12.09.2026 08:42:11 (local)
End Time: 12.09.2026 18:42:11 (local)
Renew Time: 19.09.2026 08:42:11 (local)
#1> Client: rlupin @ HOGWARTS.LOCAL
Server: cifs/FILCH-FS01.hogwarts.local @ HOGWARTS.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Start Time: 12.09.2026 08:43:02 (local)
End Time: 12.09.2026 18:42:11 (local)
Hesabı 10:05’te devre dışı bıraktık. 10:06’da rlupin hâlâ \\FILCH-FS01\Dersler paylaşımını açabilir. Çünkü hedef sunucu, elindeki servis biletini kriptografik olarak doğrular; her erişimde Domain Controller’a “bu hesap hâlâ açık mı?” diye sormaz. Bilet 18:42’ye kadar geçerli — yani devre dışı bırakma, en kötü durumda azami bilet ömrü kadar (varsayılan 10 saat) gecikmeli çalışır.
Bunun gerçekten böyle olduğunu görmek ve düzeltmenin işe yaradığını doğrulamak için klist purge yeterli — çünkü önbellek temizlendikten sonra istemci yeni bilet istemek zorundadır:
C:\> klist purge
Mevcut oturum acma kimligi 0:0x3f8a21 icin biletler temizleniyor
C:\> dir \\FILCH-FS01\Dersler
Oturum acma hatasi: hesabiniz devre disi birakildi.
DC’nin Security günlüğündeki karşılığı Event ID 4768, Result Code (Sonuç Kodu) 0x12‘dir — KDC_ERR_CLIENT_REVOKED: istemci kimlik bilgileri iptal edilmiş, yani hesap devre dışı, süresi dolmuş veya kilitli. Kodu karıştırmayın: yanlış parola 0x18‘dir ve 4768’de değil, Event ID 4771‘de görünür. Bu iki çıktı ayrımı önemlidir: ilk klist hesap açıkken de aynı görünürdü, ikinci çıktı ise yalnızca hesap kapalıyken ortaya çıkar.
Boşluğu kapatmak için ayrılış prosedürüne üç adım daha ekleyin:
# Dosya sunucusundaki acik SMB oturumlarini kapat.
Get-SmbSession -CimSession FILCH-FS01 |
Where-Object ClientUserName -eq 'HOGWARTS\rlupin' |
Close-SmbSession -Force
# Terminal/RDS oturumlarini dusur. Once oturum kimligini ogren...
quser /server:FILCH-FS01
# KULLANICIADI OTURUM KIMLIK DURUM BOSTA OTURUM ACMA ZAMANI
# rlupin rdp-tcp#4 3 Etkin 12 12.09.2026 08:44
# ...sonra o kimlikle dusur.
logoff 3 /server:FILCH-FS01
Üçüncüsü politikadır: hesabı kapatmak tek başına yeterli değilse, çıkışın fiziksel ayağını da planlayın — cihazın teslim alınması, VPN/NAC üzerinden erişimin kesilmesi. Bulut kimliği de kullanıyorsanız oradaki yenileme jetonlarının (refresh token) ayrıca iptal edilmesi gerekir; şirket içi hesabı kapatmak onları kendiliğinden geçersiz kılmaz.
Bu üç adım pencereyi olay olduktan sonra kapatır. Pencereyi önceden daraltan resmî bir özellik de vardır: Protected Users güvenlik grubu, üyelerinin TGT ömrünü ve yenileme süresini domain politikasından bağımsız olarak 240 dakikaya sabitler ve yenilemeye izin vermez — en kötü durum 10 saatten 4 saate iner. Bedeli küçük değildir: üyeler yalnızca AES ile Kerberos kullanabilir (NTLM, DES ve RC4 kapanır), kısıtlı veya kısıtsız delegasyon yapamaz, çevrimdışı oturum açamaz ve domain fonksiyonel seviyesi en az Windows Server 2012 R2 olmalıdır. Microsoft bilgisayar ve servis hesaplarının bu gruba hiç eklenmemesini, Domain Admins üyelerinin ise ancak sınandıktan sonra eklenmesini söyler; aksi halde kilitlenme riski vardır. Yani bu, ayrıcalıklı insan hesapları için doğru bir yatırımdır — herkese basılacak bir düğme değil.
1-30. Gün: Karantina, Veri Devri ve Üyelik Kaydı
Karantinadaki 30 gün bir bekleme değil, bir devir teslim dönemidir:
- Kişisel sürücüsü ve posta kutusu yöneticisine devredilir.
- O hesabın sahibi olduğu paylaşımlar, zamanlanmış görevler ve uygulama kayıtları yeni sahibine geçirilir.
- Hesabın sahip olduğu dosyaların ACL’lerinde adı geçen yerler tespit edilir (silme sonrası bunlar çözümlenemeyen SID’e döner — bir sonraki bölümde).
Bu dönemde ayrıcalıklı olmayan grup üyeliklerini kaldırmayın. Kulağa ters geliyor, ama nedeni Recycle Bin’in çalışma biçiminde: geri yükleme, nesne silindiği andaki üyelikleri geri getirir. Üyelikleri silmeden önce tek tek kaldırırsanız, geri yükleme size boş bir hesap döndürür ve CSV’den elle geri kurmanız gerekir. Hesap zaten devre dışı olduğu için üyeliklerin durması bir erişim riski yaratmaz — ayrıcalıklı olanları zaten 0. günde kaldırdık.
90. Gün: Silme ve Geri Dönüşü Olmayan SID
Silmeden önce, geri alınamayacak olan şeyin ne olduğunu netleştirelim. Her AD nesnesinin bir SID‘i vardır ve dosya izinleri, paylaşım izinleri, posta kutusu yetkileri, uygulama yetkilendirmeleri — hepsi kullanıcı adını değil, bu SID’i tutar:
Get-ADUser rlupin -Properties SID | Select-Object SamAccountName, SID
SamAccountName SID
-------------- ---
rlupin S-1-5-21-1874506631-1745523862-2072745206-1132
Hesabı sildiğiniz anda bu SID’i işaret eden her izin sahipsiz kalır. FILCH-FS01 üzerindeki ders klasöründe bu şöyle görünür:
C:\> icacls D:\Paylasim\Dersler\DADA
D:\Paylasim\Dersler\DADA S-1-5-21-1874506631-1745523862-2072745206-1132:(OI)(CI)(M)
HOGWARTS\GG-Teachers:(OI)(CI)(RX)
BUILTIN\Administrators:(I)(F)
Ve asıl tuzak şurada: rlupin bir yıl sonra okula geri dönerse ve aynı adla yeni bir hesap açarsanız, o hesap yeni bir SID alır. Eski izinler ona geçmez; yukarıdaki satır sahipsiz kalmaya devam eder. Kullanıcı adı aynı, kişi aynı, erişim yok.
⚠️
Remove-ADUser‘a basmadan önce tek bir soruyu cevaplayın: AD Recycle Bin açık mı? Kapalıysa aşağıdaki komut geri alınamaz ve elinizde yalnızca boş bir tombstone kalır. Bir sonraki bölümdekiGet-ADOptionalFeaturesorgusunu bu satırdan önce çalıştırın.
Silmeye karar verdiyseniz, önce kazara silmeye karşı koruma bayrağını kaldırmanız gerekebilir:
# Koruma acikken Remove-ADUser "Access is denied" verir — bayragi once kaldirin.
Set-ADObject -Identity (Get-ADUser rlupin).DistinguishedName `
-ProtectedFromAccidentalDeletion $false
Remove-ADUser -Identity rlupin -Confirm:$false
AD Recycle Bin: Silmeyi Geri Alınabilir Kılan Tek Şey
Yukarıdaki paragrafı okuduktan sonra akla gelen soru doğru sorudur: silmeyi geri alabilir miyiz? Yanıt, Active Directory Recycle Bin’i silmeden önce açmış olmanıza bağlıdır.
# Acik mi? EnabledScopes bos donerse kapalidir.
Get-ADOptionalFeature -Filter 'Name -like "Recycle Bin Feature"' |
Select-Object Name, EnabledScopes
Açmak için orman fonksiyonel seviyesinin en az Windows Server 2008 R2 olması gerekir:
Enable-ADOptionalFeature -Identity 'Recycle Bin Feature' `
-Scope ForestOrConfigurationSet -Target 'hogwarts.local' -Confirm:$false
⚠️ Bu işlem geri alınamaz. Recycle Bin bir kez açıldıktan sonra kapatılamaz. Etkisi genellikle olumludur (silinen nesneler öznitelikleriyle birlikte saklanır) ama
NTDS.ditboyutunu artırır ve orman fonksiyonel seviyesini geri düşürme seçeneğinizi fiilen ortadan kaldırır. Üretimde açmadan önce bilinçli bir karar olduğundan emin olun.
Recycle Bin kapalıyken silinen bir nesne tombstone olur: özniteliklerinin neredeyse tamamı temizlenir. Geri “canlandırma” mümkündür ve SID korunur, ama grup üyelikleri ve öznitelikler gelmez — elinizde yalnızca doğru SID’i taşıyan boş bir kabuk kalır. Recycle Bin açıkken ise nesne, bağ değerli öznitelikleri (grup üyelikleri dâhil) korunarak saklanır.
Saklama süresi msDS-deletedObjectLifetime ile belirlenir; ayarlanmamışsa tombstoneLifetime değerine eşittir — bizim ortamımızda 180 gün. Silinmiş nesneyi bulup geri yükleme:
Get-ADObject -Filter 'isDeleted -eq $true -and Name -like "Remus Lupin*"' `
-IncludeDeletedObjects -Properties lastKnownParent, whenChanged |
Select-Object Name, ObjectGUID, whenChanged, lastKnownParent
Name : Remus Lupin
DEL:d4f2a1c8-6b93-4e07-9a5d-2c81f3b06e4a
ObjectGUID : d4f2a1c8-6b93-4e07-9a5d-2c81f3b06e4a
whenChanged : 11.12.2026 10:22:07
lastKnownParent : OU=Karantina,OU=Hogwarts,DC=hogwarts,DC=local
Restore-ADObject -Identity 'd4f2a1c8-6b93-4e07-9a5d-2c81f3b06e4a' `
-TargetPath 'OU=Teachers,OU=Hogwarts,DC=hogwarts,DC=local'
Üç ayrıntı:
- Hedef OU var olmalıdır. Bir OU’yu ve içindekileri birlikte sildiyseniz önce OU’yu, sonra içindeki nesneleri geri yükleyin — tersi çalışmaz.
lastKnownParent, nesnenin silinmeden önce nerede durduğunu söyler. Karantinadan silinmiş bir hesabı doğrudan üretim OU’suna geri yüklüyorsanız bunu bilerek yapın.- Geri yükledikten sonra durumu doğrulayın. Hesabımız devre dışı olarak silinmişti, dolayısıyla devre dışı olarak geri gelir; kullanıcıyı gerçekten işe döndürüyorsanız
Enable-ADAccountve parola sıfırlama ayrı adımlardır.
Get-ADUser rlupin -Properties Enabled, PasswordLastSet, MemberOf |
Select-Object SamAccountName, Enabled, PasswordLastSet,
@{n='Gruplar';e={($_.MemberOf | ForEach-Object { ($_ -split ',')[0] -replace '^CN=' }) -join ', '}}
SamAccountName : rlupin
Enabled : False
PasswordLastSet : 12.09.2026 10:04:51
Gruplar : GG-Teachers, GG-Course-Defence-Against-the-Dark-Arts
Grupların geri gelmiş olması, Recycle Bin’in tombstone canlandırmasından farkının tek cümlelik kanıtıdır.
Tüm süreci tek bir takvimde toplarsak:
graph LR
G0["0. gün<br/>Üyelik CSV'si · parola sıfırla<br/>devre dışı · ayrıcalık kes<br/>oturumları kapat"] --> G1["1. gün<br/>Karantina OU'su<br/>açıklamaya silme tarihi"]
G1 --> G30["1-30. gün<br/>Veri ve görev devri<br/>üyeliklere DOKUNMA"]
G30 --> G90["90. gün<br/>Sil<br/>(Recycle Bin açık olmalı)"]
G90 --> G270["270. gün<br/>Recycle Bin süresi dolar<br/>geri dönüş yok"]
Bilgisayar ve Servis Hesapları Aynı Kurala Girmez
Atıl hesap raporunu kullanıcılarla sınırlamak eksik bir denetimdir, ama diğer iki nesne türü farklı kurallarla çalışır.
Bilgisayar hesapları. Bir domain üyesi makine, parolasını varsayılan olarak 30 günde bir kendisi değiştirir. Dolayısıyla 90 gündür hareketsiz bir bilgisayar hesabı, makinenin gerçekten kapalı olduğunun güvenilir bir göstergesidir:
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -ComputersOnly |
Where-Object { $_.Enabled -and $_.DistinguishedName -notlike '*OU=Domain Controllers*' } |
Select-Object Name, LastLogonDate, DistinguishedName |
Sort-Object LastLogonDate
Name LastLogonDate DistinguishedName
---- ------------- -----------------
OGRETMEN-PC03 02.05.2026 16:38:20 CN=OGRETMEN-PC03,OU=Teachers,OU=Hogwarts,DC=hogwarts,DC=local
Domain Controllers OU’sunu dışarıda bıraktığımıza dikkat edin. Aynı şekilde küme (cluster) nesnelerini de eleyin: bir failover cluster’ın CNO/VNO nesneleri düzenli giriş yapmaz ve listede masum şekilde atıl görünür — sildiğinizde kümeyi bozarsınız. Bilgisayar hesabında da önce devre dışı bırakın: makine bir gün geri gelirse hesabı yeniden açmak, domain’e yeniden katmaktan ucuzdur.
Servis hesapları. Bunlar atıl hesap raporunda en tehlikeli yanlış pozitiflerdir: bir servis hesabı yıllarca interaktif giriş yapmadan bir uygulamayı ayakta tutabilir. Bir servis hesabını, neyin kullandığını bulmadan asla silmeyin. İlk adım SPN’lere bakmaktır:
Get-ADUser -Filter 'ServicePrincipalName -like "*"' `
-Properties ServicePrincipalName, PasswordLastSet, LastLogonDate |
Select-Object SamAccountName, PasswordLastSet,
@{n='SPN';e={$_.ServicePrincipalName -join '; '}}
SamAccountName PasswordLastSet SPN
-------------- --------------- ---
svc-gringotts 20.06.2026 15:40:11 MSSQLSvc/gringotts-sql01.hogwarts.local:1433
SPN’i olan bir hesap Kerberos ile kimlik doğrulanan bir servisi temsil eder; ayrıca kerberoasting hedefidir (denetim araçları yazısında bu saldırıyı ele almıştık) ve PasswordLastSet değerinin domain kurulum tarihinde kalması iyi bir işaret değildir.
Uzun vadeli çözüm parolayı elle döndürmek değil, hesabı gMSA‘ya (group Managed Service Account) taşımaktır — parolasını AD’nin kendisi ürettiği ve varsayılan olarak 30 günde bir döndürdüğü bir hesap türü:
# Ormanda bir kez: KDS kok anahtari. Uretimde 10 saat sonra kullanilabilir olur.
Add-KdsRootKey -EffectiveImmediately
# YALNIZCA laboratuvarda beklememek icin:
# Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))
New-ADServiceAccount -Name gmsa-sql01 `
-DNSHostName gringotts-sql01.hogwarts.local `
-PrincipalsAllowedToRetrieveManagedPassword 'GRINGOTTS-SQL01$'
Eski hesabı bu geçişten sonra da hemen silmeyin: önce devre dışı bırakın, uygulamanın gMSA ile ayağa kalktığını doğrulayın, 90 günü bekleyin.
Sonuç
krbtgt‘yi bir kez sıfırlamak çalınmış anahtarı iptal etmez, yalnızca “önceki sürüm” rafına koyar. AD iki parola sürümü tuttuğu için Golden Ticket ikinci sıfırlamaya kadar geçerli kalır; aradaki en az 10 saatlik bekleme ve her DC’ye ayrı ayrı sorulan KVNO doğrulaması sıfırlamanın kendisi kadar prosedürün parçasıdır — replikasyon tamamlanmadan atılan ikinci adım saldırganı değil, yeni anahtarı almamış DC’ye yönelen kullanıcıları dışarıda bırakır.lastLogonTimestamp14 güne kadar geriden gelir; tek bir DC’ninlastLogondeğeri ise yalnızca o DC’nin gördüğünü bilir. 90 günlük eşikte bu sapma zararsızdır, 30 günlük eşikte çalışan hesabı atıl gösterir — kesin karar için tüm DC’lere sorun.- Devre dışı bırakmak kilidi değiştirir ama içerideki kişiyi çıkarmaz. Elindeki servis bileti azami bilet ömrü kadar (varsayılan 10 saat) geçerli kalır; parola sıfırlama, açık oturumların kapatılması ve cihaz teslimi aynı prosedürün parçasıdır —
Protected Usersüyeliği bu pencereyi peşinen 4 saate indirir. - Silmek, bu yazıdaki tek geri alınamaz adımdır — çünkü SID geri gelmez. Aynı adla açılan yeni hesap yeni bir SID alır ve eski izinlerin hiçbirini devralmaz; bu yüzden silme kararı 90 gün ertelenebilir, Recycle Bin ise silmeden önce açılmış olmalıdır.
Bu takvimin bir sonraki adımı, buradaki kontrolleri elle çalıştırmak yerine politikaya dönüştürmektir: denetim (audit) ayarlarının GPO ile merkezî olarak dağıtılması, böylece hangi olayın hangi DC’de günlüğe yazılacağının tek tek sunuculara bırakılmaması. Bu yazıdaki raporların bulduğu her zafiyetin karşılığı ise serinin sertleştirme ve denetim araçları yazılarındadır — takvim neyin bozulduğunu söyler, o iki yazı nasıl düzeltileceğini.
Ek: Terimler Sözlüğü
| Terim | Anlamı |
|---|---|
| TGT (Ticket Granting Ticket) | Kullanıcının girişte aldığı, krbtgt anahtarıyla şifrelenmiş ana Kerberos bileti. Diğer tüm servis biletleri bununla istenir. Varsayılan ömrü 10 saat. |
| KDC (Key Distribution Center) | Kerberos biletlerini dağıtan servis. Active Directory’de her Domain Controller aynı zamanda bir KDC’dir. |
KVNO (msDS-KeyVersionNumber) |
Bir hesabın Kerberos anahtar sürüm numarası. Her parola sıfırlamasında bir artar; rotasyonun tüm DC’lere ulaşıp ulaşmadığı bu sayıyla doğrulanır. |
| Golden Ticket | krbtgt hash’i ele geçirilerek üretilmiş sahte TGT. KDC üretmiş gibi görünür; yalnızca krbtgt parolasının iki kez döndürülmesiyle geçersiz kılınır. |
| SID (Security Identifier) | Bir nesnenin kalıcı ve benzersiz kimliği. İzinler kullanıcı adını değil SID’i tutar; nesne silindiğinde SID geri gelmez. |
| RID | SID’in son bölümü. krbtgt her domain’de 502, Domain Admins 512 gibi sabit değerler taşır. |
| Tombstone ömrü | Silinen bir nesnenin dizinde “silinmiş” işaretiyle kaldığı süre. Bu süreden uzun çevrimdışı kalan DC geri bağlanmamalıdır. Öznitelik boşsa etkin değer 60 gündür. |
| Lingering object | Bir DC’de silinmiş, diğerinde hâlâ duran nesne. Directory Service günlüğünde Event ID 1988 ile haber verilir ve replikasyonu durdurur. |
| USN rollback | Bir DC’nin daha önce dağıttığı değişiklik numaralarını yeniden kullanmaya başlaması. Desteklenmeyen geri yüklemelerin (ör. hipervizör snapshot’ı) sonucudur; Event ID 2095 ile yakalanır. |
| DFSR | SYSVOL replikasyonunun güncel motoru. Eski motor FRS, Windows Server 2016 ile desteklenmez. |
| gMSA | Parolasını Active Directory’nin ürettiği ve otomatik döndürdüğü (varsayılan 30 gün) servis hesabı türü. |