Hash password before validate with LDAP - c#

I have a web-based-tool. On the login-form, the password will hashed before sending it.
All fine, the database stores only hashed passwords.
Now, we want a login with LDAP over DirectoryEntry.
But the constructor only accepts plain passwords.
My question: How can I pass hashed passwords to DirectoryEntry-class?
Current method:
public bool isAuthenticated(string domain, string username, string pwd)
{
string domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
try
{
Object obj = entry.NativeObject;
return true;
}
catch
{
return false;
}
}

I do not know C#, but as far as LDAP protocol goes, there is no way to authenticate with an already hashed password.
Why do you need to hash the password before transmitting it?
If it is to avoid transmitting it over the network, the easiest solution to use would be to connect to the LDAP directory over SSL.
As a side note, IMO, transmitting the hashed password is less secure than the clear one :
If the attacker intercept the request, he will be able to authenticate with the data he found either way
If the attacker succeed in dumping the database and retrieve the hashed password, if all he needs to do is to transmit that to authenticate, it renders the fact to store hashed the password useless
Edit : Additionnal information
I don't know which LDAP directory you use, but on OpenLDAP, you could implement this kind of mechanism if you don't use the bind operation (for example, you won't be able to use the password policy overlay).
You can implement a SASL Proxy Authorization to :
connect to the directory with a technical account
search and retrieve the entry user which tries to login
test on the custom hashed password attribute if the hashed provided is the stored one
rebind with another technical account with a proxy authorization to act as this user
It will allows you to still benefit from the ACL mechanism and logging system for users operations performed
BUT: This will be available only on OpenLDAP (or if another LDAP implemenation offer the same mechanism) and it is not really the most state of the art about the LDAP protocol ;)

Related

How do I store or associate additional data with a PasswordCredential?

My UWP application logs into several web services using several accounts. Each one contains an URL, password and username along with additional information such as a developer key, etc. I would like to securely store them as roaming settings assigned to a Windows user account.
UWP's Credential Locker appears to securely store the credentials part, the user name and password. It also roams with the user and I can live with its 10 credential storage limitation (Credential Locker) Unfortunately, there doesn't seem to be a clear way of including or associating it with my accounts using a unique ID:
//
//Add a credential to PasswordVault by supplying resource, username, and password
//
Windows.Security.Credentials.PasswordVault vault = new Windows.Security.Credentials.PasswordVault();
PasswordCredential cred = new PasswordCredential(InputResourceValue.Text, InputUserNameValue.Text, InputPasswordValue.Password);
vault.Add(cred);
PasswordVault requires a username, resource string and password. Although I can retrieve a credential using a username, its not guaranteed to be unique. Although the resource key is unique, it's not clear whether it identifies the actual credential or its container.
Any ideas on how to resolve this?
Different apps use different approaches for this. Some apps have a single resource name like AppName and then use UserName to store different kinds of "keys", so they have AccessKey, Password etc.
An alternative is to have different Resource values, for example for different authentication providers like AppName.Facebook, AppName.Local etc., use UserName for, well user name and password for password or access token.
Finally - because you are not limited by the kind of string you store in the Password, you can create a complex type that contains multiple properties and for example serialize it with JSON before storing into password vault. This way you can store more information with a single entry.

How to store Encrypted Password in cookies in C#?

I want to store username and password in cookies.
I encrypted password by using MD5 Hashing technique.
so how can i store that encrypted password in cookies??
Thats not the way. You put some parameters such as timestamp, user agent, current ip, username, etc. But not the Password. Now compute hash for your token and send it as a cookie. Thats how an authentication token is made.
For authenticating the user on Log in, compute the hash on your server and compare it with the one in DB. Don't ever send your hashed password on line. For better criteria you should use salted hash for passwords. See this to get to know about salts.
Moreover MD5 is hashing not an encryption. There is a lot of difference between both of them. Also, use SHA instead of MD5. See this for details.
You shouldn't store username and password in the cookies because that's sent to the client. Even if it's hashed, specially if you are going to compare the hashed password received in the cookie with the one in the database directly. That breaks the purpose of hashing.
If you want to mantain the session of the user between requests, you should use the session ID. I'm not a C# expert, but with a quick google I've found this:
HttpContext.Current.Session.SessionID
That's what I would store in the cookie.
I would not recommend this to anyone...
Rather save get the passwords from the user. save them in a session to use through out the users connection period and if you want the user to use that same password and login later you will have to have a database that you store the data in.
So to store the information as follow
Session["username"] = txtusername.Text;
then to use it again on a different page or somewhere else
string username = Session["username"].toString();

Authenticaion, hash, salt, https process?

Hi I think I may have done this the wrong way round can anyone help explain how you hash/salt a password. Do you do it from the client or the webservice?
I have a datacontract which has a password datamember, in my service I do this to create a hash/salt of the password before it is saved:
So here is the process in which I was thinking.
Rest Service has https for secure connection
User creates account (along with password)
//to stop packet sniffing when user creates account https is used during POST so no one can see the password?
web service then creates a hash of the password to store it
//so if anyone did get access to the service/database they couldnt make much use of the data in terms of breaching accounts
Then some means to authenticate that user there after
Is this correct?
Sounds like you're on the right track. Hashing along with the salt value should never occur on client side, as attackers will have access to that code. And https would indeed secure the connection, disallowing others from reading the data.
During authentication you do the same thing: take the password the user entered via https, hash/salt that value, then compare the result hash with the value in the database. And of course if you ever return a Student object to the client, it should contain neither of the values.
It may be wise not to reuse the Password property of Student since now you can't tell whether it contains the plain password or the hashed value.

