1

A user's password and salt determine the Kerberos keys generated by ktpass. I have noticed that ktpass sometimes changes the user's salt, but other times it does not. I was able to discover the salt by capturing a packet trace of a kinit. The salt appears to be generated based on the Kerberos realm and the userPrincipalName. However, it's not this simple. If the UPN is later updated manually, the salt is not updated. (I suspect that whether the /mapop option is specified may play a role.)

  1. In what circumstances does ktpass set the user's salt?
  2. How is the salt determined?
  3. Is the salt stored in AD, or just in the KDCs?
  4. Is there a straightforward way to read the current value of the salt?
  5. Is there a way to manually change the salt?
mlowry
  • 161
  • 5
  • 12

2 Answers2

3
  1. In Microsoft Windows Active Directory, which has used Kerberos v5 since its inception in Windows 2000, the ktpass command sets the salt automatically. The salt is always used in Kerberos v5. In Kerberos v4, a salt was never used.
  2. The complete principal name (including the realm) is used as the salt, e.g., accountname/somedomain.com@SOMEDOMAIN.COM, which is then paired with the encrypted hash of the password to absolutely ensure the result is unique throughout the AD forest.
  3. As mentioned, the salt is the complete principal name (including the realm). It is stored in the ntds.dit file, which is the Active Directory database. The KDC get spun up in a process spawned by by kdcsvc.dll - and it relates to the values stored in ntds.dit. So while the KDC and AD database are not one and the same inside the runtime environment, they are, so to speak, "joined at the hip". I think when the domain controller shuts down, all the important elements within the KDC is persisted inside of ntds.dit. Microsoft does not provide exact details on how this is done. I have looked extensively, and my partial knowledge is drawn from careful study and inferences made from bits and pieces of articles found on the web. Note that the ntds.dit database is also the LDAP database. It is also the DNS database, if DNS is AD-integrated. All these protocols working together, plus a few more, form "Active Directory".
  4. Open up Active Directory Users and Computers, go to the Account tab. The "user logon name" is the most straightforward way to "read" the salt. You don't see the realm name concatenated with it right there but it is implied. The SPN, if also defined, is listed in a straightforward way like you are looking for under the Attribute Editor tab (look for servicePrincipalName). Make sure you have View > Advanced Features selected in order to expose this tab. A corresponding UPN will also be listed lower down in this same section, in the manner that looks exactly like: accountname/somedomain.com@SOMEDOMAIN.COM.
  5. When you change the account name on the AD Account tab, you have just changed the salt. Note if there is a keytab out there tied to this AD account, you will have just invalidated it, as its secret key inside is a concantaention of the password hash and the salt. When either the salt or the password changes, then the keys will no longer match between the AD account and that inside the keytab. You will have to re-generate it at this point.

Makes sense? This is really a field explanation. To learn more about Kerberos as it relates to AD, start here: Kerberos Survival Guide

