Set Active Directory password hash to a SHA1 value? - hash

I'm syncing users from an external system into ours. I need to set the user's password in our Active Directory.
I am only provided SHA1's of the external user's passwords and setPassword will hash whatever I is input.
Is setting the User's unicodePwd the actual hash field?
If so, can I just set it to the provided hash?
If not, how/can I set the hash being stored by Active-Directory?

AD does not store just one type of hash. When you change your password, the DC receives the plaintext version of the password, checks its complexity and then generates and stores MD4, MD5, PBKDF2 (4096 * SHA1) and several other kinds of hashes. It is because each authentication mechanism (NTLM, Kerberos, Digest,...) uses a different hash function and AD needs to support them all.
The password hashes are stored in these AD attributes: unicodePwd, dBCSPwd, lmPwdHistory, ntPwdHistory and supplementalCredentials. For security reasons, you cannot read them through LDAP or ADSI. But I have recently found a way to retrieve them and created a PowerShell cmdlet that can do that:
Get-ADReplAccount -SamAccountName John -Domain Contoso -Server LON-DC1
There is also a poorly documented way to push MD4 hashes (AKA NT hashes) to workstation or AD through the legacy SAMR protocol. As there are no built-in commands that expose this functionality, I have created PowerShell cmdlets to do that, too.
To generate a NT hash, you can use this PowerShell command:
$hash = ConvertTo-NTHash (Read-Host -AsSecureString)
And finally, this command pushes the NT hash to AD:
Set-SamAccountPasswordHash -SamAccountName john -Domain ADATUM -NTHash $hash -Server dc1.adatum.com
These commands can be used to migrate passwords between local and domain accounts or between AD and Samba. But be careful, Kerberos-AES and WDigest authentication will not work with this account, only NTLM and Kerberos-RC4.

As far as I understand you can't set unicodePwd to the actual hash field. You can use the userPasswd as you want for your own check but it's not used bys Active-Directory.

As far as I know, what you want is not possible. You can change/set passwords in AD using at least three different protocols:
LDAP (actually LDAPS)
Kerberos Change Password Protocol
NTLM - I am not sure if the latest versions of AD still support it
Am 100% sure that LDAP cannot be used, but you may want to check the other two, as there may be some way to do it with them.

Related

Powershell - base64 encoded with key/passphrase

With citrix netscaler update, the OTP is now encrepted in the active Directory attribute.
The OTP explorer tool created by Andreas Nick was working perfectly up to now.
https://www.andreasnick.com/102-otpedit.html
The citrix Documentation says that the OTP secret is now encrypted by the certificate. After the encryption, the HASH string that is stored in the Active Directory attribute looks like this.
OTP Secret
3DHAZHNBYLK72SFKVUOLU6E4ZE
Hash (in Active Directory)
jjtTl0YY3MGIF77HPcqYs2w2bAc=.sbntdorhH2Ju15c5.kbJ8_AP8Ytu7BiNuICEfkiSgOVJMudtNXgn2eStfoOGyV42v6VbzLA==
I tried to encrypt the OTP secret with the certificate used but they are a lot more caracters (346 in total - citrix encryption has 102).
On the citrix website it says that it is using base64 to encrypt the data.
https://docs.citrix.com/en-us/citrix-adc/current-release/aaa-tm/authentication-methods/native-otp-authentication/otp-encryption-tool.html
I tried to use this code but the HASH is not good.
$enc = [system.Text.Encoding]::UTF8
$string = "3DHAZHNBYLK72SFKVUOLU6E4ZE"
$data=$enc.GetBytes($string)
$sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
$ResultHash = $sha1.ComputeHash($data)
$str_out = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($ResultHash))
write-host $str_out
My guess is that it is using the certificate thumprint as a "key" but I was not able to find a function that encrypts a string in base64 using a key / passphrase.
I have tried other functions created to encrypt strings from a certificate, but was unable to find one that matches the one done by Citrix.
I am not good in all the encryption. I only know the very basics so the answer might be obvious and that I can simply not see it due to my lack of skills in that area.
Thank you in advance for your help.

SecureString Passwords for ADUser

I'm currently making ADUser accounts on a server, and one of the standards here is that the accounts must have a password, even if it is a default password that all new accounts share.
I'm a bit confused by the -AccountPassword parameter on New-ADUser cmdlet, and its relation to SecureString. At the moment, I managed to squeeze out a suitable script-testing-password, but I realise that it is probably nowhere near a suitable password for an account, considering the strange parameters I've put on it to get it to work:
$password = ConvertTo-SecureString "Password1" -AsPlainText -Force
I then use this with New-ADUser: -AccountPassword $password.
Could anyone advise on how to deal with a situation like this? Is my approach suitable for a default password, or am I messing up somehow here? I haven't implemented this so it is difficult to tell if it will work effectively.
In case you have the "User must change password at next logon" set when you set a default password, this approach is pretty normal. If your task is also to not make the default password visible in plaintext, you can use save/load technique on a SecureString which is readable as 100+ hex-symbols, and can be stored as a file. You write a secure string into a file once, then read it from the file and use as a valid secure string in New-ADUser. The primary restriction of a file-based approach is that the string is encrypted by the user's data, using the user that generated the string, so you can't save a SecureString as user A then read it as user B and succeed at decryption.

How to change an user password with SQL on SuiteCRM?

