PHP: Wachtwoorden veilig opslaan d.m.v. hasing en salting

  •  
  •  

Op 3 oktober 2013 kon Adobe niets anders dan toegeven dat ze ernstig de fout in waren gegaan:

"We hebben onlangs ontdekt dat een of meer personen illegaal zijn binnengedrongen in ons netwerk. Mogelijk hebben zij toegang gekregen tot uw Adobe-id en uw versleutelde wachtwoord."

Anders gezegd: hackers hebben de wachtwoorden van 2,9 miljoen Adobe gebruikers. Naked Security spreekt zelfs van 38 miljoen gebruikers, echter geven zij geen duidelijke bronnen vrij. Als zelfs een gigantisch bedrijf als Adobe deze fout begaat, dan is het een kwestie van tijd voordat het elke andere ontwikkelaar of bedrijfseigenaar ook overkomt.

1. Plain-Text (platte tekst)

De allergemakkelijkste manier om wachtwoorden op te slaan in een database is platte tekst. Dat betekent dat er in de database voor elke gebruiker een gebruikersnaam en wachtwoord combinatie terug te vinden is, zoals onderstaand voorbeeld

ID_USERusernamepassword
000001ed.kroketfrituurpan
000002piet.frietfrikandel

Wanneer je momenteel jouw wachtwoorden op deze manier opslaat, is de kans zeer groot dat jouw systeem ook niet up-to-date is of dat jouw systeem wellicht beveiligd is met een heel simpel wachtwoord. Of nog veel erger, dat je jouw php-config met wachtwoord uploadt via een slappe ftp verbinding.

2. Two way Encryption (omkeerbare versleuteling)

De mcrypt-extentie in PHP ondersteunt een flinke hoeveelheid cyphers (een procedure om een gegevensreeks te versleutelen of ontsleutelen). Het kenmerk aan al deze cyphers is dat de stappen in de procedures ook on omgekeerde volgorde uitgevoerd kunnen worden. Anders gezegd: elk versleutelde tekenreeks kan ook ontsleuteld worden.

ID_USERusernameencoded
000001ed.kroketZnJpdHV1cnBhbg==
000002piet.frietZnJpa2FuZGVs

Zoals in bovenstaande tabel te zien is (base64 encoding van de wachtwoorden uit de eerste tabel), zijn de wachtwoorden deze keer versleuteld — het originele wachtwoord zoals in de eerste tabel is nu veranderd in een waarde die het wachtwoord representeert. Geef een hacker echter wat tijd om het algoritme te achterhalen en alle wachtwoorden liggen alsnog op straat.

Pro Tip

Wanneer je via de "wachtwoord vergeten" functie van een website jouw originele wachtwoord via de e-mail toegestuurd krijgt, kun je er vanuit gaan dat jouw wachtwoord als platte tekst of met omkeerbare versleuteling is opgeslagen.

3. One way Encryption / Hashing (onomkeerbare versleuteling)

In tegenstelling tot encryption wordt bij hasing een tekenreeks versleuteld naar een som van de gegevens, waardoor dit strikt gezien geen versleuteling is. Behalve dat dit als voordeel heeft dat elk versleutelde wachtwoord dezelfde lengte krijgt, zorgt dit vooral dat de hash onomkeerbaar versleuteld wordt. De enige manier om te controleren welke gegevens bij welke hash kunnen horen, is door middel van trail and error, oftewel brute forcing.

Veelgebruikte algoritmes, zoals SHA1 of MD5 bestaan echter al zo lang dat er zogenaamde rainbow-tables in omloop zijn waarmee alle mogelijke wachtwoorden voor een bepaalde hash vooraf zijn berekend. In ruil voor een flinke hoeveelheid schijfruimte kun je hashes nagenoeg direct opzoeken en terugvertalen zonder ook maar een hash te hoeven berekenen. Sterker nog, je kunt de meeste SHA1 of MD5 hashes gewoon opzoeken in Google!

Een alternatieve manier om deze hashes te kraken is door middel van dictionary attacks, waarbij er gebruik wordt gemaakt van het feit dat gebruikers vaak dezelfde zwakke wachtwoorden gebruiken waardoor een hash relatief snel achterhaald kan worden. Kortweg kan er gezegd worden dat een hacker i.c.m. een beperkte hoeveelheid tijd alsnog achter wachtwoorden van gebruikers kan komen.

4. Hashing & Salting (sleutelafleiding)

Als voor elke hash of sleutel het wachtwoord al bekend is, dan rest er niets dan nog een extra laag over de hashing toe te voegen. Voordat elk wachtwoord versleuteld wordt, wordt er eerst een willekeurige tekenreeks toegevoegd aan het wachtwoord — dit wordt ook wel salting genoemd. Deze tekenreeks kan elke willekeurige lengte hebben en kan elke willekeurige tekens bevatten. Door voor de versleuteling eerst deze salt toe te voegen, kan er geen gebruik meer gemaakt worden van rainbow tables of dictionary attacks. Simpelweg doordat elke hash berekend moet worden aan de hand van de salt, zal het een hacker exponentieel meer tijd kosten om wachtwoorden te brute-forcen.

ID_USERusernamesalthash
000001ed.kroket54j0j744a961dc2c45d7799c5258ea1bd33ffa
000002piet.friet69i57j2e9b2184a738dce31791bf8d4ae8dc12

In bovenstaand voorbeeld zijn zowel de salt als de hash per gebruiker opgeslagen. Dit zijn ook de gegevens die in realiteit in de database terug te vinden mogen zijn, gezien zelfs met deze gegevens een wachtwoord telkens berekend moet worden om te controleren of er een match is. Onderstaand een voorbeeld hoe dit toegepast kan worden aan de "input" zijde (de PHP-kant) en de database zijde:

// generate a 10 char length salt (eample: 54j0j7)
$salt = substr(str_shuffle('1234567890abcdefghijklmnopqrstuvwxyz')), 0, 10);
$pass = 'frituurpan';

// hash = 44a961dc2c45d7799c5258ea1bd33ffa
$hash = md5($pass . $salt);
SELECT ID_USER
FROM users
WHERE username = 'ed.kroket'
AND hash = MD5( CONCAT('frituurpan', '54j0j7') );

Conclusie

Het meest kostbare voor een hacker is tijd, met voldoende tijd is elk systeem te kraken. Daarom bestaat er eigenlijk geen manier op wachtwoorden perfect op te slaan. Toch kun je het met de combinatie van hashing en salting tamelijk lastig maken. De methoden die besproken zijn hebben echt zin als jouw database onverhoopt op straat komt te liggen. Daardoor is de beveiliging van alle omliggende systemen net zo belangrijk. Eveneens kun je aan gebruikers vragen om wachtwoorden te kiezen die lang en ingewikkeld genoeg zijn.

Als laatste verdient het de aandacht dat MD5 en SHA1 verouderde algoritmes zijn. Doordat processorsnelheden steeds hoger komen te liggen is het daarom aan te bevelen dat er wordt gekeken naar methoden als SHA256 of multihashing, waarbij een hash meerdere keren berekend wordt voordat wachtwoorden opgeslagen worden. Het blijft echter een feit dat elk systeem na verloop van tijd steeds minder veilig is.