|
|
YOUR FEEDBACK
|
TOP MICROSOFT .NET LINKS .NET Security
Random Salt - Preparing for real-world eventualities
By: Patrick Hynds
Digg This!
It's a constant battle! Just when you think you understand security, someone or something reminds you of a whole aspect that you have been ignoring, usually at your peril. No matter how much you planned, prepared, worked, and worried about your plan of attack or defensive position, the job was literally never done! You had to settle for trying to be better prepared than the enemy - as opposed to being prepared for all things at all times. Computer system security has reached this point in the minds of many in the industry. To quote one of our favorite speakers, Ted Neward, "It isn't about how wide or high the walls are anymore; you have to have the troops at the top throwing rocks and pouring hot oil down to stop the bad guys." What can we do about it in the real world? To that end we wish to share a technique that acknowledges that we might be better off planning for the when of intrusion, rather than only the preventative aspects. The technique we're getting to is called "random salt" in some circles, and was well demoed by Microsoft's Erik Olson at Tech-Ed in Dallas this year. While we at CriticalSites have known about this technique (and used it) for a while, noticing Erik's incorporation reminded us of how rarely it is implemented. Many people dislike the very idea because they feel it admits defeat. While we sympathize with this view, we also know that sometimes you get outmatched - and you have to have a plan to deal with that eventuality. The alternative is to surrender - and that is the real admission of defeat.
The Hypothetical Situation
On to the Technology! The .NET namespace includes a nice neighborhood known as System.Security.Cryptography that contains all we need to make this happen. When we create an account for our hypothetical situation we will take a couple of preparation steps to make it work. First we create a random string that we will refer to as the "salt." This value is never reused from user to user and can be generated when needed. The salt is combined with the password assigned to/chosen by the user to form a new string. The more convoluted the combination, the better. The resulting combined string is then hashed using SHA1 or MD5, and saved to the database along with the salt. This means that any number of users could have the same password and yet the salt and hash values stored in the database by definition will not be the same. The process of authentication is to take the password provided by the user (hopefully over SSL or some other secure channel), combine it with the salt, and hash it. The resulting hash is compared to the saved hash and if they match, then the password provided by this user is the same as the password used to create the account.
Let's Look at Some Code Let's look at that code a little at a time and put it in context. If you are familiar with Forms Authentication, then you already have most of the picture. You set up your Web.Config for Forms Authentication and build your login form (i.e., login.aspx). Normally you would put some database lookup logic in the submit button's click event to retrieve the username and password to compare with what the user provided. If they match, then you are in clover - the cookie gets issued and, if you did it correctly, the user is redirected to the original requested page. The twist here is the password-compare thing. We don't want to store the password in the database. We still need to use SSL for the login.aspx page since the password is being passed (just not stored). Okay, given that lead-in, let's examine some code. We start by creating our byte arrays to do our comparisons. We need one for the password sent by the user:
' Encoding is found in And one each for the salt and hash values we pull out of the database. These are stored in the same record as the username:
' Convert is from System.Convert SHA1 is a useful hash and my choice for this demo. The SHA1 object has a create method that returns a HashAlgorithm, which we will use directly as a parameter to the CryptoStream constructor:
' SHA1 from System.Security We use the CryptoStream object, csRecreateHash, to combine the password with the salt. This method must match the steps used to create the hash stored in the database when the account was created (or the last time the user password was changed):
' Hash the password we got back You might remember the HashResult from above. It was also one of those parameters from the CryptoStream constructor: Dim HashRecalculated() As Byte = HashResult.Hash Now we're back in the real world. Compare the hash from the database (HashArray) to the one we just recalculated (HashRecalculated). If they match, then the user is legit and should be given the nod:
' Compare the recalculated hash The rest you can wade through on your own; let the comments be your guide. What used to be a single line becomes a big lump, but a reusable lump. Take this technique and use it; we need all the help we can get to hold back the barbarians at the gates.
Conclusion
Resources MICROSOFT .NET LATEST STORIES
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK BREAKING NEWS FROM THE WIRES
|
||||||||||||||||||||||||||||||||||