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

Correct AES Salt Generation #36

Merged
merged 1 commit into from
Dec 17, 2019
Merged

Correct AES Salt Generation #36

merged 1 commit into from
Dec 17, 2019

Conversation

monoxgas
Copy link

@monoxgas monoxgas commented Dec 6, 2019

It was my flawed understanding (and I assume many people's as well), that the salt for AES types in Kerberos was FQDN.Upper() + Username.Lower(). However this is not the case.

I believe Kevin Robertson details it the clearest in Get-KerberosAESKey

.PARAMETER Salt
[String] Concatenated string containing the realm and username/hostname.
AD username format = uppercase realm + case sensitive username (e.g., TEST.LOCALusername, TEST.LOCALAdministrator)
AD hostname format = uppercase realm + the word host + lowercase hostname without the trailing '$' + . + lowercase realm (e.g., TEST.LOCALhostwks1.test.local)

This came as such a surprise that I wondered how Windows determines the correct salt when supplying any username for authentication. The secret lies in an initial AS-REQ without a PA-ENC-TIMESTAMP section and with PrincipalName set to the case-insensitive username. The KDC will then respond with an KRB5_ERR_PREAUTH_REQUIRED containing a PA_ETYPE_INFO2, which supplies the encryption type + the correct salt. As per usual, impacket already has this figured out:

https://github.com/SecureAuthCorp/impacket/blob/d65c0d220a9613ae74db42adc9362a7947acdd66/impacket/krb5/kerberosv5.py#L200

So what to do? Well the extra back/forth might not be ideal in some scenarios (brute-forcing), but I'd be happy to implement it just to have it. Maybe a separate command like getsalt? It could also be added as part of the hash command which I rather like. It does open itself up to a fair bit of complexity like extra flags, specifying whether the username is already cased properly, etc.

Of course these steps are generally unnecessary if you just use the samaccountname from AD (machine accounts aside). Therefore I've started by just removing any ToLower() calls when calculating the salt. This might also be best paired with some help/notes that indicate the username is case sensitive.

Let me know what your thoughts are and I'd be happy to oblige.

@HarmJ0y
Copy link
Member

HarmJ0y commented Dec 17, 2019

This is awesome, as always @monoxgas . Appreciate the catch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants