Wachtwoorden hashen? Wettelijk verplicht!

Door Gtoniser op donderdag 7 augustus 2014 12:06 - Reacties (19)
Categorie: Algemeen, Views: 5.809

Nodig?
"Ja, Joomla slaat de wachtwoorden standaard beveiligd op, maar dat vinden we niet handig dus slaan we ze ook als plaintext op"
Tijdens een gesprek met een klant kwam deze opmerking afgelopen week langs. Ja, een wachtwoord plaintext opslaan kan soms handig zijn, maar een beetje webdeveloper weet wel dat zulke dingen niet door de beugel kunnen.
Het excuus wat ik wel eens langs hoor komen is dat de dienst toch niet zo belangrijk is, en mensen hooguit een wachtwoord voor die dienst buit kunnen maken.
Fout.
Veel mensen gebruiken standaard dezelfde wachtwoorden, en als ik een kwaadwillende "hacker" ben en ik heb jouw email en wachtwoord, dan ga ik deze natuurlijk als eerste proberen op je email account, facebook, etc

Verplicht!
Wat veel mensen niet lijken te weten is dat het goed beveiligen van wachtwoorden in Nederland wettelijk is verplicht. In Nederland hebben we namelijk te maken met de Wet Bescherming Persoonsgegevens.
De text van deze wet kun je hier vinden. Het artikel in toepassing is artikel 13:
quote: WBP
De verantwoordelijke legt passende technische en organisatorische maatregelen ten uitvoer om persoonsgegevens te beveiligen tegen verlies of tegen enige vorm van onrechtmatige verwerking. Deze maatregelen garanderen, rekening houdend met de stand van de techniek en de kosten van de tenuitvoerlegging, een passend beveiligingsniveau gelet op de risico's die de verwerking en de aard van te beschermen gegevens met zich meebrengen. De maatregelen zijn er mede op gericht onnodige verzameling en verdere verwerking van persoonsgegevens te voorkomen.
Wat betekent dit nou in de praktijk? Het orgaan wat toezicht houdt op deze wet, het College Bescherming Persoonsgegevens (CBP) heeft een handig document hierover: http://www.cbpweb.nl/down...ging-persoonsgegevens.pdf
Hoewel het woord "richtsnoeren" misschien wat lijkt op aanbevelingen, moet je dit niet zien als een voorbeeld, maar als de invulling van de wet waar je je aan dient te houden.
In het hoofdstuk over het hiervoor genoemde Artikel 13 vinden we onder andere het volgende:
quote: CBP
Naast de beveiliging van persoonsgegevens ziet artikel 13 Wbp ook op de toepassing van privacy enhancing technologies (pet)
(...)
pet is de verzamelnaam voor een aantal technieken die de verantwoordelijke kan toepassen om bij het verwerken van persoonsgegevens de risico’s voor de betrokkenen te beperken.
Even verder vinden we wat voor regelgeving deze pet inhoudt:
quote: CBP
Bij het onderzoeken en beoordelen van de naleving van de wettelijke verplichting tot het toepassen van pet hanteert het cbp als uitgangspunt een aantal gangbare pet maatregelen. Deze maatregelen zijn:
• Encryptie (versleuteling) en hashing
De verantwoordelijke maakt gebruik van cryptografische bewerkingen om de persoonsgegevens
die hij verwerkt te beveiligen. Hij past encryptie (versleuteling) toe bij verzending van persoonsge­
gevens via het internet, bij de opslag van persoonsgegevens op draagbare apparatuur en op verwij­derbare media zoals usbsticks en in andere situaties waar persoonsgegevens kwetsbaar zijn voor toegang door onbevoegden (bijvoorbeeld persoonsgegevens die via het world wide web kunnen worden benaderd). Bij de opslag en verwerking van wachtwoorden maakt hij gebruik van hashing. Bij het toepassen van cryptografische technieken past hij alle gangbare voorzorgsmaatregelen toe, zoals goed ingericht sleutelbeheer en het gebruik van sleutellengten en versleutelingstechnieken die in overeenstemming zijn met de actuele stand van de techniek.
Voor de duidelijkheid, dit betekent dat dingen als
PHP:
1
2
$hash = md5($password);
$hash = sha1($password);

