Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Kerberos TGS etype 17/18 #2809

Open
magnumripper opened this Issue Oct 4, 2017 · 24 comments

Comments

Projects
None yet
7 participants
@magnumripper
Copy link
Owner

magnumripper commented Oct 4, 2017

@kholia kholia self-assigned this Oct 15, 2017

@kholia kholia removed their assignment Oct 19, 2017

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Oct 21, 2017

I haven't seen any proof (or proof-of-concept) that doing this is possible.

Also see my comments in PR #2822.

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Oct 21, 2017

@elitest Do you have any proof (or proof-of-concept) that Kerberoasting of TGS-REP messages which use etype 17 and 18 is technically possible? Have you considered the possibility that it might not be possible to crack such TGS-REP messages at all? Also see my comments in PR #2822. In particular, note that I could only conduct Kerberoasting attacks against MS Active Directory and not against krb5 software.

@elitest

This comment has been minimized.

Copy link

elitest commented Oct 22, 2017

@kholia Great question. So it is possible to to generate the hashes against correctly configured accounts. To configure service accounts correctly set msDS-SupportedEncryptionTypes to 24 in the LDAP attributes of the account as discussed here. This is actually the way that AD administrators should be configuring accounts if they want the TGS-REPs encrypted more securely with AES. Once you have that setup you kerberoast the SPN that that account is registered with. Both GetUserSPNs.py and Invoke-Kerberoast now support generating and understanding AES hashes. See our talk at DerbyCon 7 for maximum detail. We are confident that we have implemented the hashes correctly as we used packet captures of the TGS-REPs on these AES accounts to validate that we were grabbing the correct data.

As to whether or not the hashes will crack. I don't have any PoC that cracks an AES kerberos ticket, however my understanding of the RFCs and MS-KILE lead me to believe that the TGS-REP is encrypted with the RC4 hash(NTLM in the case of AD) the same way that AES does with the respective keys(AES128 and AES256).

One other issue specific to john, is that I believe john's TGS hash format will need to be modified or something as it doesn't specify which type of crypto is used, whereas hashcat's format does.

Let me know if you have any other further questions or if I can help in any way.

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Oct 23, 2017

One other issue specific to john, is that I believe john's TGS hash format will need to be modified or something as it doesn't specify which type of crypto is used, whereas hashcat's format does.

This particular problem is easy to solve.

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Oct 27, 2017

Maybe @gentilkiwi, @PyroTek3, @Fist0urs, and @HarmJ0y have something to say on this topic (i.e. Kerberoasting of etype 17 and 18 "hashes" instead of etype 23).

It seems that solving this problem will require some amount of reversing / low-level debugging of Kerberos functionality on Windows platform.

@gentilkiwi

This comment has been minimized.

Copy link

gentilkiwi commented Oct 28, 2017

Low Level Debug ? If I remember well, type 17 or 18 are standards.
I made a little ugly C POC around it to get key from password: https://gist.github.com/gentilkiwi/612588b1d4d3a3039fa83802f0053290

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Oct 28, 2017

@gentilkiwi Thanks for taking a look at this stuff! 👍

I have the AES key derivation part working as well [1]. The parts that I am missing are (1) how is this AES key used to decrypt the encrypted ticket data from TGS-REP message (2) how does the client verify that the decrypted data is correct (there is SHA1 checksum involved but I am missing the exact details). These details will make the Kerberoasting of etype 17/18 TGS-REP messages possible.

We need to figure out the HMAC key derivation part (which is involved in the SHA1 checksum calculation). This will also involve figuring out the correct value of usage[3]. I am assuming that this stuff is very similar to the code we have in krb5_asrep_fmt_plug.c file. I could be wrong though.

[1] https://github.com/kholia/JohnTheRipper/tree/TGS-ng (see crypt_all from the top commit, filename is krb5_tgs_fmt_plug.c).

@gentilkiwi

This comment has been minimized.

Copy link

gentilkiwi commented Oct 28, 2017

Did you take a look in: https://www.ietf.org/rfc/rfc3962.txt ?
As for RC4, the best way to check is to detect ASN1 header in first 16 bytes.

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Oct 29, 2017

