Active Directory (AD) ile ilgili en yaygın hatalardan biri, yönetim delegasyonunun güvensiz ve kaotik yapılması
Sahne Açılıyor...
Enterprise ortamında bir pazartesi sabahı:
- Güvenlik Ekibi: "Bizim 500+ kullanıcı
adminCount=1ile işaretlenmiş!" - Yönetici: "Nasıl olur? Sadece 50 kişi yöneticiymiş..."
- Denetçi: "Bu nedir? Bunu belgelendirmediğinizi görüyorum."
- CTO: "Bu risk nasıl bu kadar büyüyüp kimse fark etmedi?"
Gerçek Sorun
Active Directory (AD) ile ilgili en yaygın hatalardan biri, yönetim delegasyonunun güvensiz ve kaotik yapılması, bunun sonucunda:
- Shadow Admin Sorunu: Resmi olmayan yönetim yetkilerine sahip hesaplar ortaya çıkıyor
- adminCount Patolojisi: Sistem tarafından otomatik olarak kaldırılması gereken flag'ler cihaz üzerinde kalıyor
- AdminSDHolder Çelişkisi: Yöneticiler, koruma mekanizmasını anlayamadıkları için kırıyor
- Denetim İzleri: "Kim ne zaman neyi değiştirdi?" sorusuna cevap verilemiyor
Bu Yazı Kimler İçin?
- Active Directory Yöneticileri: Delegasyon stratejisi planlayan
- Güvenlik Mimarları: Least Privilege ilkesini uygulamak isteyenler
- Sistem Yöneticileri: Eski hataları düzeltmek isteyen
- Denetim Ekipleri: Uyum ve izleme raporu isteyenler
adminCount = 1 Nedir? Teknik Açıklama
Tanım: AdminCount Attribute'u
adminCount, Active Directory'de bir hesabın veya bilgisayarın Protected Groups (Korunan Gruplar) içinde bulunup bulunmadığını gösteren bir boolean flag'idir.
adminCount = 1 ➜ Bu nesne korumalı grup üyesi (veya olmuş) demektir
adminCount = 0 ➜ Bu nesne korumalı grup üyesi değil
Korunan Gruplar Nelerdir?
Active Directory, aşağıdaki grupları otomatik olarak korur:
| Grup | RID | Açıklama |
|---|---|---|
| Domain Admins | 512 | Etki alanı yöneticileri (çoğu zaman kötü amaçlı hedef) |
| Enterprise Admins | 519 | Orman yöneticileri (Tier 0 erişim) |
| Schema Admins | 518 | Şema değişikliği yetkisi (çok tehlikeli) |
| Account Operators | 548 | Kullanıcı/grup yönetimi (yerel gruplara erişebilir) |
| Backup Operators | 551 | Yedekleme ve geri yükleme yetkisi |
| Print Operators | 550 | Yazıcı yönetimi |
| Server Operators | 549 | Sunucu yönetimi (yerel) |
| Replicator | 552 | Replikasyon (nadiren kullanılır) |
SDProp (Security Descriptor Propagator) Mekanizması
Active Directory, SDProp adlı bir arka plan işlemi çalıştırır:
SDProp Döngüsü (Her 3600 sn)
1. Korunan grupları tarar
2. Üyeleri tespit eder
3. adminCount=1 atanır
4. AdminSDHolder ACL'ini kopyalar
5. Üyelerin Permission'ını günceller
adminCount'un Yaşam Döngüsü
SENARYO 1: Grup Üyesi Ekleme (Doğru Davranış)
─────────────────────────────────────────
User1 ➜ (Domain Admins'e eklenir) ➜ adminCount=1 otomatik atanır
User1 ➜ (Domain Admins'den çıkarılır) ➜ adminCount AYNEN KALIR
SENARYO 2: Grup Üyesi Çıkarma (SİZİN İŞİNİZ!)
─────────────────────────────────────────
User1'in adminCount=1 kaldırılması için ➜ El ile `Set-ADObject -Clear adminCount` çalıştırmanız gerekir!
SENARYO 3: Korunan Gruba Doğrudan Üye Ekleme (Hata!)
─────────────────────────────────────────
Grup1 ➜ (Domain Admins'in nesne üyesi olmuş) ➜ adminCount=1 + ACL koruması ➜ O grupta herkes korunuyor!
Praktik Örnek: Bir Kullanıcının adminCount'u Kontrol Etme
# Tüm adminCount=1 olan kullanıcıları listele
Get-ADUser -LDAPFilter "(adminCount=1)" -Properties adminCount, MemberOf |
Select-Object Name, adminCount, @{
L='Gruplar';
E={($_.MemberOf | ForEach-Object {$_ -replace '^CN=|,.*$'}) -join ', '}
}
# Çıktı Örneği:
# Name adminCount Gruplar
# ─────────────────────────────────────
# Admin1 1 Domain Admins, Enterprise Admins
# User2 1 (boş - ORFANlanmış!)
# ServiceAcc1 1 (boş - ORFANlanmış!)
Sorun: adminCount Zamanla Orfa Kalır
# SORULU ZAMAN ÇİZELGESİ
─────────────────────────────────────────
T=0 : User ➜ Domain Admins'e eklenir ➜ adminCount=1 atanır
T=1 gün : User ➜ Domain Admins'den çıkarılır ➜ adminCount AYNEN 1 kalır!
T=30 gün: Denetçi raporunda User hâlâ "admin" olarak görünüyor
T=60 gün: Hiç kimse bunun fark etmediğine güveniyor
T=∞ : Yeni denetçi raporunda "500+ gizli yönetici var!" yazıyor
AdminSDHolder Riski: Neden ACL'yi Değiştirmiyorsunuz?
AdminSDHolder Nedir?
AdminSDHolder, Active Directory'de CN=AdminSDHolder,CN=System konumunda bulunan orman düzeyinde bir container'dır. Bu nesnenin ACL'i (Access Control List), tüm korunan grup üyelerine otomatik olarak uygulanır.
Mimari Görselleştirme
AdminSDHolder Container
(CN=System,DC=contoso,DC=com)
ACL (Erişim Kontrol Listesi):
├─ SYSTEM: FullControl
├─ CREATOR OWNER: FullControl
├─ Domain Admins: FullControl
└─ Enterprise Admins: FullControl
⬇ (Her 3600 sn kopyalanır)
Domain Admins Group
(Üye: Admin1, Admin2, ...)
AdminSDHolder ACL'i Ne İçerir?
# AdminSDHolder'ın ACL'ini görüntüle
$AdminSD = Get-ADObject -Identity "CN=AdminSDHolder,CN=System,DC=contoso,DC=com" -Properties ntSecurityDescriptor
$AdminSD.ntSecurityDescriptor.Access | Format-Table IdentityReference, ActiveDirectoryRights, AccessControlType -AutoSize
# Çıktı Örneği:
# IdentityReference ActiveDirectoryRights AccessControlType
# ─────────────────────────────────────────────────────────────────────────────────────────
# NT AUTHORITY\SYSTEM FullControl Allow
# BUILTIN\Administrators FullControl Allow
# CONTOSO\Domain Admins FullControl Allow
# CONTOSO\Enterprise Admins FullControl Allow
ÇOK YAYGIN HATA: AdminSDHolder ACL'ini Değiştirmek
Hata Senaryosu
Bir yönetici şöyle düşünüyor:
"Domain Admins grubu bize çok fazla yetki veriyor. Sadece belirli nesneleri yönetebilmeleri için ACL'ini düzelteyim."
# ❌ YANLIŞ YAP! ❌
$AdminSDPath = "CN=AdminSDHolder,CN=System,DC=contoso,DC=com"
$AdminSDObj = Get-ADObject -Identity $AdminSDPath
$ACL = Get-Acl "AD:\$AdminSDPath"
# ... ACL'den permission'ları kaldırır ...
Set-Acl -Path "AD:\$AdminSDPath" -AclObject $ACL
Sonuçlar: Kontrolü Kaybetme
T=0 : ACL değiştirilir
T=5 min : SDProp çalışır, değişikliği geri yazmaya çalışır
T=10 min: Hatalı davranış ortaya çıkıyor:
├─ Domain Admins'lar birbirini yönetememaya başlar
├─ Policy uygulanmamaya başlar
├─ Yetkilendirme kontrolleri bozulur
└─ Denetim izleri tutarsız hale gelir
T=∞ : Etki alanı düzeyinde uyum problemi
Doğru Yaklaşım: ACL'yi Asla Değiştirmeyin
Kurallar:
- AdminSDHolder'ı sadece okuyun - İncelemek için
Get-Aclkullanabilirsiniz - Delegasyon istiyorsanız OrgUnit (OU) kullanın - Aşağıda göstereceğiz
- Kısıtlamak istiyorsanız özel gruplar oluşturun - Korunan grupları değiştirmeyin
- SDProp döngüsünü kesmeyin - Varsayılan 3600 saniye kalsın
Sağlıklı Delegasyon: AdminSDHolder Yerine OU Delegasyonu
# AdminSDHolder'ı OKUMAK (izin verilen)
Get-ADObject -Identity "CN=AdminSDHolder,CN=System,DC=contoso,DC=com" `
-Properties ntSecurityDescriptor |
Select-Object -ExpandProperty ntSecurityDescriptor |
Select-Object -ExpandProperty Access
# Eğer kısıtlama istiyorsanız, bu şekilde yapın:
# ✅ OU Delegasyonu ile "Tier 2 Yöneticiler" grubu oluştur
# ✅ Bu gruba sadece belirli OU'daki nesneleri değiştir yetkisi ver
# ✅ AdminSDHolder'ı AYNEN BIRAK
Tier Modeline Göre Delegasyon: Tier 0/1/2 Planlaması
Microsoft Tier Model Nedir?
Microsoft, AD ortamlarında güvenlik katmanlarını sınıflandırmıştır:
┌─────────────────────────────────────────────────────────────────┐
│ TIER MODEL │
├─────────────────────────────────────────────────────────────────┤
│ │
│ TIER 0 (En Kritik - Çok Az Kişi) │
│ ├─ Enterprise Admins │
│ ├─ Schema Admins │
│ ├─ Domain Admins (kısıtlı) │
│ └─ Kriti orman kurtarma hesapları │
│ │
│ ↕ (Tek yönlü güven - Tier 0 hiçbir şeye güvenmesin) │
│ │
│ TIER 1 (Etki Alanı Yönetimi) │
│ ├─ OU Yöneticileri │
│ ├─ Grup Politikası Yöneticileri │
│ └─ Sunucu Yöneticileri (sınırlı) │
│ │
│ ↕ (Güven yönetilmeli) │
│ │
│ TIER 2 (İş Birimi Yönetimi) │
│ ├─ Yerel Yöneticiler │
│ ├─ Uygulama Yöneticileri │
│ └─ Destek Personeli (sınırlı) │
│ │
│ ↕ (Geniş erişim, ancak yönetilmeli) │
│ │
│ TIER 3 (Son Kullanıcılar) │
│ ├─ Standart Kullanıcılar │
│ └─ Konuk Hesapları │
│ │
└─────────────────────────────────────────────────────────────────┘
Delegasyon Stratejisi: Her Tier İçin
TIER 0: Orman Yönetimi (Maximum Güvenlik)
Amaç: Şema, orman yapısı, kritik yapılandırma
Kişi Sayısı: 2-3 (hatta 2 de az değildir!)
Gruplar:
- Enterprise Admins
- Schema Admins
Delegasyon Modeli:
┌──────────────────────────────────────┐
│ TIER 0 Delegasyon Akışı │
├──────────────────────────────────────┤
│ 1. Değişiklik Talep Formu │
│ 2. Üst Yönetim Onayı │
│ 3. 2 Kişi Aynı Anda Hazır (4 Göz) │
│ 4. Değişiklik + Denetim Kaydı │
│ 5. Test Ortamında Öncesi Simülasyon │
│ 6. Raporlama (Zorunlu) │
└──────────────────────────────────────┘
PowerShell Kontrol:
# TIER 0 üyelerini listele
$Tier0Groups = @('Administrators', 'Domain Admins', 'Enterprise Admins', 'Schema Admins')
foreach ($Group in $Tier0Groups) {
Get-ADGroupMember -Identity $Group -Recursive |
Where-Object { $_.objectClass -eq 'user' } |
Select-Object Name, samAccountName, @{L='Grup'; E={$Group}}
}
# Aylık rapor: TIER 0 değişiklikleri
Get-ADUser -LDAPFilter "(adminCount=1)" -Properties WhenChanged, LastLogonDate |
Where-Object { $_.WhenChanged -gt (Get-Date).AddDays(-30) } |
Select-Object Name, WhenChanged, LastLogonDate
TIER 1: Etki Alanı Yönetimi (Orta Güvenlik)
Amaç: GPO, OU, Kullanıcı/Bilgisayar yönetimi
Kişi Sayısı: 5-10
Gruplar:
- Domain Admins (OU Delegasyonu ile sınırlandırılmış)
- GPO Editörleri
- OU Yöneticileri
Delegasyon Modeli:
# TIER 1: OU Delegasyonu Örneği
─────────────────────────────────────
OU=Tier1_Servers,DC=contoso,DC=com
├─ Server1
├─ Server2
└─ Server3
# "Tier1_ServerAdmins" grubu sadece bu OU'da işlem yapabilir
# Delegasyon adımları:
1. Grup oluştur
New-ADGroup -Name "Tier1_ServerAdmins" -GroupScope Global
2. OU'ya erişim ver (dışarıdan değil!)
# GUI: Delegation of Control Wizard
# veya
dsacls.exe "OU=Tier1_Servers,DC=contoso,DC=com" `
/G "CONTOSO\Tier1_ServerAdmins:CCCCDC"
3. PowerShell ile kontrol
Get-ADUser -LDAPFilter "(memberOf=CN=Tier1_ServerAdmins,CN=Users,DC=contoso,DC=com)" `
-Properties MemberOf | Select Name, MemberOf
TIER 2: İş Birimi Yönetimi (Esnek)
Amaç: Yerel uygulama, grup yönetimi, hizmet hesapları
Kişi Sayısı: 20+
Gruplar:
- Yerel Yönetici Grupları
- Uygulama Grup Yöneticileri
- Help Desk Operators
Delegasyon Modeli:
# TIER 2: Grup ve Hizmet Hesabı Yönetimi
─────────────────────────────────────
# "Tier2_AppAdmins" grubu
# ├─ SharePoint_Admins grubunu yönetebilir
# ├─ App_ServiceAccounts OU'sunda hesap oluşturabilir
# └─ Kendi gruplarını yönetebilir (recursively yönetemesin!)
# OU Delegasyonu: Tier 2 için daha geniş izinler
$OU = "OU=Tier2_Applications,DC=contoso,DC=com"
$Group = "Tier2_AppAdmins"
# Delegasyon GUI aracı
# Delegated Tasks: User Accounts Creation, Modification
# Reset Password
# Group Management
# PowerShell ile doğrula
dsacls.exe $OU /G "CONTOSO\$Group:CCCCDA"
Yaygın Hatalar: Tier Delegasyonunda
Hata 1: Account Operators Kullanmak
# ❌ YANLIŞ
Get-ADGroup -Identity "Account Operators" -Properties members |
Select-Object -ExpandProperty members
# Sorun: Account Operators eski, standartlaştırılmamış ve kötü amaçlı hedef
# ✅ DOĞRU: Özel OU delegasyonu grup oluştur
New-ADGroup -Name "Tier1_UserAdmins" -GroupScope DomainLocal
Hata 2: Tier'lar Arası Güven Eksikliği
# ❌ YANLIŞ
# TIER 2 admin'i doğrudan Domain Admins grubuna eklenir
Add-ADGroupMember -Identity "Domain Admins" -Members "CONTOSO\Tier2_Admin"
# ✅ DOĞRU
# TIER 2 admin'i, Tier 2 OU'sunda sınırlı yetkiye sahiptir
# TIER 1'de yardım isterse, bir ticket oluşturur ve TIER 1 admin tarafından yapılır
Hata 3: Delegasyonun Belgelenmemesi
# ✅ DOĞRU YÖNETİM
# Delegasyon logu tut
$Delegati
Date = Get-Date
Admin = $env:USERNAME
Reason = "Ticket #12345 - Yeni OU Yöneticisi"
Approved = "Manager (email)"
}
# JSON olarak kaydet
$DelegationLog | ConvertTo-Json | Out-File -Path "C:\Logs\delegations_$(Get-Date -Format yyyyMM).json" -Append
Best Practice Checklist: Uygulanabilir Adımlar
A. Envanter Oluşturma (Haftada 1 kez)
# Script: AD_AdminCount_Report.ps1
$ReportPath = "C:\Reports\AD_AdminCount_$(Get-Date -Format yyyyMMdd).csv"
$Results = @()
# Tüm adminCount=1 nesneleri bul
$AdminUsers = Get-ADUser -LDAPFilter "(adminCount=1)" `
-Properties adminCount, MemberOf, WhenChanged, LastLogonDate
foreach ($User in $AdminUsers) {
$Groups = ($User.MemberOf | ForEach-Object {
($_ -split ',')[0] -replace 'CN='
}) -join '; '
$Results += [PSCustomObject]@{
Name = $User.Name
SamAccountName = $User.samAccountName
adminCount = $User.adminCount
Grup_Uyeligikleri = $Groups
S
S
Aktif_Mi = if ($User.LastLogonDate -gt (Get-Date).AddDays(-30)) { "Evet" } else { "Hayir" }
}
}
$Results | Export-Csv -Path $ReportPath -Encoding UTF8 -NoTypeInformation
Write-Host "Rapor: $ReportPath"
Kontrol Listesi:
- [ ] Tüm adminCount=1 kullanıcılar listelenmiş
- [ ] Her kullanıcı için grup üyelikleri kontrol edilmiş
- [ ] Orfa kalan (boş grup) kullanıcılar tespit edilmiş
- [ ] Aylık rapor trend analizi yapılmış
B. adminCount Temizliği (Aylık)
# Script: Cleanup_adminCount.ps1
# ÖNEMLİ: Bu script'i çalıştırmadan ÖNCE
# 1. Backup al
# 2. Test ortamında dene
# 3. İş saati dışında çalıştır
function Remove-OrphanedAdminCount {
param(
[switch]$WhatIf
)
$AdminUsers = Get-ADUser -LDAPFilter "(adminCount=1)" `
-Properties adminCount, MemberOf
$ProtectedGroups = @(
'Domain Admins',
'Enterprise Admins',
'Schema Admins',
'Account Operators',
'Backup Operators',
'Print Operators',
'Server Operators',
'Replicator'
)
$Cleaned = 0
foreach ($User in $AdminUsers) {
# Kullanıcının korunan grup üyeliğini kontrol et
$InProtectedGroup = $false
foreach ($Group in $ProtectedGroups) {
try {
$GroupMembers = Get-ADGroupMember -Identity $Group -Recursive -ErrorAction Stop
if ($GroupMembers | Where-Object { $_.objectGUID -eq $User.objectGUID }) {
$InProtectedGroup = $true
break
}
} catch {
# Grup bulunamadı, devam et
}
}
# Eğer korunan grupta değilse, adminCount'u kaldır
if (-not $InProtectedGroup) {
Write-Host "Temizleniyor: $($User.Name) (adminCount kaldırılacak)"
if ($WhatIf) {
Write-Host " [PREVIEW] Set-ADObject -Identity $($User.DistinguishedName) -Clear adminCount"
} else {
Set-ADObject -Identity $User.DistinguishedName -Clear adminCount -Confirm:$false
$Cleaned++
}
}
}
Write-Host "Toplam temizlenen: $Cleaned"
}
# Kullanım:
# 1. Önce WhatIf ile göz at
Remove-OrphanedAdminCount -WhatIf
# 2. Sonra gerçekten çalıştır
Remove-OrphanedAdminCount
Kontrol Listesi:
- [ ] Backup alındı (AD snapshot/export)
- [ ] Test ortamında çalıştırıldı
- [ ] WhatIf parametresi ile önizleme yapıldı
- [ ] Log dosyası kaydedildi
- [ ] Denetim izleri kontrol edildi
C. AdminSDHolder Kontrol (Aylık Denetim)
# Script: Audit_AdminSDHolder.ps1
function Audit-AdminSDHolder {
$AdminSDPath = "CN=AdminSDHolder,CN=System,DC=$(($env:USERDNSDOMAIN -split '\.' | ForEach-Object { "DC=$_" }) -join ',')"
Write-Host "AdminSDHolder Denetimi: $AdminSDPath" -ForegroundColor Green
# 1. AdminSDHolder'ın ACL'ini oku
$AdminSDObj = Get-ADObject -Identity $AdminSDPath -Properties nTSecurityDescriptor
$ACL = $AdminSDObj.nTSecurityDescriptor
Write-Host "`n=== ACL İçeriği ===" -ForegroundColor Cyan
$ACL.Access | Format-Table @{
L='Kimlik'; E={$_.IdentityReference}
}, @{
L='Haklar'; E={$_.ActiveDirectoryRights}
}, @{
L='Tür'; E={$_.AccessControlType}
} -AutoSize
# 2. ACL'in varsayılan olup olmadığını kontrol et
$DefaultACEs = @(
'NT AUTHORITY\SYSTEM',
'BUILTIN\Administrators',
'OWNER RIGHTS'
)
$UnexpectedACEs = $ACL.Access | Where-Object {
-not ($_.IdentityReference.Value -match ($DefaultACEs -join '|'))
}
if ($UnexpectedACEs) {
Write-Host "`n UYARI: Beklenmeyen ACL'ler bulundu!" -ForegroundColor Red
$UnexpectedACEs | Format-Table IdentityReference, ActiveDirectoryRights
} else {
Write-Host "`n ACL normal görünüyor" -ForegroundColor Green
}
# 3. SDProp çalıştırıldığını kontrol et
$SDPropTime = (Get-ADDomainController | Get-ADReplicationPartnerMetadata -Target (Get-ADDomain).DNSRoot).ReplicationSchedule
Write-Host "`nSDProp Periyodu: Varsayılan 3600 saniye (1 saat)" -ForegroundColor Cyan
# 4. Korunan grup üyelerinin ACL'ini kontrol et
Write-Host "`n=== Korunan Grup Üyelerinin ACL Kontrolü ===" -ForegroundColor Cyan
$DomainAdmins = Get-ADGroup -Identity "Domain Admins"
$DomainAdminsACL = Get-ADObject -Identity $DomainAdmins.DistinguishedName -Properties nTSecurityDescriptor
$ACLsSame = $null -eq (Compare-Object -ReferenceObject $AdminSDObj.nTSecurityDescriptor.Access `
-DifferenceObject $DomainAdminsACL.nTSecurityDescriptor.Access)
if ($ACLsSame) {
Write-Host "✅ Domain Admins ACL'i, AdminSDHolder ile eşleşiyor (normal)" -ForegroundColor Green
} else {
Write-Host "⚠️ UYARI: Domain Admins ACL'i farklı! SDProp'u yeniden çalıştırmayı deneyin." -ForegroundColor Red
}
}
# Kullanım
Audit-AdminSDHolder
Kontrol Listesi:
- [ ] AdminSDHolder ACL'i varsayılan durumda
- [ ] Korunan gruplar ACL'i AdminSDHolder ile eşleşiyor
- [ ] SDProp periyodu 3600 saniye (varsayılan)
- [ ] Denetim raporu oluşturuldu
D. OU Delegasyonu Oluşturma (Kurulum Aşaması)
# Script: Setup_OU_Delegation.ps1
function New-OUWithDelegation {
param(
[Parameter(Mandatory)][string]$OUName,
[Parameter(Mandatory)][string]$ParentOU,
[Parameter(Mandatory)][string]$DelegateGroupName,
[string[]]$Permissi Accounts', 'Reset Password')
)
# 1. OU oluştur
$OUPath = "OU=$OUName,$ParentOU"
try {
New-ADOrganizationalUnit -Name $OUName -Path $ParentOU -ProtectedFromAccidentalDeletion $true
Write-Host "✅ OU oluşturuldu: $OUPath"
} catch {
Write-Host " OU oluşturma hatası: $_"
return
}
# 2. Delegasyon Grubu oluştur
try {
New-ADGroup -Name $DelegateGroupName -GroupScope DomainLocal -GroupCategory Security -Path $ParentOU
Write-Host " Delegasyon Grubu oluşturuldu: $DelegateGroupName"
} catch {
Write-Host " Grup oluşturma hatası: $_"
return
}
# 3. Delegasyon Yap (GUI ile veya dsacls ile)
Write-Host "`n Delegasyon Adımları:"
Write-Host " 1. Active Directory Users and Computers'ı aç"
Write-Host " 2. $OUPath - Sağ Tıkla - 'Delegate Control'"
Write-Host " 3. $DelegateGroupName'i seç"
Write-Host " 4. Aşağıdaki izinleri seç:"
foreach ($Perm in $Permissions) {
Write-Host " - $Perm"
}
# Alternatif: dsacls ile (ileri kullanıcılar için)
# dsacls.exe "$OUPath" /G "CONTOSO\$DelegateGroupName:CCCCDA"
}
# Örnek Kullanım:
# Tier 1 Sunucu OU'su
New-OUWithDelegation `
-OUName "Servers" `
-ParentOU "OU=Tier1,DC=contoso,DC=com" `
-DelegateGroupName "Tier1_ServerAdmins" `
-Permissions @('User Accounts', 'Reset Password', 'Manage Group Membership')
# Tier 2 Aplikasyon OU'su
New-OUWithDelegation `
-OUName "Applications" `
-ParentOU "OU=Tier2,DC=contoso,DC=com" `
-DelegateGroupName "Tier2_AppAdmins" `
-Permissions @('User Accounts', 'Reset Password')
Kontrol Listesi:
- [ ] OU yapısı Tier modeline uygun planlandı
- [ ] Delegasyon Grupları oluşturuldu
- [ ] İzinler minimuma indirildi (Least Privilege)
- [ ] Belgeler oluşturuldu (Kim, Ne, Ne Zaman)
E. Aylık Raporlama (Zorunlu!)
# Script: Generate_Monthly_Report.ps1
function Get-ADMonthlyReport {
param(
[int]$Days = 30
)
$StartDate = (Get-Date).AddDays(-$Days)
$ReportPath = "C:\Reports\AD_Monthly_Report_$(Get-Date -Format yyyyMM).html"
# 1. adminCount Raporu
$AdminCountUsers = Get-ADUser -LDAPFilter "(adminCount=1)" `
-Properties adminCount, MemberOf, WhenChanged, LastLogonDate
# 2. Yeni Eklenmiş Admins
$NewAdmins = $AdminCountUsers | Where-Object { $_.WhenChanged -gt $StartDate }
# 3. Orfa Kalan Admins
$OrphanedAdmins = $AdminCountUsers | Where-Object {
($_.MemberOf -join '').Length -eq 0
}
# 4. Etkinlik Olmayan Admins (30+ gün)
$InactiveAdmins = $AdminCountUsers | Where-Object {
$_.LastLogonDate -lt $StartDate
}
# HTML Rapor
$HTML = @"
Active Directory Aylık Rapor
Raporlama Tarihi: $(Get-Date -Format 'dd.MM.yyyy')
Dönem: Son $Days Gün
Özet İstatistikler
- Toplam Admin: $($AdminCountUsers.Count)
- Yeni Eklenenler: $($NewAdmins.Count)
- Orfa Kalanlar: $($OrphanedAdmins.Count)
- Etkinlik Olmayan (30+ gün): $($InactiveAdmins.Count)
Orfa Kalan Adminler (ACTION REQUIRED!)
$(
$OrphanedAdmins | ForEach-Object {
""
}
)
| İsim | Hesap | Son Değişiklik |
|---|---|---|
| $($_.Name) | $($_.samAccountName) | $($_.WhenChanged) |
Yeni Eklenenler
$(
$NewAdmins | ForEach-Object {
$Groups = ($_.MemberOf | ForEach-Object { ($_ -split ',')[0] -replace 'CN=' }) -join '; '
""
}
)
| İsim | Grup | Eklenme Tarihi |
|---|---|---|
| $($_.Name) | $Groups | $($_.WhenChanged) |
Etkinlik Olmayan Adminler (30+ gün)
$(
$InactiveAdmins | ForEach-Object {
$DaysInactive = ((Get-Date) - $_.LastLogonDate).Days
""
}
)
| İsim | Son Giriş | Gün Sayısı |
|---|---|---|
| $($_.Name) | $($_.LastLogonDate) | $DaysInactive |
Rapor otomatik olarak oluşturulmuştur. Kontrol ve onay gereklidir.
"@
$HTML | Out-File -Path $ReportPath -Encoding UTF8
Write-Host "Rapor oluşturuldu: $ReportPath"
# Email ile gönder (isteğe bağlı)
# Send-MailMessage -From 'ad-reports@contoso.com' -To 'admins@contoso.com' ...
}
# Kullanım
Get-ADMonthlyReport -Days 30
Kontrol Listesi:
- [ ] Rapor otomatik olarak oluşturuluyor (Task Scheduler)
- [ ] İşe yaramayan adminler vurgulı şekilde gösteriliyor
- [ ] Rapor yöneticilere gönderiliyor
- [ ] Denetim izleri tutanağına kaydediliyor
Shadow Admin Avı: BloodHound + PingCastle
Shadow Admin Nedir?
Shadow Admin, resmi olmayan yönetim yetkilerine sahip hesaptır:
┌────────────────────────────────────────────┐
│ SHADOW ADMIN ÖRNEKLERI │
├────────────────────────────────────────────┤
│ ❌ User1 - Domain Admins'de gözükmüyor │
│ ✓ Ama OrgUnit'te "Yazma" yetkisine │
│ sahip (Delegasyon aracılığıyla) │
│ │
│ ❌ ServiceAccount - Resmi admin değil │
│ ✓ Ama GenericAll hakkı nedeniyle │
│ Domain Admins'e ekleyebiliyor │
│ │
│ ❌ Printer Admin - Sadece yazıcı yönetmeli │
│ ✓ Ama Schema Admins grubunun ACL'ini │
│ değiştirebildi (hata mı?) │
└────────────────────────────────────────────┘
BloodHound İle Tarama
BloodHound, AD'de yetki yollarını görselleştirir. Kurulum:
# 1. BloodHound Community Edition'ı indir
# https://github.com/BloodHoundAD/BloodHound/releases
# 2. Neo4j Graph Database kur
docker run --name neo4j -p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/password \
neo4j:5.10
# 3. SharpHound Collector çalıştır (AD sunucusunda)
# SharpHound.exe -c All -d contoso.com -OutputDirectory C:\Temp
# 4. İndir ve BloodHound'a yükle
BloodHound ile Shadow Admin Bulma:
Analiz Adımları:
1. Collector çalıştır
SharpHound.exe -c All --outputdirectory C:\temp
2. Dosyaları BloodHound'a yükle
- JSON dosyalarını seç
- Upload
3. Queryleri çalıştır:
├─ "Find Dangerous Rights"
├─ "Find AD Abuse Paths to High Value Targets"
├─ "Find Dangerous ACL Permissions"
├─ "Domain Dominance" (ileri)
└─ "Find all Nodes - One Way Trust Relationships"
4. Sonuç: Grafikte kırmızı yollar = Riski yol (kimler admin olabilir?)
PingCastle İle Rapor
PingCastle, AD sağlığını denetler:
# 1. PingCastle.exe'yi indir
# https://www.pingcastle.com/
# 2. Admin olarak çalıştır
.\PingCastle.exe -healthcheck -domain contoso.com
# 3. HTML rapor oluşur: PingCastleReport_contoso.html
# Kritik Kontroller:
# ─────────────────
# ├─ "Detect unregistered users" (Orfa admin yok mu?)
# ├─ "Dangerous ACLs" (Tehlikeli izinler)
# ├─ "Delegated Admins" (Yetki verilen adminler)
# ├─ "Service Accounts Not Delegated" (Hizmet hesapları kontrol)
# └─ "Protected Groups Have Weak Accounts" (Korunan gruplar güvensiz mi?)
Otomatik Shadow Admin Taraması
# Script: Find_Shadow_Admins.ps1
function Find-ShadowAdmins {
Write-Host "Shadow Admin Taraması Başladı..." -ForegroundColor Cyan
# 1. Korunan grup üyelerini getir
$ProtectedGroups = @('Domain Admins', 'Enterprise Admins', 'Schema Admins', 'Account Operators')
$AdminUsers = @()
foreach ($Group in $ProtectedGroups) {
Get-ADGroupMember -Identity $Group -Recursive |
Where-Object { $_.objectClass -eq 'user' } |
ForEach-Object { $AdminUsers += $_ }
}
Write-Host " Resmi admin sayısı: $($AdminUsers.Count)"
# 2. Tehlikeli ACL'leri bul
Write-Host "`n Tehlikeli ACL'ler taranıyor..."
$SuspiciousACEs = @()
# OU'ları tara
$OUs = Get-ADOrganizationalUnit -Filter * | Select-Object -First 50
foreach ($OU in $OUs) {
try {
$ACL = Get-Acl "AD:\$($OU.DistinguishedName)"
# GenericAll, GenericWrite, WriteDacl gibi tehlikeli izinleri bul
$DangerousACEs = $ACL.Access | Where-Object {
($_.ActiveDirectoryRights -like '*GenericAll*') -or
($_.ActiveDirectoryRights -like '*GenericWrite*') -or
($_.ActiveDirectoryRights -like '*WriteDacl*') -or
($_.ActiveDirectoryRights -like '*WriteProperty*')
}
foreach ($ACE in $DangerousACEs) {
# Eğer resmi admin değilse, shadow admin olabilir
if ($AdminUsers | Where-Object { $_.SID -eq $ACE.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) }) {
# Resmi admin, skip
} else {
$SuspiciousACEs += [PSCustomObject]@{
OU = $OU.Name
Identity = $ACE.IdentityReference
Rights = $ACE.ActiveDirectoryRights
AccessType = $ACE.AccessControlType
ObjectType = $ACE.ObjectType
}
}
}
} catch {
# OU erişim hatası, devam et
}
}
if ($SuspiciousACEs.Count -gt 0) {
Write-Host "`n UYARI: $($SuspiciousACEs.Count) şüpheli ACL bulundu!" -ForegroundColor Red
$SuspiciousACEs | Format-Table OU, Identity, Rights -AutoSize
} else {
Write-Host "`n Şüpheli ACL bulunamadı" -ForegroundColor Green
}
# 3. Delegasyon Grubuna Sahip Kullanıcıları Bul
Write-Host "`n Özel delegasyon grupları taranıyor..."
$Delegati -Filter { Name -like '*Admin*' -or Name -like '*Delegate*' } -Properties Members |
Where-Object { $_.DistinguishedName -like '*OU=*' } # Sadece OU'daki gruplar
foreach ($Group in $DelegationGroups) {
$Members = Get-ADGroupMember -Identity $Group -Recursive
Write-Host " └─ $($Group.Name): $($Members.Count) üye"
}
}
# Kullanım
Find-ShadowAdmins
Kaynaklar & İleri Okuma
Microsoft Resmi Kaynaklar
| Kaynak | URL | İçerik |
|---|---|---|
| Tier Model | Microsoft Docs | Tier 0/1/2 mimarisi |
| AdminSDHolder | Microsoft Docs | AdminSDHolder detaylı |
| Protected Groups | Microsoft Docs | Korunan gruplar listesi |
| Delegation | Microsoft Docs | OU delegasyonu rehberi |
Açık Kaynak Araçlar
| Araç | Kullanım | Download |
|---|---|---|
| BloodHound | Shadow Admin avı, ACL analizi | https://github.com/BloodHoundAD/BloodHound |
| PingCastle | AD sağlık raporu, denetim | https://www.pingcastle.com/ |
| ADExplorer | AD tarama ve ACL denetimi | https://docs.microsoft.com/en-us/sysinternals/ |
| Get-ADGroupChanges | Grup değişiklikleri izleme | GitHub (çeşitli) |
Güvenlik Blogları
- https://specterops.io/ - Yetki yönetimi uzmanları
- https://www.harmj0y.net/blog/ - Active Directory güvenliği (ileri)
- https://docs.microsoft.com/en-us/windows-server/identity/ - Resmi Microsoft
Kitaplar
- "Active Directory Cookbook" - Laura E. Hunter (klasik)
- "The Hacker Playbook 3" - Peter Kim (AD saldırıları)
- "Securing Active Directory for the Real World" - Erdal Ozkaya
Son Kontrol Listesi: Tüm Adımlar
┌──────────────────────────────────────────────────────────────┐
│ ACTIVE DIRECTORY GÜVENLİ DELEGASYON CHECKLIST │
├──────────────────────────────────────────────────────────────┤
✅ HAFTALIK GÖREVLER
□ adminCount raporu oluştur ve gözden geçir
□ Orfa admin olup olmadığını kontrol et
□ Yeni admin eklentisini denetim günlüğüne kaydet
□ Shadow admin avı çalıştır (BloodHound)
✅ AYLIK GÖREVLER
□ HTML raporu oluştur ve yöneticilere gönder
□ adminCount temizliğini çalıştır (orfa kalanları kaldır)
□ AdminSDHolder ACL'ini denetle
□ PingCastle raporu oluştur
□ Delegasyon belgelerini güncelle
✅ ÇEYREK YIL GÖREVLERİ
□ Tier model uyumluluğunu gözden geçir
□ OU delegasyonunun hâlâ uygun olduğunu kontrol et
□ Account Operators kullanımını sıfırla
□ Break Glass hesaplarını test et (güvenli ortamda)
✅ YILLIK GÖREVLER
□ Tüm admin hesaplarını denetim yapan dış ekip tarafından doğrula
□ Security Assessment yapmaz
□ Tier Model'i güncel hale getir
□ Disaster Recovery planını test et
□ Yönetici eğitimi düzenle
✅ KRİTİK KURALLARI KONTROL ET
□ AdminSDHolder ACL'i BİR KEZ DAHA DEĞIŞMEDI
□ Account Operators grubu KULLANILMIYOR
□ Delegasyon SADECE OU seviyesinde
□ TIER 0 hesapları 2-3 adet ve MFA'lı
□ Break Glass hesapları var ve güvende (vault)
□ Aylık raporlama ZORUNLU hale getirildi
□ BloodHound / PingCastle raporları düzenli alınıyor
└──────────────────────────────────────────────────────────────┘
Başlamak İçin İlk 24 Saat
Saat 0-2: Envanter
# Step 1
Get-ADUser -LDAPFilter "(adminCount=1)" -Properties MemberOf, WhenChanged |
Export-Csv -Path "C:\Backup\admincount_baseline.csv"
Saat 2-4: AdminSDHolder Denetimi
# Step 2
Audit-AdminSDHolder # (Yukarıdaki script)
Saat 4-8: Temizlik Planlaması
# Step 3
Remove-OrphanedAdminCount -WhatIf # Sadece preview!
Saat 8-24: Dokumentasyon
- Mevcut durumu belgele
- Yöneticileri bilgilendir
- Değişim yönetimi politikası oluştur
Active Directory'de admin hakkı yönetimi basit görünse de, yaşadığı zaman çok karmaşık hale gelebilir. Bu rehberin temel ilkeleri:
- adminCount'u Anlayın - Otomatik ama kalıcı değildir
- AdminSDHolder'ı Sakın - Asla değiştirmeyin!
- OU Delegasyonu Yapın - Korunan grupları değil, OU'ları delegeyin
- Tier Model İzleyin - Tier 0, 1, 2 ayrımını net yapın
- Aylık Rapor Tutun - Denetim için zorunlu
- Otomatize Edin - Script'ler zamanı kurtarır
- Tool Kullanın - BloodHound ve PingCastle hayat kurtarır
Başarı, günlük disiplin ve şeffaflık ile ölçülür. Şu anda 500+ gizli admin varsa, korkma. Planı uygula, rapor yap, denetleyeni tatmin et. Kolay gelsin...