Versio

[Theorie] Veilige wachtwoord handling

Overzicht Reageren

Pagina: 1 2 volgende »

GaMer B

GaMer B

21/07/2008 20:55:00
Quote Anchor link
Hallo allemaal,

Dit keer heb ik niet echt een vraag, maar wil eerder iets met jullie delen. Heb het een en ander gelezen op de community van CodeIgniter (wat ik gebruik) en daar zitten een stelletje slimme mensen :P. Ik weet ook niet waar zij het weer van hebben en of het hier al staat (niets daar over gevonden althans), dus bij deze.

Vandaag heb ik gelezen hoe je (het beste) veilig een wachtwoord kunt opslaan in de database. Om te beginnen gebruik niet de SHA1() functie van MySQL, maar van PHP. PgFrank z'n kop zal nu drie keer rond draaien, maar het is wel zo. Als je de MySQL SHA1() functie gebruikt (ook voor MD5() overigens), komt het plain-text wachtwoord in de SQL logs te staan. Leesbaar voor hackers (?) / admins.
Verder is er een erg veilige methode om wachtwoorden in databases op te slaan. Het concept baseert zich wel op een salt, dat is gebleken dat dat het beste is wat je kunt bedenken. Het ziet er zo uit:

sha1([config-salt-key] + [database-hash] + [sha1(plain-text wachtwoord)])
Optioneel zou je die sha1 over het plain-text wachtwoord kunnen weglaten om collision te voorkomen, maar is misschien toch wel een goede optie.

De [config-salt-key] sla je op buiten de database, in een config bestand dus. Die is dan ook static. Een goede website waar je goede salt keys kunt vinden, is GRC.com. Gegarandeerd unieke random strings.
De [database-hash] maak je met behulp van microtime() en wat random tekens (kun je ook GRC.com voor gebruiken overigens) en vervolgens MD5 / SHA1 er overheen. sha1(microtime()) is vaak voldoende. Let op! Dit is dus dynamisch en moet dus ook maar één keer gebeuren! Doe dit bij de registratie! De hash sla je vervolgens in de tabel op in een veld genaamd hash of iets dergelijks. Deze zul je ook iedere keer samen met de salt key moeten oproepen.
De [sha1(plain-text)] is dus ook bij de registratie, want ergens anders kom je niet aan de plain-text. Deze hash is op het einde van het proces nergens meer te bekennen.

Nu de samengestelde hash maken:
sha1([config-salt-key] + [database-hash] + [sha1(plain-text wachtwoord)]) en deze opslaan in de tabel in een veld genaamd password of iets dergelijks. Deze zul je alleen ter vergelijkings materiaal nodig hebben.

Bij het inloggen moet je het ingevoerde wachtwoord hashen met sha1, vervolgens de salt key en hash in de database (ook de samengestelde hash) opvragen en die vervolgens weer samenstellen en dan vergelijken met de samengestelde hash.

Wat vinden jullie van deze methode? Zouden jullie die ook gaan gebruiken? Ik in elk geval... Nog aanvullingen aan deze methode?
Moge er een discussie ontstaan.

GaMer13
Gewijzigd op 01/01/1970 01:00:00 door GaMer B
 
PHP hulp

PHP hulp

25/05/2012 16:20:59
Gesponsorde koppelingen:
 
Frank -

Frank -

21/07/2008 21:04:00
Quote Anchor link
GaMer13 schreef op 21.07.2008 20:55:
Om te beginnen gebruik niet de SHA1() functie van MySQL, maar van PHP. PgFrank z'n kop zal nu drie keer rond draaien, maar het is wel zo. Als je de MySQL SHA1() functie gebruikt (ook voor MD5() overigens), komt het plain-text wachtwoord in de SQL logs te staan. Leesbaar voor hackers (?) / admins.
Verder is er een erg veilige methode om wachtwoorden in databases op te slaan. Het concept baseert zich wel op een salt, dat is gebleken dat dat het beste is wat je kunt bedenken.

1) Waarom zou ik dan nu m'n kop 3 keer ronddraaien?
2) Dat van de logs is bekend, vandaar dat hashen van wachtwoorden in de database niet handig is. Je wilt alleen maar kunnen vergelijken, daarmee bereik je al je doel.
3) Wat is nu het nieuws? Lijkt me allemaal gesneden koek en veilig (genoeg).
 
- -

- -