Did you take a look in: https://www.ietf.org/rfc/rfc3962.txt?

Yes, we have already implemented this entire RFC in the krb5pa-sha1_fmt_plug.c and krb5_asrep_fmt_plug.c files. These plugins crack the various AS-REP messages which are using etype 17/18 just fine. We are just missing support for cracking TGS-REP messages which are using etype 17/18.

As for RC4, the best way to check is to detect ASN1 header in first 16 bytes.

Yes, @Fist0urs implemented this technique in krb5_tgs_fmt_plug.c file.

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Oct 31, 2017

Here are some rough ideas on how further progress can be made. Please note that I am not sure if this approach is even correct.

I suspect that Kerberos functionality is provided by lsasrv.dll on Windows. WinDbg can be attached to the LSASS process, and various functions present in lsasrv.dll can be traced. In particular, tracing of input + output data from LspRC4EncryptData, LspAES256EncryptData, rijndaelEncrypt128, rijndaelEncrypt256, LspAES256DecryptData and related functions needs to be done. Tracing LspRC4EncryptData will act as a verifier for this approach. We should see the NT hash coming in as the RC4 key while tracing the LspRC4EncryptData function. After that, I would like to see the actual AES key being used to encrypt the TGS stuff. The output of AES encryption needs to be compared to the data in the TGS-REP packet we see on the wire.

The runas /user:EXAMPLE\user "cmd" command can be used along with "Request Ticket(s)" method from https://github.com/nidem/kerberoast to trigger the invocation of the desired functions.

https://blogs.msdn.microsoft.com/spatdsg/2005/12/27/debugging-lsass-oh-what-fun-it-is-to-ride/ should be useful here.

For function tracing, ideas from https://labs.mwrinfosecurity.com/blog/heap-tracing-with-windbg-and-python/ can be used.

@elitest

This comment has been minimized.

Copy link

elitest commented Nov 2, 2017

@kholia What would happen if we just decrypted a bunch of TGS-REPs... shouldn't we get something formatted as ASN1 if the decryption worked?

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Nov 3, 2017

@elitest Yes, that is correct.

https://adsecurity.org/?p=2293 says, "The TGS is encrypted using the target service accounts’ NTLM password hash and sent to the user (TGS-REP)". This is what makes Kerberoasting attacks possible. The code in krb5_tgs_fmt_plug.c decrypts the encrypted TGS, and checks that that decrypted data looks like valid ASN.1 data. So far, so good.

In case of etype 17/18, I have the AES key derivation part working. This matches the aes256_hmac data shown my mimikatz, and it also matches the output of echidna. However when I decrypt the encrypted TGS (which is using etype 17/18) with this AES key, I don't get valid ASN.1 data as the output. This makes me suspect that either (1) my code is broken (quite possible) (2) Kerberoasting of TGS-REP messages in case of etype 17/18 is not possible (MS fixed their implementation specific bugs) (3) we are missing some important "algorithm" details, which will require more reversing + debugging on Windows.

Current code -> https://github.com/kholia/JohnTheRipper/tree/TGS-ng (see crypt_all from the top commit, filename is krb5_tgs_fmt_plug.c)

@kholia kholia self-assigned this Nov 6, 2017

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Feb 28, 2018

So far no one has been able to prove that this task/technique is possible.

@kholia kholia added the non-trivial label Mar 20, 2018

@kholia kholia closed this Mar 20, 2018

@HarmJ0y

This comment has been minimized.

Copy link

HarmJ0y commented Feb 15, 2019

@kholia this is something I want to see if we can revisit - the code you at the Current code -> https://github.com/kholia/JohnTheRipper/tree/TGS-ng (see crypt_all from the top commit, filename is krb5_tgs_fmt_plug.c) comment - was that preserved at any point?

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Feb 15, 2019

Thanks for looking into this stuff @HarmJ0y 👍

https://github.com/kholia/JohnTheRipper/tree/TGS-ng

