Active Directory'de adminCount=1, AdminSDHolder ve Güvenli Delegasyon

Active Directory'de adminCount=1, AdminSDHolder ve Güvenli Delegasyon

Sahne Açılıyor...

Enterprise ortamında bir pazartesi sabahı:

  • Güvenlik Ekibi: "Bizim 500+ kullanıcı adminCount=1 ile 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:

  1. Shadow Admin Sorunu: Resmi olmayan yönetim yetkilerine sahip hesaplar ortaya çıkıyor
  2. adminCount Patolojisi: Sistem tarafından otomatik olarak kaldırılması gereken flag'ler cihaz üzerinde kalıyor
  3. AdminSDHolder Çelişkisi: Yöneticiler, koruma mekanizmasını anlayamadıkları için kırıyor
  4. 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:

Caption
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:

  1. AdminSDHolder'ı sadece okuyun - İncelemek için Get-Acl kullanabilirsiniz
  2. Delegasyon istiyorsanız OrgUnit (OU) kullanın - Aşağıda göstereceğiz
  3. Kısıtlamak istiyorsanız özel gruplar oluşturun - Korunan grupları değiştirmeyin
  4. 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
$DelegationLog = @{
    Date = Get-Date
    Admin = $env:USERNAME
    Action = "Tier1_UserAdmins grubuna User5 eklendi"
    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
        Son_Degistirilme = $User.WhenChanged
        Son_Giris = $User.LastLogonDate
        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[]]$Permissions = @('User 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..."
    
    $DelegationGroups = Get-ADGroup -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:

  1. adminCount'u Anlayın - Otomatik ama kalıcı değildir
  2. AdminSDHolder'ı Sakın - Asla değiştirmeyin!
  3. OU Delegasyonu Yapın - Korunan grupları değil, OU'ları delegeyin
  4. Tier Model İzleyin - Tier 0, 1, 2 ayrımını net yapın
  5. Aylık Rapor Tutun - Denetim için zorunlu
  6. Otomatize Edin - Script'ler zamanı kurtarır
  7. 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...


 

Önceki Yazı  CVE-2025-59287 (WSUS — Windows Server Update Services) zafiyeti
CVE-2025-59287 (WSUS — Windows Server Update Services) zafiyeti

Ekim 2025'te ortaya çıkan CVE-2025-59287, Microsoft’un Windows Server Update...

Sonraki Yazı
Ubuntu Statik IP ile Route

Bir Ubuntu sunucusunda birden fazla ağ arayüzü (örneğin biri internete, di�...