通过忘记密码功能取消密码哈希

Unhash the password through forgot password feature

我的网站有散列密码功能,当用户注册时,密码会在数据库中散列。我还设法通过该散列密码登录。但是,我添加了忘记密码功能。它工作正常(将密码发送到用户电子邮件)但密码仍然被散列?有什么技巧可以分享吗?

这是我忘记密码的代码:

protected void SendEmail(object sender, EventArgs e)
    {
        string username = string.Empty;
        string password = string.Empty;
        string constr = ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ConnectionString;
        using (SqlConnection con = new SqlConnection(constr))
        {
            using (SqlCommand cmd = new SqlCommand("SELECT Username, [Password] FROM UserData WHERE Email = @Email"))
            {
                cmd.Parameters.AddWithValue("@Email", txtEmail.Text.Trim());
                cmd.Connection = con;
                con.Open();
                using (SqlDataReader sdr = cmd.ExecuteReader())
                {
                    if (sdr.Read())
                    {
                        username = sdr["Username"].ToString();
                        password = BusinessLayer.ShoppingCart.CreateSHAHash("Password").ToString();
                    }
                }
                con.Close();
            }
        }
        if (!string.IsNullOrEmpty(password))
        {
            MailMessage mm = new MailMessage("sender@gmail.com", txtEmail.Text.Trim());
            mm.Subject = "Password Recovery";
            mm.Body = string.Format("Hi {0},<br /><br />Your password is {1}.<br /><br />Thank You.<br/><br/>IslandGas Team", username, password);
            mm.IsBodyHtml = true;
            SmtpClient smtp = new SmtpClient();
            smtp.Host = "smtp.gmail.com";
            smtp.EnableSsl = true;
            NetworkCredential NetworkCred = new NetworkCredential();
            NetworkCred.UserName = ConfigurationManager.AppSettings["UserName"];
            NetworkCred.Password = ConfigurationManager.AppSettings["Password"];
            smtp.UseDefaultCredentials = true;
            smtp.Credentials = NetworkCred;
            smtp.Port = 587;
            smtp.Send(mm);
            lblMessage.ForeColor = Color.Green;
            lblMessage.Text = "Password has been sent to your email address.";
        }
        else
        {
            lblMessage.ForeColor = Color.Red;
            lblMessage.Text = "This email address does not match our records.";
        }
    }

我试着用这段代码让它工作:

using (SqlDataReader sdr = cmd.ExecuteReader())
                {
                    if (sdr.Read())
                    {
                        username = sdr["Username"].ToString();
                        password = BusinessLayer.ShoppingCart.CreateSHAHash("Password").ToString();
                    }
                }

但在电子邮件中,它仍然是散列的。

顺便说一句,这是我在业务层中的 hashpassword 代码:

public static string CreateSHAHash(string Phrase)
    {
        SHA512Managed HashTool = new SHA512Managed();
        Byte[] PhraseAsByte = System.Text.Encoding.UTF8.GetBytes(string.Concat(Phrase));
        Byte[] EncryptedBytes = HashTool.ComputeHash(PhraseAsByte);
        HashTool.Clear();
        return Convert.ToBase64String(EncryptedBytes);
    }

如果您将用户密码的哈希值保存在您的数据库中,则无法恢复密码的原始明文。这就是密码哈希函数的含义。这是一个单向函数。

相反,您必须在数据库中保存明文密码或密码的加密(非散列)值。

库戈登

将密码发回用户的能力首先破坏了散列密码的目的。这就是为什么所有具有适当安全设计的系统都允许用户更改密码,或提供提示以提醒他们密码,但从不明确恢复他们的旧密码。

I also managed to log in through that hashed password.

这也违背了散列的目的,因为获得对散列列表的访问权限为攻击者提供了一种在不知道密码的情况下进入系统 "legally" 的方法。此外,您的系统似乎使用“unsalted”密码来生成哈希,这是一个严重的安全问题。

its working fine (sending the password to the users email)

我真诚地希望您的网站是为了娱乐用户而构建的,不会为潜在的攻击者存储任何有价值的东西。在电子邮件中发送未加密的密码与在明信片上发送秘密是一样的。

any tricks that you can share [to unhash the password]

散列的主要目的是在不进行详尽搜索的情况下无法逆转。从正确构造的哈希中恢复密码需要暴力解决方案,即您的系统需要破解您的用户密码。

使用加密强度高的随机数生成器生成随机临时密码,并将该密码通过电子邮件发送给用户。将新密码设置为在几分钟内过期。让用户使用临时密码登录,然后要求他们立即更改密码。这样您就可以让用户通过电子邮件恢复密码,而不会过多地暴露他们。

正如 gordon 和 dasblinkenlight 已经提到的,重要的是要考虑,散列函数是 单向函数 并且设计为不可恢复. (并且对您存储的密码加盐也很重要!)

要为您的用户启用密码恢复功能,您应该遵循使丢失的密码可重置 的方法。简而言之,用户输入她的电子邮件地址,您的系统会向用户发送密码重置-link。当用户单击 link 时,她将能够设置新密码。

现有的解决方案可以促进这些行动。您可以以 this extensive ASP.NET identity sample 作为起点。