T-Heron
  • 5,385
  • 7
  • 26
  • 52
  • In my experience, ktpass changes the salt only if it also changes the _userPrincipalName_. If `ktpass` is run with the `-setupn` option, e.g., to generate a keytab using a known salt (in conjunction with `/rawsalt`), then the salt in AD is not updated. If the userPrincipalName is manually updated (not using `ktpass`), then the salt is not always updated. We think this might be a bug. – mlowry Nov 23 '16 at 14:51
  • We know that the salt is not always updated because have several users whose salt is based on a previous (not current) value of _userPrincipalName_. – mlowry Nov 23 '16 at 14:55
  • This is a great discussion, I'll come back around and comment on this later today. Have to run off atm... – T-Heron Nov 23 '16 at 15:04
  • I think its best to think of "salt" as a verb, rather than a noun, when it comes to Kerberos. Its the complete principal name which is "salted" (think in terms of sprinkling salt on top of food to give it more flavor) against the hash of the user's password in order to make it even more unique. In other words, when I think of "salt", I only think of it only in terms as the principal when it is used in the operation against the password hash and nothing more. I never use either -setupn or /rawsalt in my keytab creation commands. Please send an example of how you're creating the ketytab – T-Heron Nov 23 '16 at 19:07
  • Here is an example of the sort of command we have been using to create a keytab: `ktpass /princ HTTP/testhost1.example.com /mapuser TESTUSER1 /pass XXXXXX /mapop set /crypto AES256-SHA1 /pType KRB5_NT_PRINCIPAL /out c:\temp\testhost1.keytab` This command appears to update the _userPrincipalName_ of TESTUSER1 to something like `HTTP/testhost1.example.com@CORP.EXAMPLE.COM`. The salt will then have a value like `CORP.EXAMPLE.COMHTTPtesthost1.example.com`. In addition to salting the key that is generated, it also appears to store this value of the salt somewhere in AD. – mlowry Nov 24 '16 at 10:08
  • We know that the salt is stored somewhere, and not merely generated each time, because we can see the salt in a packet trace of a kinit. Start a trace like this: `/usr/sbin/tcpdump -s 0 -w /var/tmp/TESTUSER1.pcap -i eth0 tcp port 88` Then run `kinit TESTUSER1` to get a TGT from the KDC. The AS-REP section of the packet trace reveals the salt. If we manually change the _userPrincipalName_ of TESTUSER1 to something like TESTUSER1@example.com, the salt remains set to its old value. Passwords salted with another salt — e.g., a salt based on the updated UPN — will not result in valid keys. – mlowry Nov 24 '16 at 10:11
  • Good comments on the salt. Never gotten into that deeply. Though, just looked in my test AD, there is no value called 'salt' stored on an object which has an SPN defined. I have never seen documented that this value is stored or where, please share if you happen to come across. That said, let me mention three items. 1) Work always from a template file, to create keytabs the same way every time. 2) Also capture a screenshot of keytab creation outputs into a document to help with back-referencing. 3) I would make a slight change to your keytab command, see next comment – T-Heron Nov 24 '16 at 14:00
  • 1
    My suggested changes: (1) I always use +rndPass to randomize the password so no one knows it, not even administrators. No one has to know the password for keytabs to work. (2) use the full UPN of the user onto which you are mapping the SPN: TESTUSER1@EXAMPLE.COM. I have seen where this is not done, then the ktpass command cannot find the user, and then of course no mapping is done. That kind of fits the problem statement you were describing earlier. (3) I put the full FQDN into the keytab file name, for easier sorting and referencing when you have a lot of keytabs stored. – T-Heron Nov 24 '16 at 14:11
  • Try this one instead: ktpass /princ HTTP/testhost1.example.com@EXAMPLE.COM /mapuser TESTUSER1@EXAMPLE.COM +rndPass /mapop set /crypto AES256-SHA1 /pType KRB5_NT_PRINCIPAL /out c:\temp\testhost1-example-com.keytab – T-Heron Nov 24 '16 at 14:11
  • One more comment on the salt, you're seeing what the parser is revealing about packet data. If the salt is changed, then the gears will crank out a different secret key, and that's a function of cryptography. – T-Heron Nov 24 '16 at 17:20
  • 1
    I have validated that the salt revealed in the packet trace is the correct salt to use when creating a keytab. That is, the keytab produced using this command validates ok: `ktpass.exe /out c:\temp\testhost1.keytab /princ HTTP/testhost1.example.com /pass XXXXXXXX /kvno 2 /crypto AES256-SHA1 /pType KRB5_NT_PRINCIPAL /rawsalt CORP.EXAMPLE.COMHTTPtesthost1.example.com -setupn` And for what it’s worth, I found out the _kvno_ to use (2 in this example) by running the kvno command on Linux (after running kinit to authenticate): `/usr/lib/mit/bin/kvno HTTP/testhost1.example.com` – mlowry Nov 25 '16 at 12:56
  • If your keytab validates, then you're good to go. Thanks for coming back with a great comment, I just up-voted it. – T-Heron Nov 25 '16 at 13:00
  • I can figure out the kvno, salt, and password. So I can create a working keytab. I still lack satisfactory answers to my original questions though. Best guesses: 1/2. The salt is set based on the Kerberos realm and UPN at the time a key is generated and mapped to the user. 3. The salt is cached in AD and is not automatically updated when the UPN is changed. 4. There is no straightforward way to read the current value of the salt. The only way is run capture a packet trace of a successful kinit as the user. 5. The only way to change the salt is to generate a new key and map it to the user. – mlowry Nov 25 '16 at 13:35
  • 1
    Maybe this will help explain it more - "Section - 1.23. What is a "key salt"? "kvno"?": http://www.faqs.org/faqs/kerberos-faq/general/section-25.html – T-Heron Nov 25 '16 at 13:44
  • That page provides some helpful general background information on the roles the salt and kvno play in Kerberos. I’m afraid this does not bring me more understanding of the quirks of Microsoft’s Kerberos implementation though. – mlowry Nov 25 '16 at 13:53
1

There is a slightly easier way to read the current salt value (it is not really straightforward but at least no paket tracing is required):

  1. Install MIT Kerberos for Windows
  2. Open a PowerShell and run:
    $env:KRB5_TRACE="kinit-trace.log"
    'C:\Program Files\MIT\Kerberos\bin\kinit.exe' -fV UPN-or-USER@REALM
    Get-Content $env:KRB5_TRACE | Select-String "salt"
    rm $env:KRB5_TRACE
    
    I assume here that MIT Kerberos is installed at its default location. If not you need to adjust the path name in the second command.

This solution was originally suggested here on Stackoverflow for Linux by user Spezieh.

Christoph Böhme
  • 3,766
  • 1
  • 19
  • 29