Get unencrypted password from MembershipProvider - c#

I'd like to get user password unencrypted. How to get this?
public static string GetCurrentUserPassword(string userName)
{
MembershipProvider p = (MembershipProvider)Membership.Providers["Default"];
MembershipUser obj = Membership.GetUser(userName);
return obj.GetPassword();
}
obj type : [Telerik.Sitefinity.Security.Model.User] = User "user1", Id={59d9813c-f88e-4790-9f19-3145ba8347d1}, Provider="Default"
password : "+HmReh/mzvIIuvYsM7+XdEoeQhI="

Why would you expect to be able to get the unencrypted password?
The only think you should be able to do with a stored password is use it to check the validity of the password the user has entered. For one-way hashing (and similar techniques) that involves applying the same transformation to the just-entered password (using the same salt where appropriate), and seeing whether you end up with the same hash.
You should not be storing any representation of the password which is reversible. That would mean that if an attacker gained access to your database (and any private keys), they would have access to your user's passwords directly - which is unacceptable, basically. (It wouldn't be so bad if everyone used a different password for each resource they protected, but many people don't.)

If the passwords are configured to be hashed and not encrypted, you can't do this. If you configure the membership provider to used encrypted passwords, then the GetPassword should do the trick. See PasswordFormat
That being said, I certainly can't disagree with Mr. Skeet's answer. You should really be using one-way hashed passwords if at all possible.
For dealing with forgotten password scenarios, take a look at ResetPassword.

The documentation for MembershipUser.GetPassword () says it all:
If EnablePasswordRetrieval is false, the membership provider will return an exception. If the provider supports passwords with a PasswordFormat of Hashed, you will be unable to retrieve the password for the membership user and should consider making use of the ResetPassword method when a user has forgotten his or her password.
I cannot think of any other way you would want to read the password .

Related

Hashing user password - Identity Server

I'm currently working with Identity Server 4, at present when the user logs in I need to hash their provided password and then compare with the password stored in the database (also hashed)
After some searching, I was linked to the PasswordHasher within Identity Server to handle this:
var _hasher = new PasswordHasher<User>();
var hashpassword = _hasher.HashPassword(user, context.Password);
User is my custom class that inherits from IdentityUser, however, when checking the hashed password against the one in the database the hash is completely different, I have double checked the password and I can confirm it's correct.
Can anyone suggest why I maybe seeing a different hash compared to the one in the database?
Each time you hash a password with PasswordHasher<T>.HashPassword you will get a total different result because of the salt.
To verify such hashed salted passwords use the given method IPasswordHasher<T>.VerifyPassword.

Flow of validating a user with hashed password?

