Merhaba
Serinin önceki bölümünde, tek bir sistemin ele geçirilmesinin nasıl domain çapında bir felakete dönüşebileceğini gördük. Bu bölümde ise, teknik olarak çok daha eski ama hala birçok kurumsal ortamda karşımıza çıkan, SYSVOL üzerinde unutulmuş bir yapılandırma kalıntısını istismar eden bir tekniği ele alıyoruz: Group Policy Preferences (GPP) içinde saklanan parolaların ele geçirilmesi.
Password in Group Policy Preferences (GPP) Compromise
Group Policy Preferences, yöneticilerin yerel hesap parolaları, zamanlanmış görevler, eşlenmiş sürücüler, yazıcılar ve servisler gibi ayarları Group Policy Object’ler (GPO) aracılığıyla domain’deki bilgisayarlara dağıtmasına imkan tanıyan bir özelliktir. Geçmişte, GPP bu ayarlar için bir parola alanı da sunuyordu (özellikle yerel yönetici hesabının parolasını merkezi olarak değiştirmek için yaygın kullanılıyordu) ve bu parola, ilgili GPO’nun SYSVOL paylaşımındaki XML dosyasında (`Groups.xml`, `ScheduledTasks.xml`, `Services.xml`, `DataSources.xml`, `Printers.xml`, `Drives.xml`) `cpassword` özniteliği olarak AES-256 ile şifrelenmiş şekilde saklanıyordu. Sorun şuydu: Microsoft, bu şifrelemede kullanılan statik AES anahtarını kendi dokümantasyonunda (MSDN) yıllar önce herkese açık olarak yayınlamıştı. Bu, `cpassword` değerine erişebilen HERHANGİ bir kimlik doğrulanmış domain kullanıcısının (SYSVOL, varsayılan olarak tüm Authenticated Users için okunabilir olduğundan) bu değeri saniyeler içinde düz metne çevirebilmesi anlamına geliyordu. Microsoft bu zafiyeti MS14-025 güvenlik güncellemesiyle (2014) kapattı – ancak bu güncelleme yalnızca GPP arayüzünün yeni parola oluşturmasını engelledi; daha önce oluşturulmuş ve SYSVOL’de kalmış XML dosyalarını otomatik olarak temizlemedi. Bu yüzden, güncellemeyi yıllar önce uygulamış kurumlarda bile, kimse eski GPO’ları manuel olarak temizlemediyse, SYSVOL’de hala `cpassword` içeren dosyalar bulunabiliyor. Bir saldırgan, domain’e herhangi bir düşük yetkili kullanıcı hesabıyla erişim sağladığında, SYSVOL paylaşımını tarayarak (`\\\SYSVOL\\Policies\`) bu dosyaları bulabilir, `cpassword` değerini herkese açık AES anahtarıyla çözebilir ve elde ettiği parolayı (genellikle bir yerel yönetici hesabına ait) domain’deki diğer sistemlerde deneyerek yanal hareket (lateral movement) gerçekleştirebilir.
Password in GPP Compromise’i Mitigasyon Etmek
Password in GPP compromise’i mitigasyon etmek için aşağıdaki güvenlik kontrolleri uygulanmalıdır:
- MS14-025 güvenlik güncellemesinin tüm domain controller’lara ve yönetim istasyonlarına uygulandığından emin olun. Bu güncelleme, GPP arayüzünün yeni parola tabanlı ayarlar oluşturmasını engeller.
- SYSVOL’ü `cpassword` özniteliği içeren eski GPO dosyaları için tarayın ve bunları kaldırın. Bu, PowerShell tabanlı script’lerle (`Get-ChildItem -Recurse -Include *.xml` ile SYSVOL üzerinde `cpassword` string’ini arayarak) periyodik olarak yapılmalıdır.
- GPP ile yerel yönetici parolası dağıtma pratiğini tamamen bırakın. Bunun yerine Microsoft’un LAPS (Local Administrator Password Solution) çözümü kullanılmalıdır; LAPS her makinenin yerel yönetici parolasını benzersiz, otomatik rotasyona tabi ve Active Directory’de erişim kontrolüyle korunan bir şekilde saklar.
- SYSVOL’e erişimi ve GPO düzenleme yetkilerini en az ayrıcalık ilkesine göre gözden geçirin. Yalnızca gerçekten GPO yönetimi yapması gereken hesapların bu yetkilere sahip olduğundan emin olun.
Password in GPP Compromise’i Tespit Etmek
Bu teknik, klasik anlamda tek bir “imza” event üretmez; çünkü SYSVOL’deki bir dosyayı okumak, normal bir domain kullanıcısının günlük olarak yaptığı sıradan bir işlemden ayırt edilmesi zor bir eylemdir. Tespit, daha çok bu tekniğin SONUCUNA (çalınan parolanın kullanılmasına) odaklanmalıdır. Aşağıdaki Event ID’ler merkezi olarak loglanmalı ve zamanında analiz edilmelidir.
Password in GPP Compromise’i Tespit Eden Olaylar
| Event ID | Kaynak | Açıklama |
|---|---|---|
| 5145 | Domain Controller’lar (SYSVOL paylaşımı) | Bir ağ paylaşımındaki bir nesneye erişim talebi olduğunda üretilir (Detailed File Share auditing etkinse). SYSVOL üzerinde `Policies` klasörüne, özellikle normalde GPO yönetimiyle ilgisi olmayan hesaplar tarafından yapılan erişimler incelenmelidir. |
| 4624 | Tüm domain üyesi sistemler | Bir hesap başarıyla oturum açtığında üretilir. Aynı yerel hesabın (örneğin `Administrator`) kısa bir süre içinde çok sayıda farklı sistemde, aynı parolayla oturum açması, GPP’den çalınmış bir parolanın domain genelinde yanal hareket için kullanıldığına işaret edebilir. |
| 4648 | Tüm domain üyesi sistemler | Açık kimlik bilgileriyle (explicit credentials) bir oturum açma girişimi olduğunda üretilir. Bir saldırganın çalınan yerel yönetici parolasını `runas`, PsExec veya benzeri bir araçla birden fazla sistemde denemesi bu event ile yakalanabilir. |
Lab Uygulaması: Windows Server 2025 Üzerinde Password in GPP Compromise
Bu tekniği kendi Windows Server 2025 (W25DC.bakicubuk.local) ve Windows 11 (W11CLIENT.bakicubuk.local) lab ortamımda canlı olarak denedim ve bu deneme, teoriden çok daha fazlasını ortaya çıkardı: Windows Server 2025’in bu 12 yıllık zafiyete karşı beklenenden çok daha katmanlı bir savunma hattına sahip olduğunu gösterdi.
Birinci bulgu: GPP parola alanı GUI’den kalıcı olarak devre dışı. İlk denemem, Group Policy Management Console üzerinden klasik yoldan bir GPP parolası oluşturmaktı: Demo-GPP-LegacyPassword adında yeni bir GPO oluşturup, Computer Configuration > Preferences > Control Panel Settings > Local Users and Groups altında yeni bir yerel kullanıcı tanımlamayı denedim. Hem mevcut Administrator hesabını Update action’ıyla güncellemeyi hem de gppdemo adında yeni bir hesabı Create action’ıyla oluşturmayı denedim; her iki senaryoda da Password ve Confirm Password alanları arayüzde görünüyor ama tamamen tıklanamaz/düzenlenemez durumda. Bu, MS14-025’in 2014’te yalnızca GUI’yi kısıtlayan yamasının, Windows Server 2025’te artık action veya hesap türünden bağımsız, koşulsuz bir kısıtlamaya dönüştüğünü gösteriyor – Microsoft bu özelliği fiilen ürün genelinde kapatmış.
Bu durumda, gerçek dünyada hala karşılaşılabilecek senaryoyu simüle etmek için Groups.xml dosyasını manuel olarak oluşturmam gerekti; bu, MS14-025 öncesinden kalma ve hiç temizlenmemiş bir GPO kalıntısını temsil ediyor. Microsoft’un herkese açık statik AES-256 anahtarını kullanarak bir şifreleme fonksiyonu yazdım:
function Encrypt-GPPPassword {
param([string]$Password)
$key = [byte[]](0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0xc8,0x5e,0x2b,0xd2,0x1b,0xd6,0x67,0x37)
$aes = [System.Security.Cryptography.Aes]::Create()
$aes.Key = $key
$aes.IV = New-Object byte[] 16
$aes.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aes.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$encryptor = $aes.CreateEncryptor()
$bytes = [System.Text.Encoding]::Unicode.GetBytes($Password)
$encrypted = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length)
$b64 = [Convert]::ToBase64String($encrypted)
return $b64.TrimEnd('=').Replace('+','-').Replace('/','_')
}
Bu fonksiyonla ürettiğim cpassword değerini, GPO’nun kendi SYSVOL yolundaki (C:\Windows\SYSVOL\domain\Policies\{2168eb11-4953-4e0d-bb22-f2a1472ad939}\Machine\Preferences\Groups\Groups.xml) standart GPP XML şablonuna yerleştirerek dosyayı elle yazdım:
Groups.xml dosyasının manuel olarak oluşturulması ve içeriğinde görünen cpassword değeri.
İkinci bulgu: SYSVOL’ün kendi kendini temizleme mekanizması. Dosyayı ilk oluşturduğumda okuma testi başarılı oldu, ancak cpassword değerini güncellemek için daha sonra klasöre geri döndüğümde, Machine\Preferences\Groups klasörünün tamamen ortadan kalktığını fark ettim – Test-Path False döndürüyor, Get-ChildItem -Recurse boş sonuç veriyordu. Bunun nedeni, SYSVOL’ün DFSR tabanlı tutarlılık/health-check mekanizmasının, ilgili GPO’nun gpt.ini dosyasında kayıtlı olmayan, yani “sahipsiz” (orphaned) olarak değerlendirilen bu manuel içeriği otomatik olarak temizlemesiydi. Bu, Windows Server 2025’in beklenmedik ama son derece isabetli bir sertleştirme (hardening) davranışı: platform, GPO yapılandırmasıyla eşleşmeyen SYSVOL içeriğini aktif olarak tespit edip kaldırıyor. Klasör oluşturma, XML yazma ve okuma adımlarını kesintisiz tek bir script bloğunda art arda çalıştırarak dosyanın temizlenmeden önce kanıt için okunabilmesini sağladım.
Üçüncü adım: Yetkisiz kullanıcı ile SYSVOL’den okuma ve şifre çözme. Dosya SYSVOL’de kalıcı olduğu sürece, sıradan bir domain kullanıcısı (özel bir yetkiye ihtiyaç duymadan, çünkü SYSVOL varsayılan olarak tüm Authenticated Users için okunabilir) bu dosyayı UNC yolu üzerinden (\\W25DC.bakicubuk.local\SYSVOL\bakicubuk.local\Policies\{2168eb11-4953-4e0d-bb22-f2a1472ad939}\Machine\Preferences\Groups\Groups.xml) doğrudan okuyabildi. cpassword değerini, Encrypt fonksiyonunun tam tersini yapan bir Decrypt fonksiyonuyla çözdüm:
function Decrypt-GPPPassword {
param([string]$Cpassword)
$key = [byte[]](0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0xc8,0x5e,0x2b,0xd2,0x1b,0xd6,0x67,0x37)
$b64 = $Cpassword.Replace('-','+').Replace('_','/')
switch ($b64.Length % 4) { 2 {$b64+="=="} 3 {$b64+="="} }
$encrypted = [Convert]::FromBase64String($b64)
$aes = [System.Security.Cryptography.Aes]::Create()
$aes.Key = $key
$aes.IV = New-Object byte[] 16
$aes.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aes.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$decryptor = $aes.CreateDecryptor()
$decrypted = $decryptor.TransformFinalBlock($encrypted, 0, $encrypted.Length)
return [System.Text.Encoding]::Unicode.GetString($decrypted)
}
cpassword değerinin herkese açık AES anahtarıyla çözülmesi sonucu elde edilen düz metin parola.
Fonksiyon, hiçbir özel yetki gerektirmeden cpassword değerini saniyeler içinde düz metne çevirdi. Bu, GPP’nin cpassword mekanizmasının aslında bir şifreleme değil, herkesin anahtarına sahip olduğu bir “gizleme” (obfuscation) olduğunu somut olarak gösteriyor.
Dördüncü adım: Elde edilen parolayla gerçek bir hesap oluşturmak. GPP’nin gerçek hayatta dağıtacağı yerel hesabı temsil etmek için W11CLIENT üzerinde gppdemo adında bir yerel yönetici hesabı oluşturmaya çalıştım. İlk denemede kullandığım parola (GppDemo2026!) InvalidPasswordException hatasıyla reddedildi – muhtemelen yerel parola politikasının karmaşıklık/benzerlik kontrolüyle çakıştı. Farklı bir parolayla (K9!mPx#2026Qz) hesap başarıyla oluşturuldu ve Groups.xml içindeki cpassword değerini bu yeni parolayla eşleşecek şekilde yeniden ürettim.
Beşinci bulgu: UAC’nin uzaktan erişim kısıtlaması. Elde ettiğim parolayla net use \\W11CLIENT\C$ /user:gppdemo K9!mPx#2026Qz komutunu çalıştırdığımda System error 5 - Access is denied hatası aldım – doğru kullanıcı adı ve parolaya rağmen. Bunun nedeni, UAC’nin varsayılan “uzaktan kısıtlamalar” (remote restrictions) davranışı: yerleşik (RID 500) olmayan yerel yönetici hesapları, ağ üzerinden kimlik doğrulamasında filtrelenmiş, yönetici olmayan bir token alır ve bu da admin paylaşımlarına (C$ gibi) erişimi engeller. Bunu, hedef makinede (W11CLIENT) aşağıdaki registry değişikliğiyle çözdüm:
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "LocalAccountTokenFilterPolicy" -Value 1 -Type DWord -Force
GPP’den elde edilen parolayla net use üzerinden W11CLIENT’e başarılı ağ kimlik doğrulaması.
Son kanıt: Event 4624. W11CLIENT üzerindeki Windows Event Viewer’da, bu oturum açma işlemine karşılık gelen Event ID 4624 kaydını inceledim. Kayıt, TargetUserName: gppdemo, TargetDomainName: W11CLIENT (yerel hesap olduğu için domain adı yerine makine adı görünüyor), LogonType: 3 (Network) ve AuthenticationPackageName: NTLM / LmPackageName: NTLM V2 değerlerini gösteriyor – GPP’den çalınan bir parolanın gerçek bir yanal hareket girişiminde nasıl kullanıldığının uçtan uca kanıtı:
Event ID 4624 – Genel sekme, gppdemo hesabının W11CLIENT üzerinde Logon Type 3 ile başarılı oturum açması.
Event ID 4624 – Detaylı Kimlik Doğrulama Bilgileri sekmesi, NTLM/NTLM V2 kimlik doğrulama paketini gösteriyor.
Bu lab denemesi, Password in GPP compromise tekniğinin özünün (herkese açık bir anahtarla “şifrelenmiş” bir parolanın anlamsızlığı) 2014’ten bu yana hiç değişmediğini, ama Windows Server 2025’in bu zafiyeti hem GUI seviyesinde hem de SYSVOL’ün kendi kendini denetleyen mekanizmasıyla iki ayrı katmanda pasifize etmeye çalıştığını gösterdi. Buna rağmen, eski/temizlenmemiş bir GPO kalıntısı SYSVOL’de gerçekten var olduğu sürece, teknik hala tamamen çalışır durumda.
Uyumluluk ve Çerçeve Eşlemesi Tablosu
| Çerçeve | İlgili Kontrol/Madde |
|---|---|
| PCI DSS | Gereksinim 7.1 (Erişim kısıtlaması), Gereksinim 8.2 (Güçlü kimlik doğrulama) |
| HIPAA | 164.312(a)(1) – Erişim Kontrolü |
| ISO 27001 | A.9.2 (Kullanıcı Erişim Yönetimi), A.9.4 (Sistem ve Uygulama Erişim Kontrolü) |
| KVKK | Madde 12 – Veri Güvenliğine İlişkin Yükümlülükler |
| TCMB | Bilgi Sistemleri Yönetimi Tebliğ – Erişim ve Yetkilendirme Kontrolleri |
| NIST CSF | PR.AC-4 (Erişim yetkilerinin yönetimi), PR.AC-1 (Kimlik ve kimlik bilgisi yönetimi) |
| CIS Controls | CIS 5 (Hesap Yönetimi), CIS 6 (Erişim Kontrol Yönetimi) |
MITRE ATT&CK: T1552.006 (Unsecured Credentials: Group Policy Preferences)
Sonuç
Password in GPP compromise, aslında 2014 yılında resmen kapatılmış bir zafiyet olmasına rağmen, eski GPO’ların temizlenmemesi yüzünden bugün hala birçok kurumda canlı bir risk olarak varlığını sürdürüyor. Bu bölüm, serinin diğer bölümlerinden farklı olarak bir “gün 0” saldırı değil, kurumsal hijyen eksikliğinin klasik bir örneği; çözümü de teknik olarak son derece basit: SYSVOL’ü bir kez tarayıp temizlemek ve bir daha GPP ile parola dağıtmamak. Serinin bir sonraki bölümünde, Active Directory Certificate Services (AD CS) üzerindeki ESC1 zafiyetinin nasıl istismar edilebildiğini inceleyeceğiz.