21/07/2008 21:09:00
Quote Anchor link
Quote:
Als je de MySQL SHA1() functie gebruikt (ook voor MD5() overigens), komt het plain-text wachtwoord in de SQL logs te staan. Leesbaar voor hackers (?) / admins.


Niet toevallig vanmiddag gelezen uit de post van PHP Newbie? http://www.phphulp.nl/forum/showtopic.php?cat=8&id=51328&lasttopic=1
 
GaMer B

GaMer B

21/07/2008 21:11:00
Quote Anchor link
s%s_0%W690L"HohdMI+-ft\z=5\~Ivg;i+w!?[-;8oxe*5=znKTt"iGq*v!?<1% salt
42f48088c5ad67cff5934146975dccdbd1d9e087 hash
d4fbef92af33c1789d9130384a56737d181cc6df wachtwoord

Samengestelde hash in de database:
fd9f207af326860aa16cc77b1b5ba78959d1fa0c
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
s%s_0%W690L"HohdMI+-ft\z=5\~Ivg;i+w!?[-;8oxe*5=znKTt"iGq*v!?<1%42f48088c5ad67cff5934146975dccdbd1d9e087d4fbef92af33c1789d9130384a56737d181cc6df


Is de kans op collision nu toegenomen of afgenomen? Aangezien je nu met een flinke hoeveelheid tekens een SHA1 hash maakt...

EDIT: Inderdaad, die ene feit kwam van PHP Newbie, iChris.nl
Gewijzigd op 01/01/1970 01:00:00 door GaMer B
 

21/07/2008 23:08:00
Quote Anchor link
Vraagje waar vind ik die vandaag al vaker genoemde MySQL logs. Ik heb wel ergens error logs maar ik kan zo één twee drie geen log vinden de query's die zijn gestuurd.
 
PHP Newbie

PHP Newbie

21/07/2008 23:16:00
Quote Anchor link
Webmakerij schreef op 21.07.2008 23:08:
Vraagje waar vind ik die vandaag al vaker genoemde MySQL logs. Ik heb wel ergens error logs maar ik kan zo één twee drie geen log vinden de query's die zijn gestuurd.


Klikje
 

21/07/2008 23:19:00
Quote Anchor link
Quote:
To enable the general query log, start mysqld with the --log[=file_name] or -l [file_name] option.
Ah nee dat heb ik niet aanstaan. Vraag me af waarom je het zal willen doen behalve debug. Lijkt me nogal een vertragende factor.
 
PHP Newbie

PHP Newbie

21/07/2008 23:26:00
Quote Anchor link
Het probleem is dat je niet weet of het aan of uit staat. Dan heb je ook deze deze. Het zou kunnen dat je host deze aan heeft staan...
 
Jelmer rrrr

Jelmer rrrr

21/07/2008 23:49:00
Quote Anchor link
Er zijn ook logsbestanden die alle queries opslaan om een backup bij te werken naar het punt dat de database het begaf (en geen queries meer toevoegde aan het logbestand) Ik weet niet precies hoe ze heten, iets met slow-log geloof ik, of binary log, maar volgens mij gebruikt de InnoDB engine ze.

Ik neem trouwens aan dat die logs asynchroon gaan met de database zelf, zodat een query niet hoeft te wachten opdat hij in de logbestanden is weggeschreven.

Overigens lijkt mij dit voor de server de meest veilige manier van een wachtwoord opslaan. Via een foute include (eentje die slecht- & niet-gecontroleerde user-input gebruikt om een pad te maken) of ftp-toegang zou je achter de salt in de code kunnen komen. Via SQL-injection en heel lang nadenken zou je misschien achter de hash uit de database kunnen komen. (in de zin van: het is mij nog nooit gelukt een query te schrijven die vanuit de WHERE ervoor zorgt dat ik bijvoorbeeld de waarde in de 'name' kolom overschijf met de waarde uit de hash-kolom, alhoewel er misschien iets mogelijk is met concat en subqueries) De hash mag overigens ook gewoon salt zijn, dat maakt verder niet veel uit. Zolang hij maar niet te berekenen is.

In ieder geval, als het zo laat is dat die beide aanvallen gelukt zijn, zou je je kunnen bedenken dat het achteraf misschien makkelijker was geweest om bijvoorbeeld phising of een andere vorm van social engineering toe te passen. Bijvoorbeeld je richten tot de hostingprovider en het wachtwoord ontfutselen (of waarschijnlijker: resetten) zodat je de PHP-bestanden kan aanpassen.

Heb je je zwakste punt in ieder geval verplaatst :)
 
Jurgen assaasas