Storing a password in an encrypted cookie?

I know it is not best practice to store a password in a cookie, even if the data is encrypted.
However, I have a web application that needs to be able to search against Active Directory and, as far as I can tell, it requires that the user first binds using their credentials. This means that for each search request, I need to pass the user name and password to the DirectoryEntry constructor.
Given these constraints, is there an alternaive to storing the password in a (secure) cookie?
In absence of something better (e.g. getting a service account), the solution that I'm contemplating is either to store the credentials in an encrypted cookie or cache the DirectorySearcher object.
Thanks
You could store the credentials server-side, generate a unique identifier for them, and store this identifier in a cookie. You can make the identifier expire if needed.
Store the password in a Session Variable, this variable will expires if alive beyond the SessionTimeOut period.

Secure password solution for a web service authenticating against Active Directory?

An application I'm modifying has a Web Service, and one of the web methods on that web methods is used to authenticate a user against active directory. So the current code called by the AuthenticateUser web method looks something like this:
string domainAndUsername = aDomain + #"\\" + username;
string ldsPath = buildLdsPath(searchBase);
DirectoryEntry entry = new DirectoryEntry(ldsPath, domainAndUsername,
password);
try
{
//Bind to the native AdsObject to force authentication.
object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(sAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
// more code to validate the result, etc...
}
When I started looking at this code, the first thing that worried me is the arguments to the web method look like this:
[WebMethod]
public ResultObj AddRole(string roleToAdd, string username, string password)
{
// code that calls above Authentication fragment...
}
So the current web service is expecting a password string, presumably sent in the clear over the network as XML, when the request is made to the service.asmx page.
Has anyone dealt with this type of issue before? Are there alternative Active Directory authentication mechanisms I could use that would avoid having to pass in a plain-text password? The best option I could come up with on my own is to invoke the WebMethod using an encrypted password, and have the code on the other side decrypt it. However, I'd prefer a better solution--e.g.: is there some way to do search for a DirectoryEntry using a one-way hash instead of a password?
Edit:
Additional Details: To this point I haven't considered SSL as this is a tool that is internal to our company, so it seems like overkill, and possibly problematic (it'll be running on a company intranet, and not externally visible). The only reason I'm even worried about the security of sending plain-text passwords is the escalating amount of (possibly password-sniffing) malware present even on company intranets these days.
If you have a public/private key combination, then the client could encrypt with the public key, and you decrypt with the private key.
However, that's too much work for the client, and not a very "web method" way of doing it.
Since you are sending the user name and password as parameters then you should resort to transport security, HTTPS, basically, which requires you to have a public/private key combination issued to you from a trusted certificate authority.
It should be noted that your association of SSL encrypted channel with an external facing site is incorrect. The point of wanting to encrypt a channel is to prevent man-in-the-middle attacks, exactly like you are trying to do here.
You could use a self-issued certificate, but that would require installing the public key of the certificate on each machine that is going to call your web method. It's easier to just get one from a trusted authority.
HTTPS (as mentioned) is the easy choice. Or, you could just let IIS handle authentication thru Digest or NTLM. Your app can still make authorization rules. NTLM is secure, but it'll hurt your interop. Otherwise, AD does offer some digest authentication methods, but I don't have tested code using them.
With Server 2000 domains, there's an option for "Store passwords in reversible format" - that will allow a domain controller to calculate MD5 hashes of the password to compare against your presented MD5 hash. MS realized this was a bit of a security problem, though, so Server 2003 implemented "Advanced" digest authentication - which precomputes the hash.
LDAP signon should select MD5 Digest as the authentication type, supply the username, and then supply the MD5 hash of the password. The normal LDAP clients will probably want to MD5 your password themselves though, so you'll have to override or craft them yourself.
We put our AD service on its own web site and got an SSL cert. Problem solved.
I think SSL, or possibly IPSec, are probably your best solutions.
For our particular situation, because both the client and the web service are running on our company Intranet, a solution that may work for us is to handle the Authentication on the client end using the Integrated Windows NTLM authentication, and then then just have the client supply the credentials to the Web Service. Here is the client code:
public void AddRole(string roleName)
{
webSvc.Credentials = CredentialCache.DefaultCredentials;
// Invoke the WebMethod
webSvc.AddRole(roleName);
}
The web method will now look like this:
[WebMethod]
public ResultObj AddRole(string roleToAdd)
{
IIdentity identity = Thread.CurrentPrincipal.Identity;
if (!identity.IsAuthenticated)
{
throw new UnauthorizedAccessException(
ConfigurationManager.AppSettings["NotAuthorizedErrorMsg"]);
}
// Remaining code to add role....
}
Again, I must stress this solution will probably only work if the server trusts the client, and both talk to the same Active Directory server. For public Web Services, one of the other answers given is going to be a better solution.
For further information, see:
Microsoft Support Article on passing credentials
MSDN Article on Building Secure Applications
MSDN Article on Windows Authentication - includes info on correctly configuring the web service to use the Windows Principal and Identity objects needed.

Categories