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.)
In what circumstances does ktpass set the user's salt?
How is the salt determined?
Is the salt stored in AD, or just in the KDCs?
Is there a straightforward way to read the current value of the salt?
Is there a way to manually change the salt?
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.
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.
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".
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.
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
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):
Install MIT Kerberos for Windows
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.
Related
I am currently trying to find out AD users password expiry date.
Using the methods described on numerous pages for e.g. here work fine until a user or group in AD is using a fine grained password policy that does not follow the users domain password policy.
I found a property called msDS-UserPasswordExpiryTimeComputed that figures that all out without trying to do any calculations.
This works well, until we are using a global catalog since this property is not replicated by default. When I attempting to replicate the msDS-UserPasswordExpiryTimeComputed property in my global catalog, I get the following error:
Is there anyway to replicate this property or is something wrong with my setup that is not allowing me to replicate this property? Is there a better way to calculate user password expiry to take into account the fine grained password policy?
I suspect you can't. I can't find any authoritative documentation saying it is not possible, but here are the reasons I think it's not possible:
The attribute is constructed, meaning it's not stored, but it's calculated at the time you ask for it.
The date depends on the policy on the domain, thus the server returning the data needs to know the policy on the domain of the user.
Since a GC may not be on the domain of the user you find, it may not have the information needed to be able to calculate the value.
As a workaround, you can just rebind to a DC to get the value. You didn't say which language you're working with, but usually you can take the path of the object you found, which will start with "GC://", and just replace that with "LDAP://". Then grab the msDS-UserPasswordExpiryTimeComputed value.
I have a winforms application that connects to a database with a connection string and a generic user
"Database=DBADAS;Server=TMT123\\SQLEXPRESS;User ID=user; Password=*****;
After connecting into the database with a login dialog, we check if the user and password are existent in the user table from the database.
My question is now if this is a good practice? because basically in the connection string there is every information needed to crack the server.
There are a few ways to go about this safely. Since it's a Winforms app and not a web application, most of your security risks involve someone already in your network peeking at the connection string. This adds a layer of security in and of itself.
1. Hardcoded
You can hardcode the connection string that fetches the users into a DLL and make your application depend on that DLL. I only suggest this because it sounds like the "generic user" password is permanent; otherwise, you'd have to recompile code every time you changed the password, then deploy again. This is very secure, however, as the value isn't stored in plain text.
2. App.Config
You can stick it in a configuration file. Within a secured network, this is probably the most versatile option, as you can store multiple strings and easily update them without updating the full application. This goes well alongside settings like a "DebugMode" setting, etc. Using App.Config or another XML file is ideal, but you can roll a quick and dirty .txt file, too.
3. Database
Probably the most secure way of all, as you can encrypt your database and code your programs to fetch their connection strings and login information from that database by using an unrelated login. This allows greater control over what can be reached by the application when a user has not yet logged in. It also prevents the software from operating outside of the network, which may be desirable.
4. Internal API
Having a separate application serve this data divorces user capability from your concerns, as the API and your app can exchange verification keys to see if your app even has permission to try to connect. This is my personal favorite, but obviously the most work to set up.
5. Registry Entry
Depending on how you have this installed, it may work well to embed the tokens you need in the Registry. This guarantees the app requires admin permissions to install, and allows you to use Windows security to restrict access to the hive.
Again, since it's an internal non-web app, I wouldn't worry too much about the plain text of the connectionstring; if someone has gotten this far into your network, chances are you have much bigger problems already. I wouldn't leave it floating as a plain text file in a local directory, but any degree of security above that is probably acceptable for your purposes.
Encrypting Web.Config
Open Command Prompt with Administrator privileges
At the CommandPrompt, enter:
cd C:\Windows\Microsoft.NET\Framework\v4.0.30319
In case your web Config is located in "D:\Articles\EncryptWebConfig" directory path, then enter the following to encrypt the ConnectionString:
ASPNET_REGIIS -pef "connectionStrings" "D:\Articles\EncryptWebConfig"
Use Aspnet_regiis.exe tool with the –pef option and specify the application path as shown above.
Note: The parameter "connectionStrings" is case sensitive.
For Winforms: You need to rename your app.config to web.config encrypt it by using steps 1 to 3 and again rename it to app.config.
Reference: https://www.codeproject.com/Tips/795135/Encrypt-ConnectionString-in-Web-Config
I thought I understand how Kerberos works, now I am not sure at all.
We have a problem with Kerberos authentication on a 3rd party server with Windows Active Directory. The server support is insisting that what they call "kerberos server" passes additional information somehow, namely fields identified as uid and email, and I need to confirm that they are indeed "sent" by the server before they can help any further. I read "kerberos server" as the KDC, which "sends" information by placing it into the TGT, and the uid may be the good old UPN, except I do not understand why I am asked to confirm it is really there. But what is the email attribute?
I even read the whole RFC4210, but could not find any possible place for additional info in any of the tickets. In general, 1.5.2 talks about extending the protocol, but in the very abstract manner. There are also KRB_SAFE and KRB_PRIV messages, that can be used to pass arbitrary octet strings (3.4, 3.5), but no step towards defining their structure is done in the standard. There is also padata extension, that 5.2.7 notes have also been used as a typed hole with which to extend protocol exchanges with the KDC., but this seems sent one-way. And nowhere the RFC seem to talk about additional identified fields that the authentication server can attach to the ticket.
My question is thus bifold:
Theoretical: how additional attributes are passed in Kerberos, presumably in an interoperable way (not e. g. Active Directory extensions)? What am I being asked to confirm?
Practical, if anyone can help with that: how to track what is placed by the AD into these attributes?
The server support is very lousy at telling you what they really want to have. Here is what you need: You want the KDC to send you PAC data with the generated service ticket. Here is Microsoft's reference: https://msdn.microsoft.com/en-us/library/cc237917.aspx.
How to verify? You need the a keytab for the account which is accepting the security context. Configure that with Wireshark, log all traffic. You should see the TGS-REP for the service you'd like to use. Expand it, when the keytab is fine, you will see the decrypted information. Somewhere down below, you should see the Authorization Data fields, type 1 (AD-IF-RELEVANT). That is an ASN.1-encoded sequence of elements. Even element position describes the sub type, odd element position the octet string. In that octet string is again an ASN.1-encoded suquence with type 128 (AD-WIN2K-PAC) and that is the PAC data. Unfortunately, Wireshark can decode upto level one only. The request is an opaque byte buffer. I have minimal, working (though incomplete) Java implementation of the PAC data decryption.
The email value is not included in that structure but what you have is the RID KERB_VALIDATION_INFO structure and the userPrincipalName in the UPN_DNS_INFO structure. The latter is extremely easy to decode.
First check via LDAP that for the desired client account userAccountControl does not has the NA field set.
Godspeed.
I am new to LDAP and I am wondering if attribtue names like "maxPwdAge" and "pwdLastSet" are constant attribute names for LDAP, not just AD?
The reason that I want to know this is because I want to write a program to calculate password expiration time for all systems that use LDAP. If the names are not constant across systems, it might be pretty complicate for me.
pwdLastReset is peculiar to Active Directory as far as I know.
pwdMaxAge comes from a Internet Draft 'LDAP Password Policy', which is the step before an RFC, which technically expired years ago but which is nevertheless implemented by a number of LDAP servers. In OpenLDAP you have to add the ppolicy overlay to get the password-policy attributes to appear.
You should also note that you may not have access to the pwdLastReset attribute, and that pwdMaxAge is not an attribute of the user at all: it is an attribute of the policy entry, which you may not have access to either.
No. These is no universal standard to determine when a password expires.
As #EJP mentioned, there is a Internet Draft 'LDAP Password Policy' that has been implemented to some levels for several LDAP server implementations but it is not universal.
-jim
Is there any way that we can programatically create a Documentum user by using Active Directory information? (I have very little knowledge on ADT and know that it stores user info thats all.)
In Documentum Administrator you can sync the ActiveDirectory Users by running the Job dm_LDAPSynchronization. This should do.
Hope this helps,
Max
edit: You can also create a User using DFC-Methods:
IDfUser newUser = (IDfUser) session.newObject("dm_user");
newUser.setUserName("New User");
newUser.setUserLoginName("newuser");
newUser.setString("user_source","inline password");
newUser.setString("user_password","new_password");
newUser.setDefaultFolder("/newuser",true);
newUser.save();
Instead of putting inline_password as the user_source, you probably can choose LDAP and remove the user_password. This most probably needs more information, but I don't have the DFC Documentation with me at the moment. I could look it up in the evening, but for now this should give you a good point to start.
You could also make a Server Method out of it and assign it to a custom Job.
BUT: I don't think that you can CREATE new LDAP-Users from Documentum...they need to be present in the ActiveDirectory when you import them into Documentum!
Cheers,
Max
You can configure LDAP through DA and set all the connection info, user id password and than configure the ldapsync job to do this ,whenever a new user is added into ldap,it will be imported into documentum by that job and deactivated if user is removed from ldap.
Thats the best way to avoid any programming .
The LDAP synchronization is quite limited and shortsighted. You can concatenate two LDAP attributes for a user like this : ${sn}_${givenname}#company.com. You can also substring, starting from left to a given number. Thats it. No more. I wonder why they bothered.
A proper solution would have been standarsing on a expression language - all from XQuery to RegEx. There are lots to choose from.