Jurgen assaasas

22/07/2008 00:01:00
Quote Anchor link
Webmakerij schreef op 21.07.2008 23:08:
Vraagje waar vind ik die vandaag al vaker genoemde MySQL logs. Ik heb wel ergens error logs maar ik kan zo één twee drie geen log vinden de query's die zijn gestuurd.


/var/log/mysql of /var/log/mysql.log Standaard op een Linux systeem
Gewijzigd op 01/01/1970 01:00:00 door Jurgen assaasas
 
Bo az

Bo az

22/07/2008 00:20:00
Quote Anchor link
Jelmer schreef op 21.07.2008 23:49:
Heb je je zwakste punt in ieder geval verplaatst :)


Dat vraag ik me dus af, zolang je geen ssl gebruikt gaan je wachtwoorden nog gewoon in plain-text over de lijn.
 
M Ypma

M Ypma

22/07/2008 02:11:00
Quote Anchor link
mooie methode vind ik alsvolgt, zo kan je zonder ssl toch je wachtwoorden beveiligd over gooien. Het idee achter het concept is: waarom een wachtwoord naar de server sturen als deze al het wachtwoord weet?

client: voert wachtwoord in, een lokale timestamp bij de gebruiker wordt ingepakt dmv wachtwoord

Dit wordt opgestuurd naar de server, de server kan nu met het wachtwoord de string uitpakken en het resulstaat is een timestamp... vervolgens kan je er voor kiezen om te controleren op een tijdsverschil, zo maak je het "the man in the middle" moeilijk om binnen enkele seconden de inlog procedure over te nemen.
 
PHP Newbie

PHP Newbie

22/07/2008 03:06:00
Quote Anchor link
En hoe los je dan het time-zone verschil op? Of misschien staat de klok aan de client-side wel 2 minuten voor?
 
Hipska BE

Hipska BE

22/07/2008 06:27:00
Quote Anchor link
daar was ik ooit al eens mee begonnen, maar blijkt zo simpel nog niet. tijdzone verschil is het grote probleem niet, wel het encoderen in JS en decoderen in php.

Deze methode wordt gebruikt in het kerberos protocol.

http://phphulp.nl/forum/showtopic.php?cat=1&id=43746 encryptie decryptie
http://phphulp.nl/forum/showtopic.php?cat=1&id=42849 tijdsync
 
GaMer B

GaMer B

22/07/2008 12:34:00
Quote Anchor link
Zonder SSL is het nooit goed te beveiligen dat plain-text wachtwoorden over de lijn gaan. Het enige waar je van uit kunt gaan is JS.

Met JS kun je dan on-the-fly het wachtwoord bij onSubmit met SHA1 hashen en versturen. Het is echter wel zo dat de gebruik JS aan moet staan. Dat is het grootste nadeel.

Het is wellicht te stellen dat je je meer moet focussen op de client-side beveiliging dan de server-side beveiliging. Met SSL is die onzekerheid zo weg.
 
Bo az

Bo az

22/07/2008 14:08:00
Quote Anchor link
GaMer13:
Met JS kun je dan on-the-fly het wachtwoord bij onSubmit met SHA1 hashen en versturen. Het is echter wel zo dat de gebruik JS aan moet staan. Dat is het grootste nadeel.


Nee, dat is niet het grootste nadeel, het grootste nadeel is dat iemand die de hash kan 'afluisteren' daarmee kan inloggen, dan heeft die je wachtwoord niet meer nodig.

Ik heb voor dit probleem dus laatst een oplossing gelezen, maar kan het nu nergens meer vinden :S
 
Hipska BE

Hipska BE

22/07/2008 14:50:00
Quote Anchor link
Boaz, lees dan es de bovenste van die 2 topics die ik gaf.

een timestamp encrypten met behulp van het wachwoord, en die string verzenden. Je wachtwoord komt niet over de lijn (niet nodig, want de server weet je WW ook). De server decrypt deze string opnieuw met jouw WW, en als daar een geldige timestamp uitkomt die nog binnen bepaalde grenzen ligt dan ben je ge-authenticeerd. Had je die timestamp met een verkeerd WW encrypt, dan is het onmogelijk dat er aan de serverkant met het juiste WW een correcte timestamp tevoorschijn komt.
 
Jonathan -

Jonathan -

22/07/2008 15:03:00
Quote Anchor link
Hipska schreef op 22.07.2008 14:50:
Boaz, lees dan es de bovenste van die 2 topics die ik gaf.

