views:

286

answers:

6

I am developing an Asp.NET site for a customer, and want to make sure I am using a secure authentication scheme.

In my user table, I have an authentication hash column that is calculated as sha1(salt + username + password). The site is being served via HTTPS. To log in, the user submits their name and password via HTTPS. The web server calculates the hash, and compares it to the database stored value to authenticate.

Does this sound reasonably secure? I ran this scheme past a friend of mine, and he said it was vulnerable to nefarious sys-admins. He said I should do the following:

  • Server specifies a unique salt every time the login page is served.
  • Hash the password the unique salt on the client via javascript before submission.
  • Send this hash to authenticate, but not the password.
  • Do some fancy crap that I don't understand to authenticate the hash.

What should I do?

+8  A: 

Don't reinvent the wheel, just use .Net Membership.

mdresser
I was previously involved in a project that used this. I remember there being something about it that made me avoid this solution. But I can't remember what it was. Something about it being too inflexible.But reading your link suggests my information is incorrect. :)
recursive
+2  A: 

If you change the salt with every login page served, how can you compare it to what is in the database that is hashed with a different salt?

Your under SSL so you could send the credentials free text since the line is encrypted already and then apply the rules to salt/hash your password for comparing server side. This way no one knows how you are encrypting your password. Storing the informtion in your client side javascript is just giving that information away.

Other than that, your approach looks correct. I am assuming you need a custom solution and not a built in one for whatever reason.

Kelsey
Am guessing his salt would be stored in a separate column. Otherwise it'd be pretty tricky to re-validate.
davewasthere
+3  A: 

Read this:
Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes

What have we learned?
...If it’s 2007, and rainbow table attacks set you on fire, we learned that you should go back to 1975 and wait 30 years before trying to design a password hashing scheme.
...we should be consulting our friends and neighbors in the security field for help with our password schemes.
...in a password hashing scheme, speed is the enemy. We learned that MD5 was designed for speed. So, we learned that MD5 is the enemy.
...if we want to store passwords securely we have three reasonable options: PHK’s MD5 scheme, Provos-Maziere’s Bcrypt scheme, and SRP. We learned that the correct choice is Bcrypt.

The key points here:

  • Whatever you do, don't try to build your own authentication code from scratch
  • Bcrypt is your best choice for hashing the password.
Joel Coehoorn
Well it's a good article until I saw this - "You can use a challenge-response scheme, where both sides use a math problem to prove to each other that they know the password, but neither side sends the password over the wire. These schemes are great, but they don’t work unless both sides have access to the cleartext password —- in other words, the server has to store them in the clear." He's absolutely dead wrong here. Challenge/response systems do not require the server to store the password in the clear.
Spencer Ruport
+4  A: 

Firstly, if users are connecting via HTTPS, then there shouldn't be an issue with sending the password to the server over the network.

Otherwise, ensure that your salt is long and uses decent entropy for randomness. Also ensure that you use SHA-2 rather than SHA-1 since SHA-1 is considered broken.

Eric Smith
+2  A: 

Your friend is correct in asserting the salt should be unique however he's wrong with regards to handling the salt.

  • Hash the password the unique salt on the client via javascript before submission.

That requires you to either use the same salt for everyone or know who the user is so you can send them their unique salt. The salt should never leave the server.

CptSkippy
It's not supposed to be a per-user salt. It's supposed to be unique every single time.
recursive
@recursive : How would a user ever be authenticated if the salt is different every time? If the username/password/salt aren't exactly the same for a user then the hash will never match what is stored in the database.
CptSkippy
+4  A: 

Does this sound reasonably secure? I ran this scheme past a friend of mine, and he said it was vulnerable to nefarious sys-admins.

It's always a little dangerous to send out a password directly. Even if you're using SSL. If this is what he's referring to then he's kind of right. I wouldn't say it's vulnerable, just not the safest approach.

  • Server specifies a unique salt every time the login page is served.
  • Hash the password the unique salt on the client via javascript before submission.
  • Send this hash to authenticate, but not the password.
  • Do some fancy crap that I don't understand to authenticate the hash.

It sounds like he's suggesting a challenge-response scheme in conjunction with SSL. This is a good approach but let me explain it step by step to be clear.

Upon registration, the password is sent across ssl to the server. This should be the only time the password is sent directly. The server generates a salt and stores the following hash:

hash = sha1(password + salt)

The server should also store the salt.

When the client visits a log in page, the server should generate a record in a table with an ID and a challenge value. The server should then send the ID, the stored salt and the challenge value to the client.

When the client is ready to log in, you should have a javascript function generate a challenge as well as a hash like so:

hash = sha1(sha1(password + server_salt) + server_challenge + client_challenge)

The client should then submit the hash, the server_saltid and the client_challenge values. The server then calculates a hash like so:

hash = sha1(stored_hash + server_challenge + client_challenge)

If the hashes match the user is authenticated, in either case, the challenge record should be deleted.

Spencer Ruport