Previously in SugarCRM, the following statement was enough:
UPDATE users SET user_hash = MD5('PASSWORD') WHERE user_name = 'USERNAME';
I can't find a single site on how to do it now with SuiteCRM?
I found this:
Can I still use MD5 passwords? I’m used to that and can easily administer passwords in the database using just MD5.
Sugar will still recognize passwords stored in MD5 format, but anytime a password is changed it will convert to the newer format. Unless very old PHP build (5.2) used in a system where better
crypt() is not available, new password will use salted hashing algorithm.
Posted it on SugarCRM's site:
https://developer.sugarcrm.com/2012/05/16/new-for-sugar-6-5-stronger-password-storage-encryption/
It turns out that SuiteCRM uses this new password format too, but, as well, it still recognizes md5 passwords, so, same sql statement works:
UPDATE users SET user_hash = MD5('PASSWORD') WHERE user_name = 'USERNAME';
I did it and it works :)
Btw, same post recommends change passwords with PHP crypt like this:
crypt(md5("newpassword"))
Maybe it can help someone else.

Enable password hashing in OpenLDAP

How to enable password hashing in OpenLDAP?
It seems that OpenLDAP has password-hash set to {SSHA} by default, but whenever I enter a cleartext password in userPassword attribute using Apache Directory Studio, it is still stored in clear text. I was expecting it to be converted to SSHA by OpenLDAP.
I also tried to put password-hash {SSHA} in slapd.conf file, but that didn't help.
When you tried to store userPassword attribute in add/modify LDAP operations, userPassword value is stored as plain text. But you can override this behavior using ppolicy_hash_cleartext option in ppolicy overlay module in OpenLDAP. Once you enable it, when client sends a plain text password, it is stored as SSHA by default. You can find configuration details on enabling hash password in OpenLADP from here
When you set the attribute directly, you are setting the actual value, which can be hashed or not (as you have already discovered).
The following, quoted from The FAQ:
First of all, make use of the 'slappasswd' utility to generate a password, so you can check if your PHP routines are correct. (The slappasswd utility is part of the openldap distribution).
The command
slappasswd -h {SHA} -s supersecretpassword
may help.

Verifying user's credentials with LDAP using Net::LDAP

I have an username and password and I need to verify that the username and password is found in the LDAP before letting the user into my system. I'm a newbie in LDAP and was quite confused about some terms. I know I need to bind the admin user and perform a search to check if I can find the username and password in LDAP. Then I should bind the user with the username and password.
Firstly, I don't quite understand why I need to bind the username and password at the last step.
Secondly, how do I bind the admin user? I know it should be in this format
bind("DN, OU and stuff",password=>$password)
What is the $password that I am suppose to pass?
Many thanks for your help!
The LDAP protocol is based on a request-response framework, with the exception of the unsolicited notification. The LDAP client transmits a correctly formed request to the LDAP server and then reads the response.
When an LDAP client connects to the server, the connection is not authenticated. In order to change the authentication state of a connection, the LDAP client transmits a "BIND" request to the server. A "BIND" request is either:
a simple BIND (distinguished name and credentials (password))
a SASL BIND (distinguished name or user name transmitted with other information, depending on the SASL mechanism
The server then determines whether the credentials are correct, and if they are, then the server changes the authentication state of the connection to that of the username or distinguished name and transmits a BIND response to the LDAP client. If the result code in the BIND response is 0 then the LDAP client knows that the user or distinguished name exists and the credentials are correct - there is no need to search for the user if the base object is already known.
If the connection already exists (for example, if connection pooling is used), then the client can request information about the authentication state of the connection using the authorization identity request control or the who am i? extended request. Some directory servers also support the account usable request control (which is not specified in any standards documentation but was invented by Sun Microsystems).
The base DN is the distinguished name from which a search "starts", that is, the search response would include the base DN and entries one level below the base DN if the search scope were one and all entries below the base DN if the search scope was sub or whole subtree.
Binding as the admin gives you access to search for the user. Binding as the user ensures that the password is correct.
1/ do an anonymous search if possible to lookup the dn
2/ do a bind test to verify the password
Just give you some idea, you need to fix some of the code below to match your case.
#!/usr/bin/perl
use Net::LDAP;
my $ldap = Net::LDAP->new($hostname, version => 2);
$mesg = $ldap->search(
base => $baseDN,
filter => "uid=$username",
attrs => ['dn']
);
$result = (1==0);
if ($mesg->code) {
foreach $entry ($mesg->entries) {
$dn = $entry->dn;
$bmesg = $ldap->bind($dn, $password);
$result = $bmesg->code
}
}
if ($result) {
print "Authenticated";
}
While the Perl example provided by Ken will work, its technically not the right approach. Searching is completely different versus a simple credential verification. While I won't go into the "why" on this remark, just understand that searching can behave in a misleading way, depending on how the server is configured.
As Terry mentioned, one method is the WhoAmI operation. Here's a CPAN page on the subject:
http://search.cpan.org/~marschap/perl-ldap-0.56/lib/Net/LDAP/Extension/WhoAmI.pm
As you can see, the WhoAmI operation is pretty simple when compared to a search. Only a username and password (of some kind) are needed. No filters nor search attributes are needed (nor accepted).
Basically, in laymen's terms, the WhoAmI operation would work like this (conversationally):
Client: "My name is [[insert DN here]], and my password is [[insert password here]]. Am I valid?"
Server: [[insert 'yes' or 'no' answer here]]
I hope this helps...
Max