john icon indicating copy to clipboard operation
john copied to clipboard

Support for Kerberos TGS etype 17/18

Open magnumripper opened this issue 6 years ago • 33 comments

https://github.com/hashcat/hashcat/issues/1384

magnumripper avatar Oct 04 '17 18:10 magnumripper

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

Also see my comments in PR https://github.com/magnumripper/JohnTheRipper/pull/2822.

kholia avatar Oct 21 '17 04:10 kholia

@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.

kholia avatar Oct 21 '17 04:10 kholia

@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.

ihamburglar avatar Oct 22 '17 22:10 ihamburglar

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 avatar Oct 23 '17 05:10 kholia

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.

kholia avatar Oct 27 '17 10:10 kholia

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

gentilkiwi avatar Oct 28 '17 11:10 gentilkiwi

@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).

kholia avatar Oct 28 '17 12:10 kholia

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.

gentilkiwi avatar Oct 28 '17 21:10 gentilkiwi

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 avatar Oct 29 '17 04:10 kholia

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.

kholia avatar Oct 31 '17 16:10 kholia

@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?

ihamburglar avatar Nov 02 '17 18:11 ihamburglar

@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 avatar Nov 03 '17 03:11 kholia

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

kholia avatar Feb 28 '18 04:02 kholia

@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?

HarmJ0y avatar Feb 15 '19 07:02 HarmJ0y

Thanks for looking into this stuff @HarmJ0y :+1:

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

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

kholia avatar Feb 15 '19 08:02 kholia

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!

Fist0urs avatar Feb 17 '19 22:02 Fist0urs

Sharing the code here would be great.

Thanks @Fist0urs and @skelsec for this great news.

kholia avatar Feb 18 '19 01:02 kholia

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

skelsec avatar Feb 21 '19 22:02 skelsec

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

https://github.com/magnumripper/JohnTheRipper/blob/111527672ad0740e330eacf1be8bff23e2f92fa3/src/krb5_tgs_fmt_plug.c#L61-L67

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?

Fist0urs avatar Mar 02 '19 14:03 Fist0urs

@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 :+1:

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

kholia avatar Mar 02 '19 14:03 kholia

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 😄

Fist0urs avatar Mar 02 '19 14:03 Fist0urs

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!

kholia avatar Mar 02 '19 14:03 kholia

Ok, I've implemented it in hashcat (https://github.com/hashcat/hashcat/pull/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: https://github.com/SecureAuthCorp/impacket/pull/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.

Fist0urs avatar Mar 14 '19 16:03 Fist0urs

Go for it @Fist0urs :+1:

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

kholia avatar Mar 14 '19 16:03 kholia

Any chance this could get a bump? Ran into this exact thing and see that hashcat now supports 19700.

nowhey2 avatar Dec 17 '19 15:12 nowhey2

I've just added this to a milestone, but I didn't look into the actual issue and I expect that only @Fist0urs might contribute anything in this area soon.

solardiz avatar Dec 17 '19 16:12 solardiz

Hi there! Sorry I've been really busy lately... I'll try to take a look in the upcoming month :)

Fist0urs avatar Dec 18 '19 10:12 Fist0urs

It seems that hashcat's 19700 module is broken and doesn't actually crack real hashes.

Sample hash: hashes.txt

Password is test@123.

Pcap for the same setup: [email protected] - hash may be different due to a different impacket "session".

$ ../run/john --test --format=krb5tgs_modern   
Will run 16 OpenMP threads
Benchmarking: krb5tgs_modern, Kerberos 5 TGS etype 17/18 [PBKDF2-HMAC-SHA1 + AES]... (16xOMP) DONE
Warning: "Many salts" test limited: 8/256
Many salts:	16062 c/s real, 1041 c/s virtual
Only one salt:	15906 c/s real, 1040 c/s virtual
$ ../run/john ~/hashes.txt -w=wordlist
Using default input encoding: UTF-8
Loaded 1 password hash (krb5tgs_modern, Kerberos 5 TGS etype 17/18 [PBKDF2-HMAC-SHA1 + AES])
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 9 candidates left, minimum 16 needed for performance.
test@123         (?)     
1g 0:00:00:00 DONE (2021-10-27 17:25) 100.0g/s 900.0p/s 900.0c/s 900.0C/s [email protected]@123
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

Related: https://twitter.com/hashcat/status/1105909927825104896.

kholia avatar Oct 27 '21 11:10 kholia

It seems that hashcat's 19700 module is broken and doesn't actually crack real hashes.

@kholia Perhaps you should open an issue in @hashcat GitHub, then? I guess @Fist0urs already saw your comment here and will check, though.

solardiz avatar Oct 27 '21 12:10 solardiz

CC @Fist0urs and @jsteube - Context is https://github.com/openwall/john/issues/2809#issuecomment-952846956.

kholia avatar Oct 27 '21 12:10 kholia

Hello, Is the code for this format already available on Bleeding-Jumbo? I'm asking because I don't see the --format=krb5tgs_modern and if I try the test hash sample that @kholia with --format=krb5-18 it doesn't recognize it. thanks

$ ./john John the Ripper 1.9.0-jumbo-1+bleeding-75667e2 2022-02-22 13:29:07 +0100 OMP [linux-gnu 64-bit x86_64 AVX2 AC]