een timestamp encrypten met behulp van het wachwoord, en die string verzenden. Je wachtwoord komt niet over de lijn (niet nodig, want de server weet je WW ook). De server decrypt deze string opnieuw met jouw WW, en als daar een geldige timestamp uitkomt die nog binnen bepaalde grenzen ligt dan ben je ge-authenticeerd. Had je die timestamp met een verkeerd WW encrypt, dan is het onmogelijk dat er aan de serverkant met het juiste WW een correcte timestamp tevoorschijn komt.

Dan moet het wachtwoord zonder MD5 of SHA1 in de database en dat is erg onveilig (denk aan de logs, maar ook aan hackers, hosters etc.).
 
Robert Deiman

Robert Deiman

22/07/2008 15:11:00
Quote Anchor link
@Hipska

Is het ondetussen allemaal al gelukt dan? Je kan natuurlijk zelf ook een encryptiefunctie schrijven, maar die zijn allemaal wel te lezen in principe. Misschien kan je hem wel includen/ inladen in je html als die buiten de root staat. (includen met PHP dus NIET) Dan kan je wel die functie gebruiken, maar iemand anders kan hem niet lezen, kan een optie zijn?

Jonathan schreef op 22.07.2008 15:03:
Dan moet het wachtwoord zonder MD5 of SHA1 in de database en dat is erg onveilig (denk aan de logs, maar ook aan hackers, hosters etc.).

Op zich is dat niet zo'n probleem, je logs kan je uitzetten en zijn (doorgaans, anders kan je daar ook zelf voor zorgen) niet zomaar beschikbaar.
Daarnaast wordt het wachtwoord zelf nooit verzonden, maar dus alleen de met het wachtwoord versleutelde timestamp.
De server stuurt ook geen wachtwoord terug, maar kijkt of de timestamp kan. (niet te lang geleden is en geldig is) Het password wordt nooit verzonden.

Enige nadeel kan wel zijn (ik noem het hierboven al) dat je javascript kan lezen, en als je handig bent de boel ontsleutelen en daarmee het password achterhalen.
Gewijzigd op 01/01/1970 01:00:00 door Robert Deiman
 
Hipska BE

Hipska BE

22/07/2008 15:42:00
Quote Anchor link
Robert_Deiman schreef op 22.07.2008 15:11:
Je kan natuurlijk zelf ook een encryptiefunctie schrijven, maar die zijn allemaal wel te lezen in principe. Misschien kan je hem wel includen/ inladen in je html als die buiten de root staat. (includen met PHP dus NIET) Dan kan je wel die functie gebruiken, maar iemand anders kan hem niet lezen, kan een optie zijn?

...

Enige nadeel kan wel zijn (ik noem het hierboven al) dat je javascript kan lezen, en als je handig bent de boel ontsleutelen en daarmee het password achterhalen.
Uitvoerbare JS code moet altijd leesbaar zijn door de gebruiker/browser anders kan het niet uitvoeren he. Daarom de nood om een gekende en grote encryptie te gebruiken, iets als AES Rijndael, die zijn zonder de sleutel (hier het ww) niet te decrypten. Elke zelfgemaakte encryptie zal nooit zo goed zijn als een van de grotere. Mijn enigste probleem waar ik vastgelopen ben, en daardoor dat project op de lange baan geschoven heb, is dat het me niet lukte om met JS een AES string met php goed te Decrypten (resultaat klopte niet echt).

Jonathan schreef op 22.07.2008 15:03:
Dan moet het wachtwoord zonder MD5 of SHA1 in de database en dat is erg onveilig (denk aan de logs, maar ook aan hackers, hosters etc.).
In de log zal je ook geen wachtwoord tegenkomen, daar je een SELECT pw FROM doet. Je tweede punt dat de hosters dit wel zouden kunnen zien is waar, dan kan je alsnog met JS eerst je ww MD5 doen en in DB ook als MD5 opslaan, dan is dat ook al weer opgelost.
 
Robert Deiman

Robert Deiman

22/07/2008 15:52:00
Quote Anchor link
@Hipska
Dat gebeuren met uitvoerbare JS code had ik al wel begrepen, daarom ook mijn opmerking dat je misschien net als met PHP files, ook javascript files van buiten je root wel kan laden in je pagina (met <script src="">) Dan is het wel vrij veilig, en omdat je niet in de code kan en geen idee hebt hoe het versleutelt is, is het ook moeilijk encoderen.
 

Pagina: 1 2 volgende »



Overzicht Reageren