NIET voldoende zijn.
Deze technieken zijn hopeloos verouderd, met een beetje moderne videokaart kun je zo'n 10.000 Miljoen tot 20.000 Miljoen hashes per seconde testen (bron).

In de praktijk
Wat is dan wel een goede beveiliging voor wachtwoorden in een database?
Een goede hash voldoet tenminste aan de volgende punten:
- Een random salt
- Een sterk algorithme (blowfish, sha256, sha512, etc)
- Voldoende encryptie rondes

Er zijn voldoende sites die dit verder uitwerken. Een voorbeeld voor PHP kun je hier vinden: http://www.martinstoeckli.ch/php/php.html#bcrypt

Een stukje code PHP wat ik vaak gebruik en aan deze voorwaarden voldoet (sha256 met >15000 encryptie rondes):

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class login {
    public static function securePass($input,$salt=null){
        //Secure password
        //Random salt if no salt given (if salt given its for decoding purposes)
        if($salt == null){
            $binaryLength = (int)(16 * 3 / 4 + 1);
            if(function_exists('openssl_random_pseudo_bytes')){
                $salt = substr(str_replace('+', '.',base64_encode(openssl_random_pseudo_bytes($binaryLength))), 0, 16);
            }elseif(function_exists('mcrypt_create_iv')){
                $salt = substr(str_replace('+', '.',base64_encode(mcrypt_create_iv ( $binaryLength , MCRYPT_DEV_URANDOM  ))), 0, 16);
            }else{
                $salt = substr(str_replace('+', '.', base64_encode(pack('N4', mt_rand(), mt_rand(), mt_rand(), mt_rand()))), 0, 16);
            }
        }
        $crypttype = '$5$rounds=17838$';
        return substr(crypt($input,$crypttype.$salt.'$'),strlen($crypttype));
    }
    public static function validatePass($pass,$passhash){
        $passparts = explode('$',$passhash);
        $salt = $passparts[0];
        $out = self::securePass($pass,$salt);
        if(strcmp($out,$passhash) == 0){
            return true;
        }else{
            return false;
        }
    }
}


Gebruiksvoorbeeld:
PHP:
1
2
3
4
5
//Maak een hash aan die je in de database kunt opslaan
$hash = login::securePass($password);

//Controleer het wachtwoord met de hash uit de database
$valid = login::validatePass($password,$hash);


Een bijkomend voordeel is dat deze functie het gebruikte hashtype en rondes niet opslaat in de database, dus als een hacker een database dump heeft weet hij nog steeds niet hoeveel encryptie rondes je hebt gebruikt. Nadeel daarvan is dat als je de encryptie methode of het aantal rondes verandert, alle wachtwoorden uit je database het niet meer doen.

Tot slot: Wachtwoord hashing is niet alles, maar het is wel een belangrijke stap in ieder login systeem. Wil je meer weten over websites en security? Kijk eens op https://www.owasp.org/

Volgende: How to get Tomorrowland tickets - A technical analysis 06-02 How to get Tomorrowland tickets - A technical analysis
Volgende: Gamen met PS3 controller op Windows 04-'14 Gamen met PS3 controller op Windows

Reacties


Door Tweakers user Ultimation, donderdag 7 augustus 2014 13:41

Wat is de belasting van de door jouw geschreven functie? Kan je dat eens met 10.000 - 100.000 request doen?

Door Tweakers user SilentStorm, donderdag 7 augustus 2014 13:45

interessant artikel. Ik heb laatst ook een aantal dingen met wachtwoorden moeten doen, maar dan in Java. Ik vond dit stukje uitleg op de site van jasypt (ook) heel verhelderend over het nut, noodzaak en wijze van user password encryption. Goed om te horen dat die werkwijze intussen verplicht is. Er zijn nog zat sites die je zo je eigen wachtwoord weer terug kunnen sturen, ipv een hersteloperatie aan te bieden..

Nu nog een kort, niet-technisch document om naar te verwijzen (zodat ze het daadwerkelijk lezen), wanneer je websites om de oren wilt slaan met hun onveilige praktijken..


