| By Patrick Hynds | Article Rating: |
|
| December 10, 2003 12:00 AM EST | Reads: |
17,753 |
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
What if a hacker (or an internal malcontent, for that matter) gained access to your user login information? Suppose for purposes of this conversation that you have an ASP.NET application that leverages your own authentication database via SQL Server. This is a very common scenario, and Forms Authentication is a favorite authentication method for this situation (for good reason). So you have your Login table, which contains username and password information. If a hacker could get to this data even just to read it, you would have a disaster on your hands. With this data he or she can now log in as anyone in your system and, worse, if they get write access they can create their own backdoor account, which is unlikely to be detected - and no one will be changing the password anytime soon.
On to the Technology!
Now take the aforementioned scenario and suppose you could at least prevent the database from containing the passwords in a usable form. This is the essence of the defense. While we still don't want the hacker to get into our database, our first concern is that they should not be able to log in or successfully plant a record in our user table.
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
For better illustration, in Listing 1 we have opted to not import the System.Security and other namespaces so that those are less familiar with it will easily see the lineage of all the objects.
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
' System.Text.Encoding
Dim PWDArray() As Byte = Encod
ing.Unicode.GetBytes(strPassword)
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
Dim SaltArray() As Byte = Convert.FromBase64String(strSalt)
Dim HashArray() As Byte = Convert.FromBase64String(strHash)
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
' .Cryptography.SHA1
Dim HashResult As HashAlgorithm = SHA1.Create()
' CryptoStream from
' System.Security
' .Cryptography.CryptoStream
Dim csRecreateHash As CryptoStream
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
' with the salt we stored
csRecreateHash = New CryptoStream(Stream.Null, HashResult,
CryptoStreamMode.Write)
csRecreateHash.Write(PWDArray, 0, PWDArray.Length)
csRecreateHash.Write(SaltArray, 0, SaltArray.Length)
csRecreateHash.FlushFinalBlock()
csRecreateHash.Close()
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
' with the one stored in the
' database
bValidUser = CompareAr
rays(HashRecalculated, HashArray)
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
Even with this code, you still have a long way to go to be secure. But as you build your bag of tricks, it is hard to truly be fully secure without a little random salt in your application.
Resources
Published December 10, 2003 Reads 17,753
Copyright © 2003 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Patrick Hynds
Patrick Hynds, MCSD, MCSE+I, MCDBA, MCSA, MCP+Site Builder, MCT, is the Microsoft Regional Director for Boston, the CTO of CriticalSites, and has been recognized as a leader in the technology field. An expert on Microsoft technology (with, at last count, 55 Microsoft certifications) and experienced with other technologies as well (WebSphere, Sybase, Perl, Java, Unix, Netware, C++, etc.), Patrick previously taught freelance software development and network architecture. Prior to joining CriticalSites, he was a successful contractor who enjoyed mastering difficult troubleshooting assignments. A graduate of West Point and a Gulf War veteran, Patrick brings an uncommon level of dedication to his leadership role at CriticalSites. He has experience in addressing business challenges with blended IT solutions involving leading-edge database, Web, and hardware systems. In spite of the demands of his management role at CriticalSites, Patrick stays technical and in the trenches, acting as project manager and/or developer/engineer on selected projects throughout the year.
- Kindle 2 vs Nook
- Confessions of a Ulitzer Addict
- IBM Hardware Chief, Intel VC Exec Arrested in Insider Trading Scam
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Infrastructure-as-a-Service Will Mature in 2010: Microsoft's David Chou
- Windows 7 – Microsoft’s First Step to the Cloud
- Cloud Expo and the End of Tech Recession
- Jill Tummler Singer, Deputy CIO of CIA, Keynotes at GovIT Expo
- Reality Check at the Cloud Computing Expo
- Visual Studio 2010 Is Cloud Friendly
- Fired SCO CEO Fires Back
- Kindle 2 vs Nook
- The Difference Between Web Hosting and Cloud Computing
- Ajax in RichFaces 3.3, JSF 2 and RichFaces 4
- Confessions of a Ulitzer Addict
- Wave on Ulitzer: Confessions of a Google Wave Fanboy
- IBM Hardware Chief, Intel VC Exec Arrested in Insider Trading Scam
- Cloud Computing Best Practices
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Infrastructure-as-a-Service Will Mature in 2010: Microsoft's David Chou
- Eval JavaScript in a Global Context
- Windows 7 – Microsoft’s First Step to the Cloud
- Google Maps and ASP.NET
- Crystal Reports XI & How It Has Changed
- Converting VB6 to VB.NET, Part I
- Creating Controls for.NET Compact Framework in Visual Studio 2005
- Where Are RIA Technologies Headed in 2008?
- How to Write High-Performance C# Code
- AJAX World RIA Conference & Expo Kicks Off in New York City
- Implementing Tab Navigation with ASP.NET 2.0
- i-Technology Photo Exclusive: Bill Gates & Steve Jobs In "Nerds"
- .NET Archives: Getting Reacquainted with the Father of C#
- i-Technology Viewpoint: "SOA Sucks"
- Programmatically Posting Data to ASP .NET Web Applications






























