grain de sel par utilisateur : comment faire ?

grain de sel par utilisateur : comment faire ? - PHP - Programmation

Marsh Posté le 14-01-2009 à 20:00:24    

Bonsoir,
 
j'étudie un tutoriel écrit par Guillaume Affringue pour lutter contre le vol d'identifiants (voir http://guillaume-affringue.develop [...] iffrement/)
 
J'ai un problème de compréhension de la technique dite "grain de sel par utilisateur" présentée ici : http://guillaume-affringue.develop [...] LIII-B-2-b. Affringue indique les étapes suivantes :
 


*  À l'inscription, on génère le GDS et on le place en base
* À la connexion, le visiteur entre son login
* On va chercher le GDS, soit par Ajax, soit en envoyant le login par formulaire, et en renvoyant le GDS
* On demande le mot de passe, on chiffre coté client et on envoie au serveur


 
Et de fait, comme l'indique,  l'auteur, des sites comme Spip utilisent bien une double fenêtre de connexion (d'abord le login puis, sur une autre fenêtre, le mot de passe).
 
Ce que je ne comprends pas, c'est pourquoi il n'est pas possible de simplifier ce schéma ainsi :
* À la connexion, le visiteur entre son login ET son mot de passe chiffré côté client
* on envoie le tout au serveur (via un formulaire)
* le serveur compare avec l'empreinte qu'il a dans la base de données
 
Manifestement je commets une erreur de raisonnement : pourriez-vous m'éclairer ? Merci d'avance ! :)
 
 


---------------
rule #1 : trust the python
Reply

Marsh Posté le 14-01-2009 à 20:00:24   

Reply

Marsh Posté le 15-01-2009 à 02:07:13    

hello
 
l'idée du GDS "efficace" est de changer ce GDS à chaque connexion de l'utilisateur. Ainsi, si quelqu'un attrape le mot de passe au passage (ce mot de passe est donc de la forme hash(vrai_mot_de_passe+GDS) ), ce mot de passe ne sera pas valide pour une autre connexion, puisque le GDS aura changé.
 
Donc les étapes :  
 
1. l'utilisateur rentre son login et l'envoie au serveur
2. le serveur recoit le login et génère un GDS aléatoire, propre à ce login, puis le stocke (en BDD, par exemple). le serveur envoie ce GDS au client
3. le client recoit le GDS. il peut maintenant entrer son mot de passe. Avant d'envoyer son mot de passe, un petit script javascript se charge de le hasher avec le GDS. Après le javascript, je mot de passe haché est envoyé au serveur.
4. le serveur recoit le hash du client. Il vérifie de son coté que le hash est bon en le calculant à son tour. avec le GDS qu'il vient de donner au client, il refait la même opération et calcule le hash de son coté, puis le compare à ce que le client vient de donner. Si les hash sont identiques, l'identification est réussie, sinon : non.
 
Il y a donc bien une première étape avec seulement le login, coté client. On ne peut pas éviter cette étape, puisque le client ne peut pas deviner le GDS. On peut simplement essayer d'éviter le chargement complet de la page, en utilisant AJAX, par exemple. Une fois que le client a entré son login, un script ajax l'envoie au serveur sans recharger la page, puis le serveur renvoie le GDS, qu'il stocke dans un champ input hidden, par exemple.
 
Voilà, en gros pour le GDS.
 
:jap:

Reply

Marsh Posté le 15-01-2009 à 08:18:01    

Euh les gars, je comprends pas trop votre histoire. On dirait que ça repose sur le fait que le serveur dispose lui même du mot de passe en clair. C'est pas le cas bien sur ?
 
Je comprends pas non plus vos histoires de GDS, c'est un terme inconnu de la littérature. On parle d'authentification par défi-réponse. La plus part du temps, ça fait une authentification en 5 phases (comme NTLM, chap, etc). 1) tentative de connexion 2) rejet 3) Demande d'authentification 4) envoie du défi 5) réponse au défi
 