Een interessante aftakking: Wanneer in jou systeem ook wachtwoorden bijhoudt om daarmee andere systemen mee te bevragen, kom je op heel ander terrein. Voor userpasses wil je een vorm van encryptie (bv SHA) waarmee je elke keer dat je encrypt een andere hash krijgt, die niet meer is te herleiden naar het origineel. Als je echter met jou wachtwoord een ander systeem gaat bevragen, kom je in het domein van 2-zijdige, PasswordBasedEncryption (meestal met AES, 3DES), waarin ook het originele wachtwoord weer moet zijn te herleiden, adhv een originele passphrase.

Door Tweakers user wwwhizz, donderdag 7 augustus 2014 13:53

Ik zou het nog iets sterker willen stellen: heb je iets met de beveiliging van je websites/webapplicaties te maken, dan is de OWASP-website verplichte kost :)

Door Tweakers user Gtoniser, donderdag 7 augustus 2014 14:14

Ultimation schreef op donderdag 07 augustus 2014 @ 13:41:
Wat is de belasting van de door jouw geschreven functie? Kan je dat eens met 10.000 - 100.000 request doen?
Ik heb het getest met een loop van 10k keer een wachtwoord hashen (incl salt aanmaken), en dat kostte 140 seconden (PHP cli, 1 core @ 3.71 GHz).
Je kunt het aantal rounds opschroeven zodat het generaten van de hash rond de halve seconde gaat kosten (700k rounds was dat bij mij).
Ik weet niet of je nu op zoek was naar de impact op een systeem of naar hoe moeilijk het is te brute-forcen, maar je kunt natuurlijk wat met de parameters spelen.

[Reactie gewijzigd op donderdag 7 augustus 2014 14:22]


Door Tweakers user Korben, donderdag 7 augustus 2014 14:21

Waarom in hemelsnaam het wiel opnieuw uitvinden? Gebruik gewoon bcrypt of PBKDF2. bcrypt is sowieso beter dan PBKDF2, want die is veel moeilijker te implementeren op een ASIC of GPU. Daarnaast heeft die het probleem van de veranderende work-factor niet.

Door Tweakers user Gtoniser, donderdag 7 augustus 2014 14:24

Korben schreef op donderdag 07 augustus 2014 @ 14:21:
Waarom in hemelsnaam het wiel opnieuw uitvinden? Gebruik gewoon bcrypt of PBKDF2. bcrypt is sowieso beter dan PBKDF2, want die is veel moeilijker te implementeren op een ASIC of GPU. Daarnaast heeft die het probleem van de veranderende work-factor niet.
De link naar het voorbeeld geeft een bcrypt implementatie van PHP. Echter wordt bcrypt pas vanaf PHP 5.5 (vrijwel geen hosting die dat draait) native ondersteunt en is dit gewoon een simpel voorbeeldscriptje.

[Reactie gewijzigd op donderdag 7 augustus 2014 14:24]


Door Tweakers user toquetoque, donderdag 7 augustus 2014 17:13

Allemaal leuk die zelf in elkaar gehackte "oeh oeh 15K encryptie rondes" maar gebruik gewoon PHP's password_hash() and password_verify(), draai je PHP < 5.5 gebruik dan https://github.com/ircmaxell/password_compat .

Door Tweakers user thaan, donderdag 7 augustus 2014 18:41

Gewoon lekker 2FA integreren in je applicaties, met Google Authenticator. Zeer gemakkelijk te verwerken, maakt je wachtwoord verder geen fluit meer uit.

Door Tweakers user rty, donderdag 7 augustus 2014 19:10

Gebruikt die crypt methode nu DES?

Door Tweakers user Rmg, donderdag 7 augustus 2014 21:51

thaan schreef op donderdag 07 augustus 2014 @ 18:41:
Gewoon lekker 2FA integreren in je applicaties, met Google Authenticator. Zeer gemakkelijk te verwerken, maakt je wachtwoord verder geen fluit meer uit.
Naast 2FA zul je nog steeds moeten hashen. Ze kunnen dan wel niets met de wachtwoorden op je site, alleen als je WW tabel op straat ligt heb je nog steeds een probleem.