I have restored this branch now (I don't know how/why it was gone earlier).

@Fist0urs

This comment has been minimized.

Copy link
Contributor

Fist0urs commented Feb 17, 2019

Hi guys,

I've been discussing with @skelsec at offensivecon. I planned to reverse stuff to implement it (as I did for the RC4 part) but he told me that he already made a script that implements the algorithm. I guess he can share it here so that it will be implemented? As @kholia has already started the jtr part maybe I could stick to the hashcat part? So that we'll have it both jtr and hashcat implementations 👍

Cheers!

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Feb 18, 2019

Sharing the code here would be great.

Thanks @Fist0urs and @skelsec for this great news.

@kholia kholia reopened this Feb 18, 2019

@skelsec

This comment has been minimized.

Copy link

skelsec commented Feb 21, 2019

I put together a poc script alongside with some test cases of TGS ticket decryption for etype17/18.
it runs on python3 (tested with 3.7). Paths are windows paths for the test-case files, so you may need to modfy them.
The logging is turned to debug, it shows most functions input-output parameters if you wish to cross-check it with your code.
Test cases ran by tgs_dec_poc.py
In the meantime I found a tgs ticket in your sourcecode, so I made another file decrypting just that one tgs_dec.py
Hope it helps.

Note: most of the encryption-decryption part was originally coming from impacket, I just ported it to py3 and dissected the AES it into a single file and added some comments.

kerb_poc.zip

@Fist0urs

This comment has been minimized.

Copy link
Contributor

Fist0urs commented Mar 2, 2019

@kholia, the input hash formats accepted for the 23 enctype are as follows:

/*
assuming checksum == edata1
formats are:
$krb5tgs$23$checksum$edata2
$krb5tgs$23$*user*realm*spn*$checksum$edata2
*/

Unfortunately 17/18 require the user + realm in order to create a salt, so we must include them in the input hash.

I suggest to adopt these input formats:

$krb5tgs$17$*user*realm*$checksum$edata2
$krb5tgs$17$*user*realm*spn*$checksum$edata2

Are you okay with that?

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Mar 2, 2019

@Fist0urs Sure. It would be nice to update the associated helpers tools (like run/krb2john.py?), if required. This can happen in a different, future PR (if required).

Thanks for handling this 👍

Update: Hopefully, I will be back in action in some weeks :)

@Fist0urs

This comment has been minimized.

Copy link
Contributor

Fist0urs commented Mar 2, 2019

I'll update the associated helpers tools yes!
Actually I was thinking about removing my tool "kerberom" from the repo as it is pretty deprecated. Now impacket does the job really better (and implements the 17/18 stuff) so this would be a better option imho. If you are ok with this removal, I'll create a KerberosTGS HOWTO in the docs that explain how things work.

Take your time for the code, I'll have to dive into hashcat code first to remember it so this is not urgent 😄

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Mar 2, 2019

Actually I was thinking about removing my tool "kerberom" from the repo as it is pretty deprecated.

Sure. Please go for it. Create a small PR and I will review it asap.

I'll create a KerberosTGS HOWTO in the docs that explain how things work.

This would be awesome, thanks! I don't remember most of this Kerberos stuff these days!

@Fist0urs

This comment has been minimized.

Copy link
Contributor

Fist0urs commented Mar 14, 2019

Ok, I've implemented it in hashcat (hashcat/hashcat#1955)

Next step is implementing here.

Regarding the input format I adopted this:

$krb5tgs$17$user$realm$checksum$edata2
$krb5tgs$17$user$realm$*spn*$checksum$edata2

$krb5tgs$18$user$realm$checksum$edata2
$krb5tgs$18$user$realm$*spn*$checksum$edata2

I enclosed user and realm within '$' and spn within '*' as user and realm are mandatory and spn is optionnal (not taken into account while computing the hash). PR to adapt the hash format (+ correction) was accepted in impacket: SecureAuthCorp/impacket#584

I'll also commit a "HOWTO" regarding Kerberos in jtr.

I tried to comment a lot the hashcat code so that it would be easier to implement these hash formats within john, if I'm not the one who implements it.

@kholia

This comment has been minimized.

Copy link
Collaborator

kholia commented Mar 14, 2019

Go for it @Fist0urs 👍

It might be a while before I am back in action.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.