The inner workings of the undocumented pwdencrypt() hash function in Microsoft SQL Server have been revealed in a paper by security researcher David Litchfield of Next Generation Security Software (NGSS).
pwdencrypt() creates the user's password hash, which is stored in the main database. Litchfield begins by observing that when it's applied to the same input (foo), it will produce different hashes at different times, from which he reckons, assuming the worst, that the salt must be time sensitive in some way. Salting is normally done to prevent collisions and to strengthen hashes against dictionary attacks.
In other words, if a hash weren't salted, it would be easy to encrypt dictionary words using numerous hash functions and run the hashes against ones found in someone else's pass file. Obviously, the less we can determine about how the salt is generated, the stronger the hash becomes.
Unfortunately, we now know from Litchfield's simple experiment that SQL Server is using some manner of time-dependent scheme for salt generation. That's more than we ought to know, as we'll see.
His next observation is that the time function does not result in a truly random number, which is further bad news.
"The time () C function is called and used as a seed passed to the srand() function. srand() sets a start point to be used for producing a series of (pseudo) random numbers. Once srand is seeded the rand() function is called to produce a pseudo random number. This number is an integer; however SQL Server converts this to a short and sets it aside. Let's call this number SN1. The rand() function is called again producing another pseudo random integer which, again, is converted into a short. Let's call this number SN2. SN1 and SN2 are joined to produce an integer SN1:SN2 to produce a salt. This salt is then used to obscure the password."
The user's password is converted to unicode with the salt tacked on the end, and this is used to produce a hash with SHA. The same salt is added to the password when a user attempts to log in, and the resulting hash is compared to the one on record. If they match, access is granted.
Unfortunately, Litchfield says, "the password is then converted to its upper case form, the [same] salt tacked onto the end and another SHA hash is produced."
The hash is produced twice, against the case-sensitive password and again against the uppercase form. The uppercase 'version' is obviously a good deal easier to crack; and once we know it, finding the case-sensitive version is child's play. Indeed, there's little point in using case-sensitive passwords on your system if the crypto scheme is going to create hashes from the uppercase version, using the same salt, and then store them. Case-sensitive passwords are an improvement only so long as we're kept in the dark about their uppercase companions.
So with that in mind Litchfield ends his paper with a little command-line app which will run a dictionary attack to find the uppercase password for you. The rest of it, any fool can handle.
Thus security through obscurity fails again. ®