I was reading this article about hashing passwords when I came to this part:
To Validate a Password
Retrieve the user's salt and hash from the database.
Prepend the salt to the given password and hash it using the same
hash function.
Compare the hash of the given password with the hash from the
database. If they match, the password is correct. Otherwise, the
password is incorrect.
But I am a little confused with the flow this would follow, for example lets assume I have a database with a user table with id,name,password and email and in order to login to some app I need to input my email and password.
Following the the steps above, I first need to get the salt+hashed password of said user stored in the database.
Question:
Assuming I am using a simple stored procedure would the only way be to do it like this...
CREATE PROCEDURE [dbo].[sp_validate_user]
#us_email VARCHAR (MAX)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT us_id,
us_name,
us_pass,
us_email
FROM Users
WHERE us_email = #us_email
END
Then following step two and three:
public static bool ValidatePassword(string inputPassword, string storedPassword)
{
// Extract the parameters from the hash
char[] delimiter = { ':' };
string[] split = storedPassword.Split(delimiter);
int iterations = Int32.Parse(split[ITERATION_INDEX]);
byte[] salt = Convert.FromBase64String(split[SALT_INDEX]);
byte[] hash = Convert.FromBase64String(split[PBKDF2_INDEX]);
byte[] testHash = PBKDF2(inputPassword, salt, iterations, hash.Length);
return SlowEquals(hash, testHash);
}
My concern comes from the fact that if I am creating objects with the data pulled from the table, doesn't that make the information within vulnerable somehow?
Also does that mean that the only way to use this validation is pulling all the user's information based only on a username/email just to check in runtime if the input password and the hashed one match and then letting said user access the information?
I'm sorry if this sounds confusing but any insight would be great.
It looks like you may be thinking of it backwards. The salt is added to the cleartext password before passing to the hash function. Store the end result in the database.
Commonly, the salt is the username. Something unique to each user to thwart dictionary attacks. (A dictionary attack relies on the economy of scale by cracking one password and then looking for other instances of the same crypto-text. It used to work especially well on very large user databases like well known sites that have millions of users, but hopefully those sites use proper salting and key derivation nowadays).
So for username u, password p, assume SHA2 is hash function. Concatenate u + p to get a salted value, then hash it.
hashtext = SHA2(u + p) // in this case, + is concatenate
hashtext is what you store in the database.
For the login, user enters his username u2 and password p2:
tryhash = SHA2(u2 + p2)
Query database for a user record matching u2, with password hashtext of tryhash
Lets say you have an MVC action receiving loginViewModel which is populated with cleartext email or username as well as cleartext password, entered from the page:
var loginUser = new User(loginViewModel);
CalcHash(loginUser);
var realUser = users.Find(loginUser.username);
if(realUser.HashPassword == loginUser.HashPassword)
// success
While it is also possible to add the hashed password as a second argument to your Data Access method, ie. users.Find(username, hashPass), it is usually not done this way, because you need to access the user record even if the password fails, in order to increment password failure count and lockout the account.
The article covers ASP.NET (C#) Password Hashing Code but you seem to want to use a database?
You have three things to worry about; the unique key for the user (username), your chosen hashing algorithm and adding a salt to the password attempt (prevents rainbow table attacks).
To validate a password you should create a sql stored procedure that accepts the username and password attempt as parameters. This data is in plain text and has been entered into the web form, passed to the web server and will be passed into the database server via the stored procedure.
The stored procedure will do the following;
Lookup the data row for user based on matching the username parameter with the username field and
select the stored salt field
Append the salt from (1) to the password parameter and hash the result
Lookup the data row for the user based on matching the username parameter with the username field
and the hash result from (2) with the hashed password field.
If there is no row found the password hashes don't match and are wrong so return a suitable error code
If there is a row found return the useful user data i.e. First Name, Address
If the stored procedure handles all this then the web server never needs to know what the salt is or the hashing algorithm. At no point does the hash result or the salt get transmitted out of the database server.
I think you understood it correctly, this is the usual workflow:
Get the password-hash by username SELECT password_hash FROM user WHERE email=?.
Extract the salt from the password_hash, or get the salt from a separate field.
Calculate the hash of the entered password with the extracted salt and compare the hashes.
Validating the password cannot be done in a single query, because you first have to extract the salt. Appropriate hash functions like PBKDF2, BCrypt or SCrypt are often not supported by the database system, so you have to do the validation in your code. Additionally to the salt you also have to store other parameters like the cost factor and the algorithm (to be future-proof), so it is a good idea to store all these parameters in the same database field.
The salt should be a random string of at least 20 characters, so it is not safe to use the username as salt, or to derrive the salt from other information.

ASP.NET Membership Provider - Expose the salt

Background
We are using the ASPNET membership provider that stores member login information, along with MongoDB to store a secondary set of information.
Because MongoDB does not offer built-in encryption we have decided to encrypt some of the data before inserting it into the database using the member's salt that is in the ASPNET membership provider tables.
Objective
How would I go about exposing the salt so that it is accessible in code? I cannot find any methods for this in the default provider classes.
Alternative
Either that or could anybody suggest a better approach? One of the benefits of having the salt saved in a different place is to protect it from "interlopers".
Thanks,
Max.
Here is one approach, you can use the username, e-mail to salt.
public static string hashCalculator(string username, string password)//Use username as salt.
{
byte[] stringbytes = System.Text.Encoding.Unicode.GetBytes(username.ToLower() + password);
return Convert.ToBase64String(new SHA384Managed().ComputeHash(stringbytes));
}

RavenDB Querying to check Username and Password

I'm fairly new to C# and RavenDB, so please excuse my lack of understanding.
I currently have a Windows Form Application. In one of the forms, I have two text boxes and one button. These two text boxes serve as the username and password inputs and the button is obviously there so that the user can login. When the user clicks on the button, a method is called and saves the content of the two inputs in two string variables.
At the moment, in my RavenDB Database, I have created two samples of username and password.
How do I appropriately check whether the username and password given from the user exists in the database.
Any help is really appreciated.
There are two ways to answer this question.
a) You can query for multiple properties using the Linq provider
session.Query<User>().Where(user=> user.Name = username && user.Password = pass).ToList();
b) The problem with this is that this assumes that you are storing the password as plain text in the database, which you should never do.
You can see how we implemented that in RaccoonBlog's RavenDB's sample application:
https://github.com/ayende/RaccoonBlog/blob/master/src/RaccoonBlog.Web/Models/User.cs
https://github.com/ayende/RaccoonBlog/blob/master/RaccoonBlog.Web/Areas/Admin/Controllers/LoginController.cs
As a matter of good security practice you don't store passwords at all, rather you you store the password's hash.
To store your password
Read the values on the server and generate a hashcode of the password. You should use crypto functions to generate hash (such as via SHA256)
Store a document in Raven DB of type User with his username and hashed password
To check if the user with the passed credentials is in the database
Query Raven DB and look for the user with the given name and password hash.
Sample code
var user = session.Query<User>()
.Where(u => u.UserName == "Alice" && u.HashedPassword == "hashPwd");

Trying to compare password history to hashed passwords created by SqlMembershipProvider

I am using a SqlMembershipProvider and storing my passwords as hashed. I am also keeping a history of the (hashed) passwords in another table. I want to be able to compare the password a user tries to change their password to, to their old passwords and throw an error if it was too recent. I do not seem to be able to figure out how to use the hashing functions to do this. Basically what I am looking for is a method like this:
public bool PasswordCompare(string plaintextPassword, string salt, string hashedPassword)
{
//where the salt and hashedPassword are pulled out of the aspnet_Membership table
//which are automatically generated by the provider
}
I hope this is clear, thank you.
This post has some good info. Looks like you have to:
...implement your own customized
MembershipProvider, record the
password history and encrypt the
password by your self.
SQLMembershipProvider: Comparing Hashed Passwords

Categories

Resources