Dans aucun cas, ça ne nécessite que le mot de passe soit stocké clair côté serveur.

Reply

Marsh Posté le 15-01-2009 à 09:07:38    

suizokukan a écrit :


* On demande le mot de passe, on chiffre coté client et on envoie au serveur



Donc ça ne sert à rien, si c'est chiffré côté client [:petrus dei]

Reply

Marsh Posté le 15-01-2009 à 09:32:45    

En gros, si j'ai bien compris (en bleu ce qui se passe côté serveur) :
1. Le client envoie son identifiant
2. Le serveur génère un mot (le Grain de sel) aléatoire, associé à cet identifiant.
3. Le serveur envoie le GdS avec sa demande de mot de passe.
4. Le client saisit le mot de passe.
(Là, c'est une hypothèse...)
5. Un script côté client hash le MdP puis hash un mot composé à partir du MdP et du GdS.
6. Le client envoie le hash(hash(MdP)+GdS)
7. Le serveur calcule le hash du ( hash stocké dans sa base + GdS)
8. En cas d'égalité, le login est validé.

Reply

Marsh Posté le 15-01-2009 à 09:39:39    

Bonjour
 
Le principe du GDS (Grain De Sel) propre à un utilisateur se déroule comme ceci
1) A l'inscription :  
    On crée un GDS unique et propre à l'utilisateur, qui restera le même au cours du temps.
    On hash l'ensemble (mot de passe + GDS)
    On stocke le GDS en base, avec les autres infos du user, dont le mot de passe sous la forme hash(mdp + GDS)
 
2) A la connexion :
    Si on veut chiffrer le mot de passe coté client, il nous faut le GDS de l'utilisateur qui essai de se connecter pour pouvoir réappliquer hash(mdp + GDS). Mais comme le GDS est spécifique à un user, il nous faut déjà connaitre le user, puis aller chercher son GDS pour pouvoir chiffrer le mdp selon le méme modèle que celui en base, c'est à dire hash(mdp + GDS)
 
Ainsi, le mot de passe n'est pas stocké en clair, est stocké avec un GDS, ne transite pas en clair, et l'utilisation de GDS spécifique à l'utilisateur empêche les force brute sur l'ensemble de la base (mais ne l'empêche pas pour un user spécifique)
 
Le GDS par session comme vous décrivez est possible, mais à mon avis trop compliqué car nécessite forcement au moins 2 GDS (vu qu'il "faut" avoir le mdp en clair)

Reply

Marsh Posté le 15-01-2009 à 09:48:24    

wamania a écrit :

2) A la connexion :
    Si on veut chiffrer le mot de passe coté client, il nous faut le GDS de l'utilisateur qui essai de se connecter pour pouvoir réappliquer hash(mdp + GDS). Mais comme le GDS est spécifique à un user, il nous faut déjà connaitre le user, puis aller chercher son GDS pour pouvoir chiffrer le mdp selon le méme modèle que celui en base, c'est à dire hash(mdp + GDS)


Sauf que ça ne change pas grand chose par rapport à avoir le mot de passe en clair. Si on arrive à chopper ce qui transite, de toute manière on pourra se connecter, vu que le chiffrage est côté client...

Reply

Marsh Posté le 15-01-2009 à 09:57:37    

Absolument, le hash coté client n'est pas fait pour empêcher le vol de session, mais pour assurer l'intégrité du mot de passe lors des transferts de celui-ci par le réseau.

Reply

Marsh Posté le 15-01-2009 à 09:58:23    

Hmmm, franchement, un bon vieux HTTPS des familles est 10x mieux que cette solution bancale :D

Reply

Marsh Posté le 15-01-2009 à 10:00:56    

Taz a écrit :

Euh les gars, je comprends pas trop votre histoire. On dirait que ça repose sur le fait que le serveur dispose lui même du mot de passe en clair. C'est pas le cas bien sur ?
 
Je comprends pas non plus vos histoires de GDS, c'est un terme inconnu de la littérature. On parle d'authentification par défi-réponse. La plus part du temps, ça fait une authentification en 5 phases (comme NTLM, chap, etc). 1) tentative de connexion 2) rejet 3) Demande d'authentification 4) envoie du défi 5) réponse au défi
 
