0

Hi I have a program where I request a username and password from a user through WPF, I then send the data to a database where it is stored.

 private void btnRegister_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                using (SqlConnection connection = new SqlConnection(ConnectionSQL.conn))
                {
                    SqlCommand command = new SqlCommand("INSERT INTO USERTABLE " +
                                                        "VALUES(@Username, @Password);" +
                                                        "Select SCOPE_IDENTITY();", connection);
                    command.Parameters.AddWithValue("@Username", txtbUsername.Text);
                    command.Parameters.AddWithValue("@Password", Utils.hashPassword(txtbPassword.Text));
                    connection.Open();

                    SqlDataAdapter adapter = new SqlDataAdapter();
                    adapter.InsertCommand = command;

                    int id = Convert.ToInt32(adapter.InsertCommand.ExecuteScalar());
                    MessageBox.Show("User Registered! User has been added to the database: " + id);
                    adapter.Dispose();

                    String Username = txtbUsername.Text;
                    String Password = txtbPassword.Text;
                    Users temp = new Users(id, Username, Password);

                    Login L = new Login();
                    arrUsers.Add(temp);
                    Hide();
                    L.ShowDialog();
                    
                }
            }
            catch (SqlException ex)
            {
                MessageBox.Show("Error Connecting to the Database", "Connection Error" + ex.ToString());
            }

        }

I created a function to store the password as a hash in the database.

 public class Utils
    {
        public static string hashPassword(String password)
        {
            SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();

            byte[] password_bytes = Encoding.ASCII.GetBytes(password);
            byte[] encrypted_bytes = sha1.ComputeHash(password_bytes);
            return Convert.ToBase64String(encrypted_bytes);


        }
    }

When I try log in and validate password when its stored as a hash it doesnt work.

 private void btnLogin_Click(object sender, RoutedEventArgs e)
       {
           try
           { 
               using (SqlConnection connection = new SqlConnection(ConnectionSQL.conn))
               {
                   connection.Open();
                   String Username = Convert.ToString(txtbUsername.Text);
                   String Password = Convert.ToString(txtbPassword.Text);

                   String sql = "SELECT * FROM USERTABLE where Username = '" + Username + "' " +
                       "AND Password = '" + Password + "' ;";
                   SqlCommand command = new SqlCommand(sql, connection);
                   SqlDataReader reader = command.ExecuteReader();
                   if (reader.HasRows)
                   {
                       MessageBox.Show("You Have Successfully Logged In");
                       MainWindow Main = new MainWindow();
                       txtbUsername.Text = "";
                       txtbPassword.Text = "";
                       this.Hide();
                       Main.ShowDialog();
                       this.Show();
                   }
                   else
                   {
                       MessageBox.Show("Invalid Credentials");
                   }
                   reader.Close();
                   command.Dispose();
               }
           }
           catch (SqlException ex)
           {
               Console.WriteLine(ex.ToString());
           }
           Console.ReadLine();
       }

Although when i dont hash the password in the database it works. Any tips on solving this?

  • How are you trying to validate the password? This looks like the code for *creating* the user, not for *logging in* the user. – David Oct 26 '21 at 16:43
  • Please show the code where you are validating the password. – derpirscher Oct 26 '21 at 16:46
  • 4
    Note that storing passwords is a *hard problem* and you should almost always rely on an existing framework that does all of this for you. For example here you are not salting your hashes. – DavidG Oct 26 '21 at 16:48
  • I added the code where im trying to validate it says invalid when i store the passwords as hashes – Sebastian Marshall Oct 26 '21 at 16:50
  • 1
    @SebastianMarshall: At a glance it looks like you simply forgot to hash the password before comparing...? – David Oct 26 '21 at 16:52
  • 5
    You are not hashing the password on login. And you should use parameterized queries also for login (like you do at creating the user) – derpirscher Oct 26 '21 at 16:53
  • 1
    You really should consider what DavidG is saying. Try taking a look at this: https://stackoverflow.com/questions/2005054/how-to-salt-and-hash-a-password-value-using-c – jimnkey Oct 26 '21 at 16:54
  • 2
    You've written a client side app where the client is accessing your DB directly. You've already lost. Anyone can just extract the DB credentials from the codebase or sniffing network traffic and do whatever they want to your DB. They can wipe everything, read other people's info, insert their own highly privileged accounts, or whatever else they want. You need to have an API sitting in between the client app and your DB. All the other problems about salting, or parameterizing queries pales in comparison. – Servy Oct 26 '21 at 16:55

1 Answers1

1

You don't compare a non hashed password with a hashed password. When getting the password from the client, you need to hash that password again, and then match the hashed values. If they match, it should return success.

Updating this should resolve it:

String Password = Convert.ToString(Utils.hashPassword(txtbPassword.Text));

But there are a lot more glaring issues here that you will need to address:

Firstly: You need to use SqlParameter to add values to your WHERE clause instead of adding the values directly into your SQL command. This is to avoid SQL Injection.

Secondly: Split your data access layer away from your application. This is a great risk if the code accessing your database is available to the client.

There are some other things I would change. But these should be good starting points.

Marius
  • 1,420
  • 1
  • 11
  • 19