$ ./john --format=krb krb4 krb5-17 krb5-3 krb5asrep-aes-opencl krb5pa-md5-opencl krb5pa-sha1-opencl krb5 krb5-18 krb5asrep krb5pa-md5 krb5pa-sha1 krb5tgs

PracaGrande avatar Mar 03 '22 18:03 PracaGrande

Looks like @kholia had a working format but never created a PR, and now that branch is gone in his repo 😢

magnumripper avatar Mar 04 '22 00:03 magnumripper

Damm, was felling luck I could try cracking some Kerberos tickets with John ...

Meanwhile, I also have the following hash format Kerberos 5 TGS etype 18 with a 32 bits checksum instead of 24 like the sample from @kholia . This was captured from a Windows 2016 Server using Invoke-Kerberoast.ps1 from @HarmJ0y ... I know its not related to JtR but wondering if anyone in this thread knows if this is a different format? (also unable to load it into hashcat)

$krb5tgs$18$user$realm$*spn*$DA56E256167275EA6D4FE490C554976E$CBF774183730E46CFFD08D6695F428ADDA06AF2B4EFAC951180CA0A333712988A760634414F8D5A6EF9D2A2C1C999CC1FF5DB21004E0763A1B0BD9F3435AB6FF71E9CCF53708579B33B11955C5A1CB7625A65DE1D3D04E69D80B99A6DE0ACE593CD2FEF9B6F1212E490637F765F83539629C3C8D3544B68B313D321DB4A7C2AF2928A17AE8F44CF2F5A7AFFEAC477803E858CA7D72E757A194397206F700DAFAFAFA2B49BB7B2CADFEE9756E1B06DD3435EEAC46E2A02D316D57BE9460E92ED9E7FCCC8654094216131EECAA73E702C4DFDAF3CD77AB13C2B201905628FF9FB526AE38238E1D0CDA5FE26F6FC38DEBB41A7038E233F57F6DDBE19271E71DE1789309E9EAA615FB3B008CA0BB3DB560922318BA270F2CA406A0A3127A71380467DE3898FF952A0C18DC009A438C1C0761CCB0E8CA53320C7633D529542ABBB330D370258C89F11B8B2F907FA0D801E937F5714489BE1F55C7E4625BCB6E3B73F056B8EE2A0465FA541FA6AD2F991E8965451FCFB56FEF95538EE9C28AA593FCD85F2600514DAE8A138E950C346F88BFD89823E5FF548C0C2133D7B3D6F231FD770467BD2C9AAB88B990DC296F9B6AD8315E0A0124495787D998DABDFE79DE6CF7F022C4C944988A590E5A955E9D1BFF9011B82CC12EC77501A60E943D7B9D97D2E0E9A7292ABDDAB1FC070969BE9FB81B4293038445F563592539B313F7EBF1113E95B0BBBE5A3CA2669CA00335DB16CC4EC1AAE8BB5993967666D2B394C571C5AAC0DB7E3860859F2B028E6AD346CA2D6EAD1B9452EB2E110FBF3131FB9410BA0853AB97855E89E7EBDDDA2003058D82761A46B17B0C4241A025E5A9AA7E2AC6396BFDA64DD0BF8EF2C1FF8EEAD9DE6010DD114DDDB911F8D603869D51B2FB17A125E47EF7FD1684F9358BD88ADE05B39A263ED63721DEB6EE2CED00C37CD8FDC96177AE1F0467C79F09CC1D8DACA2B6626F459FE5EE94E2E8C0E7ADC62A1E1D6A3B32337396102ED5D1BBEE5EE9AD2BDFC3BFEAAE6DFB8C7ED5C6FF931B6FFF10C1E36853832F0D8CFB6D68BCDC915F36DCEC8B75B0E1373D374D76608BF329B7ACA15600F2E760285D63B948AE0AE4A3C690A0FC7D3A3C90FDEC7D031F91FD3DFE56AE7AEA3C5471E47BC08F94FA1179598B9C36E706125CB9DB1E082160649AB47B07FB035E5366F36F5E42EE7E1EBC70F3EB55324B5A91DC7686C93334DEE482BD57DCE73E47589E767358398C1A78270D11ECDBDB954E7F6D684904631F2C649B11FB8FBFC9B687A0076D3A326AAD7251CC49A1AA437F0D903A6830DE82568FE7AB3FE688139F128488FB269B72BF37B63587325D68016DBFAF6904B3676031403B7A45B33229D27A00AD36BEAC798DEA9C1A62EFE4A2638E285D8FE66935C8D2EF4E68BFD5B472D724A6D79D85EC68F2C359C8B5D5B81C19CC2CEF934AD332820A00D3F44128AD7F074631E243BA65025D7EA34265F38C550C0DA07EB88694FBB5A7318E98AF1C2AD1FA4A9F81C9350D4B9BF216DC0CC50CCF3EABECA5618643FF90E01A23CF99FE82643232C7E255E396780BE85570A9688754EEE9AD036CAB9B070D91B3680817B08AC9B88404EBC91827CBB16EC3A475A7F01061D73D0496E834F8493CAC44F3AC87EAC4B5C53D193A938E14A5A91C5D20CF3CF0AE5B2D620F739D54F62A23EA112F2ED449864D67A3AE2A7620241A0CFB6FF3A291366514C3EC620FDBAC6CF9F33249EF5B20

PracaGrande avatar Mar 04 '22 08:03 PracaGrande