Dans aucun cas, ça ne nécessite que le mot de passe soit stocké clair côté serveur.


 
le mdp n'est pas nécessairement stocké en clair coté serveur. ca dépend de l'implémentation.  
 
l'idée est que :
* le mot de passe ne circule pas en clair
* le mot de passe chiffré qui circule diffère à chaque authentification
 
pour l'implémentation, on peut avoir :  
 
coté client, on envoit : hash( hash(password) + GDS)             (avec le GDS qui change à chaque authentification)
coté serveur on envoit : hash( hash(password) + GDS)           (en sachant que hash(password) est contenu tel quel en base, donc pas 'en clair')
 
en fait... c'est une histoire de position de parenthèse  ;)
 

FlorentG a écrit :


Sauf que ça ne change pas grand chose par rapport à avoir le mot de passe en clair. Si on arrive à chopper ce qui transite, de toute manière on pourra se connecter, vu que le chiffrage est côté client...


 
si. si le login est chiffé et change à chaque fois, le pirate ne peut plus utiliser ce qu'il intercepte puisque le GDS changera.
 
On n'évite pas le Man in the middle avec ca. Pour le Man in the Middle, il faut un certificat, et donc https et tout le bazar.
On n'évite pas non plus les keyloggers qui pourraient enregistrer ce qui se passe avant le javascript (ou plus généralement le chiffrement coté client).
 
ici, on se protège un peu des sniffers réseau et autres oreilles indiscrètes.

Reply

Marsh Posté le 15-01-2009 à 10:00:56   

Reply

Marsh Posté le 15-01-2009 à 10:02:48    

Certes, le HTTPS est la meilleur solution.
Ça ne veut pas forcement dire que les autres sont bancales....

Reply

Marsh Posté le 15-01-2009 à 10:06:47    

nabbo a écrit :

si. si le login est chiffé et change à chaque fois, le pirate ne peut plus utiliser ce qu'il intercepte puisque le GDS changera.


Si le salt change à chaque connexion, effectivement :jap: Je parlais du coup du salt qui ne change pas, lequel cas ça ne sert à rien.
 
Mais le problème aussi est que ça repose sur JavaScript :/ Attention à faire une version qui marche sans
 
 

nabbo a écrit :

On n'évite pas non plus les keyloggers qui pourraient enregistrer ce qui se passe avant le javascript (ou plus généralement le chiffrement coté client).


Ouais voilà [:sadnoir]

Reply

Marsh Posté le 15-01-2009 à 10:09:34    

FlorentG a écrit :

Hmmm, franchement, un bon vieux HTTPS des familles est 10x mieux que cette solution bancale :D


 
ca présente toutes les sécurités, mais c'est plus compliqué à mettre en place. il faut avoir des technos (SSL, etc) qui ne sont pas nécessairement présentes sur tous les serveurs (mutualisés, par exemple).
 
L'idéal est aussi d'avoir un certificat... ce qui coute de l'argent.
 
La solution présentée ici n'est pas parfaite en terme de sécurité et est certes un peu bancale, mais elle est moins lourde à mettre en place.
 
A voir donc, suivant le besoin.
 
:jap:

Reply

Marsh Posté le 15-01-2009 à 10:12:25    

FlorentG a écrit :


Mais le problème aussi est que ça repose sur JavaScript :/ Attention à faire une version qui marche sans


 
on peut aussi choisir de ne pas accepter les versions sans javascript.
 
