“Forms Authentication” by Meneer.Depuydt

We maken allemaal wel eens fouten, zo ook meneer.depuydt. Een tijdje terug bouwde ik een backoffice waarbij de beveiliging werd afgehandeld door middel van Forms Authentication. De theorie is leuk, bijna niets programmeren en alles wat je kan dromen op gebied van authenticatie en authorisatie is voorzien. Accounts bijmaken, wachtwoorden resetten, wachtwoorden wijzigen … In theorie fijn tot je net iets meer wil dan voorzien is. Een stukje bijbouwen is gekkenwerk als het al niet onmogelijk is.

Alleen idioten veranderen nooit van visie en daarom besliste ik Forms Authentication vaarwel te zeggen en de authenticatie terug zelf in handen te nemen maar wat te doen met de door de Forms Authentication gebouwde tabellen en de daarin zittende duizenden gebruikers?  Iedereen een mailtje sturen dat hun login veranderd is? Weinig professioneel…

Wat research leerde ons hoe de Forms Authentication tabellen in elkaar zaten. Elke gebruiker heeft naast zijn login een SALT waarde en een geëncrypteerd wachtwoord. We hoeven niet terug te kunnen keren naar het ongeencrypteerde wachtwoord (dat is trouwens onmogelijk) als we op basis van de SALT en het geëncrypteerde wachtwoord het door een gebruiker ingetikte wachtwoord kunnen verifiëren zijn we al lang blij.

En dat kan … met deze code.

 1: public string CheckPassword(string salt, string plaintext)
 2: {
 3:     byte[] un64basesalt = Convert.FromBase64String(salt);
 4:     byte[] un64plaintext = ASCIIEncoding.Unicode.GetBytes(plaintext);
 5:
 6:     int lengtesalt = un64basesalt.Length;
 7:     int lengteplain = un64plaintext.Length;
 8:
 9:     byte[] plainTextWithSaltBytes = new byte[lengtesalt+lengteplain];
 10:
 11:     for (int i = 0; i < un64basesalt.Length; i++)
 12:         plainTextWithSaltBytes[i] = un64basesalt[i];
 13:
 14:     for (int i = 0; i < un64plaintext.Length; i++)
 15:         plainTextWithSaltBytes[lengtesalt + i] = un64plaintext[i];
 16:
 17:     HashAlgorithm hash;
 18:     hash = new SHA1Managed();
 19:
 20:     byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes);
 21:     return Convert.ToBase64String(hashBytes);
 22: }

Een woordje uitleg. De Salt waarde die je in de DB aantreft is met BASE64 gecodeerd, je kan die makkelijk decoderen (regel 3).  Het plaintext wachtwoord ingetikt door een gebruiker zetten we net als de SALT om in een byte array (regel 4). Van beide zaken vragen we de lengte op (6+7).  Vervolgens kleven we de byte array van de salt en het plain text wachtwoord achter elkaar (eerste wachtwoord dan de salt) (11,12 + 14,15) en her resultaat daarvan gaan we ‘hashen’ met het SHA1 algoritme. (17).

Het bekomen resultaat kan vergeleken worden met de geencrypteerde waarde in de databank. Als die overeenstemmen is het wachtwoord van de gebuiker correct. Uit de hele DB structuur van de forms authentication moeten we dus enkel de logins, salts en geencrypteerde wachtwoorden overnemen in onze nieuwe applicatie.

Hebt u nog vragen of opmerkingen, dan hoor ik graag van u!