Door Tweakers user Blubber, vrijdag 8 augustus 2014 10:16

Persoonlijk gebruik ik meestal voor wachtwoorden PBKDF2 of bcrypt, vooral bcrypt is erg handig. Waar je wel op moet letten, en dat gaat in jouw code (denk ik) fout, is dat je een constant time vergelijking gebruikt om de hashes te vergelijken, anders lek je data. Sommige talen (zoals Python) hebben hier ingebouwde functies voor.

Door Tweakers user Gtoniser, vrijdag 8 augustus 2014 10:46

Blubber schreef op vrijdag 08 augustus 2014 @ 10:16:
Waar je wel op moet letten, en dat gaat in jouw code (denk ik) fout, is dat je een constant time vergelijking gebruikt om de hashes te vergelijken, anders lek je data. Sommige talen (zoals Python) hebben hier ingebouwde functies voor.
Ben toch nieuwsgierig hoe je hier een timing attack op wilt uitvoeren. Alle input wordt door dezelfde hashfunctie gegooid en vergeleken met de al bekende hash van het wachtwoord. Er lekt dus nergens data in deze functie.

Door Tweakers user Blubber, vrijdag 8 augustus 2014 10:51

Gtoniser schreef op vrijdag 08 augustus 2014 @ 10:46:
[...]
Ben toch nieuwsgierig hoe je hier een timing attack op wilt uitvoeren. Alle input wordt door dezelfde hashfunctie gegooid en vergeleken met de al bekende hash van het wachtwoord. Er lekt dus nergens data in deze functie.

code:
1
strcmp($out,$passhash)



Ik ben geen PHP expert, maar ik ga er vanuit dat strcmp returned zodra het kan en niet de vergelijking afmaakt, maar ik weet het niet zeker (zoals ik hierboven ook al opmerkte).

Als strcmp niet altijd de vergelijking afmaakt kan dat potentieel informatie lekken in een timing attack.

Door Tweakers user Gtoniser, vrijdag 8 augustus 2014 11:13

Blubber schreef op vrijdag 08 augustus 2014 @ 10:51:
[...]
Ik ben geen PHP expert, maar ik ga er vanuit dat strcmp returned zodra het kan en niet de vergelijking afmaakt, maar ik weet het niet zeker (zoals ik hierboven ook al opmerkte).
Even afgezien van of strcmp de vergelijking afmaakt, we vergelijken hier hashes, geen plaintext of block cyphers, dus als je kunt zien met een timing attack dat de eerste helft van de hash hetzelfde is als de hash van het password, dan zegt dit niets over de PT.

Door Tweakers user Blubber, vrijdag 8 augustus 2014 11:38

Gtoniser schreef op vrijdag 08 augustus 2014 @ 11:13:
[...]
Even afgezien van of strcmp de vergelijking afmaakt, we vergelijken hier hashes, geen plaintext of block cyphers, dus als je kunt zien met een timing attack dat de eerste helft van de hash hetzelfde is als de hash van het password, dan zegt dit niets over de PT.
Bij nader inzien denk ik dat je inderdaad gelijk hebt, met de kanttekening dat er wel een stark hash algoritme en salt gebruikt moeten worden. (meer info).


Door Tweakers user Crazy D, zaterdag 9 augustus 2014 08:39

Enige punt is de vraag of je profielgegevens zoals bv hier op tweeakers onder de persoonsgegevens vallen. En dat zal voor 99% van de sites waarop je moet inloggen, de vraag zijn.

Door Tweakers user Bitage, zaterdag 9 augustus 2014 19:04

Crazy D schreef op zaterdag 09 augustus 2014 @ 08:39:
Enige punt is de vraag of je profielgegevens zoals bv hier op tweeakers onder de persoonsgegevens vallen. En dat zal voor 99% van de sites waarop je moet inloggen, de vraag zijn.
Je kunt je naam en woonplaats en nog wel meer gegevens invullen die tot de persoon herlijdbaar zijn op Tweakers. Dat maakt het al dat het waarschijnlijk wel onder deze wet valt. Evenzo voor de meeste andere sites.

Reageren is niet meer mogelijk