Solution possible en environement controlé (en entreprise, on peut s'assurer que tout le monde utilise javascript).
 
Solution pas franchement recommandée sur internet, pour l'accessibilité. (même si possible techniquement).

Reply

Marsh Posté le 15-01-2009 à 10:40:11    

En entreprise, on utilise HTTPS !


---------------
Laissez l'Etat dans les toilettes où vous l'avez trouvé.
Reply

Marsh Posté le 15-01-2009 à 12:24:20    

bon je vous laisse jouer.

Reply

Marsh Posté le 15-01-2009 à 12:34:40    

ligne htaccess d'après mon petit outil :  
"$user2:".crypt($password,substr($user2,0,2))
ici le salt sont les deux premieres lettre de l'user, mais l'on peut déterminer n'importe quoi :)
à ça on ajoute une connexion https forcée et le tour est joué :)


---------------
Photos Panoramiques Montagnes Haute Savoie
Reply

Marsh Posté le 15-01-2009 à 12:56:00    

Taz a écrit :

bon je vous laisse jouer.

 

tu peux aussi nous dire ce que tu fais, dans un environnement où tu ne peux pas faire d'https.

 

Un hébergement mutualisé, par exemple.
Toujours dans le thème d'une appli web. Donc pas de ntlm, etc.


Message édité par nabbo le 15-01-2009 à 12:57:05
Reply

Marsh Posté le 15-01-2009 à 14:02:52    

Taz a écrit :

bon je vous laisse jouer.


Nanan, tu apportes ton expertise et ta pédagogie légendaires :D

Reply

Marsh Posté le 15-01-2009 à 14:04:10    

grosbin a écrit :

ligne htaccess d'après mon petit outil :  
"$user2:".crypt($password,substr($user2,0,2))
ici le salt sont les deux premieres lettre de l'user, mais l'on peut déterminer n'importe quoi :)
à ça on ajoute une connexion https forcée et le tour est joué :)


Seul problème, le salt peut être deviné :D Utile pour construire des rainbow tables personnalisées (si on est vraiment motivé).

Reply

Marsh Posté le 15-01-2009 à 14:31:34    

grosbin a écrit :

ligne htaccess d'après mon petit outil :  
"$user2:".crypt($password,substr($user2,0,2))
ici le salt sont les deux premieres lettre de l'user, mais l'on peut déterminer n'importe quoi :)
à ça on ajoute une connexion https forcée et le tour est joué :)


 
 
est ce que tu peux détailler un peu ?
le htaccess est généré à la volée et interprété par php ?
 
ton salt est dépendant du login, donc effectivement devinable ?
 
comment est ce que tu récupères la variable $password ?

Reply

Marsh Posté le 15-01-2009 à 16:56:39    

Heu, il y a un truc que je ne comprends pas.
C'est quoi l'intérêt de faire en deux étapes (pseudo puis mot de passe et grain de sel) alors qu'on pourrait simplement faire en une seule?
Le seul cas où ça changerait quoi que ce soit au niveau sécurité, c'est si quelqu'un écoute tout ce qui passe par un routeur donné et qu'il reçoit par hasard (s'il reçoit tout ce qui est envoyé par l'utilisateur ou tout ce qui est reçu par le serveur, ça ne changerait strictement rien même en faisant en 15 envoies) le paquet qui contient ces données là.

Reply

Marsh Posté le 15-01-2009 à 18:13:14    

FlorentG a écrit :


Sauf que ça ne change pas grand chose par rapport à avoir le mot de passe en clair. Si on arrive à chopper ce qui transite, de toute manière on pourra se connecter, vu que le chiffrage est côté client...


 
Je sais pas si c'est pour la raison dont tu parles et si c'est toujours le cas mais j'ai le souvenir que gibii (https://gibii.ac-grenoble.fr/b2i/login/login.php?etab_id=321&GIBII_FIN=../login/login.php) chiffre les données de connexion au onsubmit, donc la connexion ne marche pas si JS est désactivé  :pfff: .

Reply

Marsh Posté le 15-01-2009 à 18:44:23    

Un grand merci pour cette discussion qui m'aura fait comprendre bien des choses. Comme d'habitude, HFR assure !


---------------
rule #1 : trust the python
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed