FalconFriday — Detecting UnPACing and shadowed credentials—0xFF1E

When playing around with Certipy and Rubeus in a recent project, I got into the rabbit hole. Going through the attacks implemented in Certipy, I wanted to build as many solid detections as possible — essentially revisiting our earlier work on ADCS abuse detection. The rabbit hole started when I began looking into the KDC options[1], their meaning and how they were used in these tools.

I managed to squeeze out quite some high-fidelity detections, of which I want to share two today.

UnPACing the hash

“UnPAC-the-hash” is a technique which allows an attacker with a valid TGT to obtain the NTLM hash of an account. The full details and conditions of this attack are not the topic of this post, you can read the details here and here. I’ll highlight only the relevant parts in this post.

As Dirk-jan points out in his blog post, the KDC ticket option which makes this attack possible is called “ENC-TKT-IN-SKEY”. This ticket option needs to be set as part of the User-to-User (U2U) authentication scheme. Unfortunately, to detect the attack, it’s not enough to look for this ticket option. There are too many Kerberos requests which have this ENC-TKT-IN-SKEY option set, so we need to dive into the code of Certipy to see which options are set.

Certify code where KDC options are set.

As you can see in the screenshot above (and here), Certipy sets the following options:


As you can see in the Microsoft documentation, you can look up which bits correspond to these values in the KDC options bitmask value.


In case you’re not very familiar with bitmasks, consider the following image:

Bitmask for KDC options.

You’ll see that the position row corresponds to the documentation referenced above. The position is counted starting at the “most-significant-bit”(MSB). 0 is the most significant bit and 31 is the least significant bit. For every KDC option enabled, we put a 1 at the corresponding position, or a 0 otherwise. If you do this for the 5 KDC options mentioned, you’ll get a binary number 01000000100000010000000000011000. This is equal to 0x40810018 in its hex representation. In our detection, we will check if these flags are enabled by comparing the bit at each position of a TGS request with the expected value in the bitmask above.

Other tools

Looking into other similar tools, like Rubeus and Kekeo, it turns out the options set are similar. In the Kekeo implementation, you can see that the code uses KERB_KDCOPTION_standard combined with KERB_KDCOPTION_enc_tkt_in_skey.

Combining both options, we see that the intersection of these sets leaves us with Forwardable, Renewable, Renewable_ok, Enc_tkt_in_skey.

Finally, let’s have a look at how Rubeus has implemented this. You’ll see that for U2U requests, it sets the same options as Certipy.

Final detection

So, now we have enough information to build a detection. If you want to go for a broad approach, you should look for TGS requests which have at least the following options set: Forwardable, Renewable, Renewable_ok, Enc_tkt_in_skey. If this happens to give a lot of false positives in your environment, you can add the Canonicalize KDC option to your detection. Based on our testing, this is specific enough to distinguish Certipy/Kekeo/Rubeus TGS UnPAC-the-hash attempts from normal Kerberos traffic.

The full query can be found here.

Shadowing credentials

Another attack — which is more or less a direct consequence of the influential research on ADCS — is shadowing credentials. The full attack is described here. Elad Shamir already provides some good suggestions for detecting this attack. In our blog here, we want to elaborate a bit more on detecting this attack.

Preferred detection

There are two event IDs which you can use for detecting this attack. The first one is 5136 and is the most accurate/straightforward one. To make Active Directory generate this event, the Directory Service Changes audit policy should be set to at least Success. Event 5136 is “A directory service object was modified” and does exactly what we need. Based on this event, we can exactly see when/how the msDS-KeyCredentialLink attribute of an object is changed. The detection for using this event ID is straightforward and is provided here.

Alternative detection

An alternative solution is available if 5136 is not logged in your environment. This alternative is 4662, “An operation was performed on an object”. This is a more generic event and requires an audit policy which is not very common (refer to this page on how to enable this event id). However, if you happen to have it, or are able to get this event, you can use it to detect this attack. The data inside event 4662 requires some more understanding of event logging though, so we will go in a bit more detail on that.

The detection that uses 4662 looks roughly as follows:

| where EventID == 4662
| where Properties has "5b47d60f-6090-40b2-9f37-2a4de88f3063"
// msDS-KeyCredentialLink.
| where Properties has "%%7685" or AccessList has "%%7685"
| where Account !startswith "<YOUR_DOMAIN>\\MSOL_" // AAD Connect.

The obscurity in this detection comes from the “magic values”. The first magic value is the GUID. This GUID refers to the so-called “schemaIdGUID” of msDS-KeyCredentialLink in the Microsoft documentation.

The second magic value in this query is the %%7685 which is a value defined as MESSAGETABLE in msobjs.dll . You’ll find that the %%7685 value translates to the “Write Property” string, which is the action we’re interested in. Weirdly enough, we’ve seen that sometimes the action is the first part of the “Properties” field, while other times, the “AccessList” contains this value when a property is written. We haven’t really figured out what happens when, but checking for the value in any of both is sufficient for this FalconFriday’s purpose. You can find the detection in our FalconFriday repository.

For both detections, we filter out the “Azure AD Connect” account, since we’ve seen this account writes the msDS-KeyCredentialLink very often (for understandable reasons). If you use Azure AD Connect, you might want to filter out those actions. Other than that, we haven’t see any false positive for this detection.

Knowledge center

Other articles

Together. Secure. Today.

Stay in the loop and sign up to our newsletter

FalconForce realizes ambitions by working closely with its customers in a methodical manner, improving their security in the digital domain.

Energieweg 3
3542 DZ Utrecht
The Netherlands

FalconForce B.V.
[email protected]
(+31) 85 044 93 34

KVK 76682307
BTW NL860745314B01