[RESOLU] Protection formulaires.

Eléphant du PHP | 290 Messages

27 nov. 2014, 10:58

Si quelqu'un peut m'éclairer sur les point 1,2,3 et 4 c'est sympa :D
Je vais écrire un nouveau message pour le point 5 qui est un peu à part.

ViPHP
xTG
ViPHP | 7331 Messages

27 nov. 2014, 15:38

1/ Dans la table tu as :
- mdp = hashage(grain_de_sel_utilisateur + mdp_utilisateur)
- grain de sel = grain_de_sel_utilisateur

2/ Si tu utilises un grain de sel fixe et qu'une personne malveillante le connait il pourra monter une rainbow table de toute pièce.
Par contre si tu changes de grain de sel pour chaque utilisateur il doit maintenant créer X rainbow table !!! ;)
(Et j'ai absolument décroché pour le reste de ce point...)

3/ Absolument rien compris à la phrase précédente donc je botte en touche !
Sauf pour :
Si on crée une concaténation automatique entre un mot de passe posté et un grain de sel aléatoire,
comment l'utilisateur pourrait-il être identifié comme ayant saisi le bon mot de passe?
Le grain de sel est dans la table, si tu as le nom de l'utilisateur tu peux récupérer son grain de sel.
Il ne s'agit en aucune façon d'en utiliser un autre que ce dernier...

4 / J'ai absolument pas suivi les autres messages et plus le temps de les lire désolé. :(

5/ Parce qu'il n'applique pas les mêmes règles pour les champs input. Il faut malheureusement utiliser autre chose pour protéger ces affichages là. (à ma connaissance il n'existe pas de fonction fournie par PHP)

Mammouth du PHP | 2278 Messages

27 nov. 2014, 16:22

J'interviens après la bataille :D mais j'ai trouvé ceci
http://www.openwall.com/phpass/
et là:
http://us2.php.net/manual/fr/function.crypt.php
remarque utiliseteur n 8
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

Eléphant du PHP | 290 Messages

27 nov. 2014, 17:56

Merci xTG et Sirakawa pour vos messages :D

Je crois comprendre :D

En fait, le sel aléatoire sert dans le cas où l'on veut qu'un programme donne un sel différent à chaque utilisateur.
Mais maintenant, si c'est nous qui attribuons d'office un sel à un utilisateur on n'a plus besoin de sel aléatoire.
C'est le cas lorsqu'on attribue déjà d'office un mot de passe à un utilisateur.
Pourquoi pas tant qu'à faire lui attribuer aussi le sel :mrgreen:
On choisit alors un sel différent pour chaque utilisateur.

Donc grâce à vous j'ai à priori tous les éléments en ma possession pour me lancer dans la programmation.
Mais j'aurais encore besoin de vous demander une chose :oops:
Ca me paraît important et ça devrait pas prendre trop de temps.
C'est à propos d'un message de AB (pas besoin de lire les messages antérieurs.
Oui, juste une précision : le grain de sable envoyé dans le formulaire doit être différent à chaque envoi du formulaire (ce qui est le cas dans mon exemple plus haut). Sinon, sans même pouvoir connaître le mot de passe, on pourrait néanmoins s'authentifier en renvoyant simplement le contenu du post. Si donc tu as un sel fixe pour chaque visiteur pour sauvegarde en bdd par exemple, il n'est pas suffisant à lui seul pour assurer l'unicité de la connexion.
Donc avec un simple hash du mot de passe en bdd, le javascript doit renseigner le formulaire avec quelque chose comme :
TOUT SÉLECTIONNER
hash(sel_unique_formulaire.hash(mot_de_passe))

et avec hash + sel en bdd :
TOUT SÉLECTIONNER
hash(sel_unique_formulaire.hash(mot_de_passe.sel_unique_visiteur))

Et dans tous les cas javascript doit bien évidemment supprimer le contenu du champ "mot_de_passe" du formulaire avant l'envoi vers le serveur sinon tout cela ne sert à rien :wink:

EDIT : la seconde hypothèse suppose de devoir faire une requête ajax pour connaître le sel du visiteur en bdd en fonction de son login
Pouvez-vous m'expliquer où il veut en venir avec l'avant-dernière phrase:
Et dans tous les cas javascript doit bien évidemment supprimer le contenu du champ "mot_de_passe" du formulaire avant l'envoi vers le serveur sinon tout cela ne sert à rien :wink:
Ca à l'air très important!!

Désolé encore pour le dérangement :oops:

ViPHP
xTG
ViPHP | 7331 Messages

27 nov. 2014, 19:08

C'est le fait que le javascript calcule le hash a envoyer.
Il ne sert donc plus à rien d'envoyer le mot de passe.
Mais surtout le but est de n'envoyer entre le client et le serveur que des données qu'un hacker ne pourra pas interpréter.
Donc si tu laisses l'envoi du mot de passe en clair... Il le verra et donc le hash envoyé il s'en tembouille un peu. :P

ViPHP
AB
ViPHP | 5818 Messages

27 nov. 2014, 22:08

il a l'air très compliqué le code javascript que tu m'a montré!!
Si tu parles de cet exemple de code le code javascript à comprendre est juste celui mentionné ci-dessous, le reste est une fonction de haschage sha 256 :
[javascript]<script language="javascript">
<!--
function doChallengeResponse(form) {

var str = form.utilisateur.value+'<?php echo $_SESSION["sel"]?>'+form.mot_de_passe.value;
form.reponse.value = SHA256(str);
form.mot_de_passe.value = "";

// 64 correspond à la longueur d'un sha 256 (condition à modifier si l'on change d'encodage)
if (form.mot_de_passe.value == '' && form.reponse.value.length == 64)
{
form.submit();
}
else return false;

}
// -->
</script>[/javascript]
Quand tu aura compris ces quelques lignes de code, tu auras compris le principe.

Dans mon exemple "$_SESSION["sel"]" est aléatoire (cf code php). C'est pour assurer l'unicité du post et de cette façon "form.reponse.value" n'est valable qu'une seule fois et un pirate qui récupérerait cette valeur ne pourra rien en faire directement.
Au mieux il devra créer une table de correspondance pour retrouver le mot de passe mais ça lui prendra du temps puisqu'il ne pourra pas se servir d'un dictionnaire.
Si $_SESSION["sel"] avait toujours la même valeur alors form.reponse.value aurait toujours la même valeur et ainsi il serait facile de renvoyer cette valeur dans un "faux formulaire" pour s'authentifier sans avoir besoin de calculer quoi que ce soit (même s'il ne connait pas le mot de passe il s'en fou).
De même si l'on effaçait pas le contenu du mot de passe en faisant form.mot_de_passe.value == '' , alors le mot de passe serait envoyé en clair dans le formulaire.
L'exemple de code est complet donc il te suffit d'analyser le code pour voir comment je fais. Comprends le avant de te poser d'autres questions.

Là je n'ai jamais parlé du sel qui servirait éventuellement pour ta bdd et qui lui ne varie pas (donc ne pourrait pas servir à lui seul pour assurer l'unicité de form.reponse.value). Le code donné en exemple suppose que le pass est simplement hasché sans sel en bdd.
Si tu te sert d'un sel pour ta bdd il faudrait donc le rajouter dans le code côté javascript et côté php, mais chaque chose en son temps tu verras cela après (il faut séparer les problèmes).

Mammouth du PHP | 2278 Messages

28 nov. 2014, 11:13

Sur le mot de passe
C'est pourquoi j'ai signalé ce site :
le sel est embarqué dans le mot de passe codé, et ce sont les procédures prévues qui créent le mot de passe codé enlehachant plusieurs fois et qui en assurent la vérification.
On 'a ainsi aucun sel à stocker
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

ViPHP
AB
ViPHP | 5818 Messages

05 déc. 2014, 07:11

Sur le mot de passe
C'est pourquoi j'ai signalé ce site :
le sel est embarqué dans le mot de passe codé, et ce sont les procédures prévues qui créent le mot de passe codé enlehachant plusieurs fois et qui en assurent la vérification.
On 'a ainsi aucun sel à stocker
Effectivement la méthode "crypt" de php est très pratique pour protéger ses mots de passe en bdd mais il n'est pas possible d'utiliser ce système avec la méthode d'authentification de sel aléatoire concaténé avec le mot de passe côté client. En effet on ne pourrait pas faire de comparaison côté php avec le hash enregistré en bdd qui est construit avec un sel embarqué.

C'est en fonction de la possibilité ou non d'avoir une connexion sécurisée pour l'authentification qu'on peut choisir la meilleure protection.

- Avec ssl on peut transmettre le pass en clair puisque la connexion est cryptée. En mode parano on peut éventuellement le hasher - mais pas le saler- côté client avant de l'envoyer vers php et comparer avec le résultat du crtyp du mot de passe enregistré en bdd.
Ssl procure la sécurité de la transmission et "crtyp" avec ses sels embarqués permet une bonne protection des enregistrements en bdd. Et comme avec crtyp on peut doser la protection en augmentant le coût processeur avec un paramètre également embarqué dans chaque mot de passe, c'est une excellente solution qui permet de faire des distinctions avec par exemple un coût processeur plus important pour un admin.
C'est la solution "naturelle" pour les utilisateurs de sll.

- Sans ssl la connexion n'est pas sécurisée et on est pas à l'abri d'un sniffeur de réseau, en particulier si l'on se trouve derrière un proxy d'entreprise, ou une connexion depuis un lieu public, une connexion wifi piratée etc. On peut se faire voler sa session ce qui est potentiellement très grave mais qui demande au pirate d'intervenir durant la durée de la session. Il est plus intéressant pour lui d'enregistrer simplement le mot de passe (s'il est transmis en clair) ou sinon de pouvoir se connecter quand il le veut avec le post enregistré (qui sera toujours le même si le mot de passe est simplement hashé). D'où l'intérêt du sel aléatoire concaténé au mot de passe avant hashage de l'ensemble qui permettra de rendre le post unique (valable une seule fois). En plus cela permet une meilleur protection du hash en rendant l'utilisation de dictionnaire impossible si le pirate veut trouver le mot de passe.
Mais le problème est que l'on ne pourra pas utiliser des fonctions comme "crtyp" côté php car on ne pourra pas faire de comparaison des résultats avec le hash généré par javascript (s'il contient un sel aléatoire). Pour protéger ses mots de passe en bdd on devra donc se contenter de les hasher. Ou les hasher avec un sel mais qui sera identique pour toute la table (pour pouvoir le passer dans la construction du hash en javascript). Ou sinon on peut envisager de faire une première requête en ajax en fonction du login et qui ramènerait le sel correspondant enregistré en bdd avant de le concaténer au mot de passe puis hasher les deux, puis concaténer au sel aléatoire de session (qui permet l'unicité du post) et de hasher le tout en javascript avant d'envoyer le post en php. Cette dernière solution permet de se protéger au mieux d'un piratage de la bdd avec un sel différent pour chaque mot de passe hashé en bdd mais cela complique un peu les choses. Et côté bdd on est pas tout à fait au même niveau de protection qu'avec "crtyp". Après si on est certain que l'on ne se fera jamais pirater son réseau on pourrait se contenter de "crypt" en bdd et laisser passer les mots de passe en clair... mais un piratage de réseau est assez facile, un piratage de bdd normalement beaucoup moins (si pas de grosses failles dans le code) et donc sans sll je trouve que c'est le meilleur compromis que l'on puisse faire entre protection réseau et protection des données bdd :)

Evidemment ssl + "CRYPT_BLOWFISH" ou "CRYPT_SHA512" est l'idéal, plus facile et sécurisé sur les deux plans :wink:

Eléphant du PHP | 290 Messages

10 déc. 2014, 09:36

Bonjour,

Je reviens vers vous après avoir lu plusieurs fois le tuto ainsi que vos messages envoyés.

J'aurais quelques petites questions, pour la plupart dans un but de confirmation.

1) On utilise du code javascript alors que php gère lui-même très bien les fonctions de hash et les concaténations de variables.
La raison est-elle la suivante:
on ne veut pas faire passer en clair les mots de passe dans les feuilles php car cela signifie que les mots de passe arrivent
sur le serveur, et dans le cas d'un attaque réseau le pirate guette ce qu'il peut trouver sur le serveur (réseau commun place publique,
réseau commun entreprise,...)
Donc on utilise js car tout est alors traité par le navigateur de l'ordinateur du visiteur seulement,
et la variable mot de passe est en plus vidée avant l'envoi de la variable hashée concaténée.
?

2) Dans ce cas, ne serait-il pas judicieux d'ajouter une ligne pour vider aussi la variable str dans le code js?
La variable str hashée serait envoyée sur le serveur mais pas la variable str non hashée.

3) Je compte mettre dans ma base de données le hashage de login utilisateur + mot de passe
dans une colonne et un grain de sable fixe mais différent par utilisateur dans une autre.
Pour prendre en compte ce grain de sel fixe si je comprends bien je vais devoir
demander avec une requête asynchrone de me récupérer sur le serveur le grain
de sable de l'utilisateur dont le nom vient d'être écrit dans le champs utilisateur du formulaire.
Donc je vais devoir faire en sorte que cette requête soit déclenchée par un événement onBlur
sur ce champs.
C'est bien ça?
Ensuite, dans mon code js je concatène le grain de sel fixe au mot de passe,
je hashe le tout, je concatène l'ensemble au grain de sel aléatoire et je hashe à nouveau le tout.
J'envoi ma nouvelle variable sur le serveur.
Un code php va récupérer dans ma bdd mon ensemble hashé mot de passe+sel fixe utilisateur,
puis concaténer cet ensemble au grain de sel aléatoire et hasher à nouveau le tout.
Ensuite je compare ma nouvelle variable créée côté php et ma nouvelle variable créée côté js.
L'égalité ou l'inégalité entre les deux variables détermine si l'utilisateur peut rentrer ou pas dans sa session.
C'est toujours ça?

4) Enfin, je dois m'assurer sur chaque page de session que le grain de sel aléatoire est bien présent,
sinon l'utilisateur sort de la session avec un header.
Sans ça une attaque réseau permettrait de rentrer dans la session de n'importe qui.
C'est bien ça?

ViPHP
xTG
ViPHP | 7331 Messages

10 déc. 2014, 14:22

1/ Tout à fait.

2/ Ce qui importe c'est form.reponse.value (qui est le hash de str) et non str qui restera entièrement côté client.
Si le client est infecté par un pirate alors hash ou non en JS ça servira au final à rien.

3/ Tu m'as un peu perdu... Mais oui c'est tout à fait ça.

4/ Je ne vois pas ce que ça donnerait comme sécurité, pour moi c'est inutile.
Une fois que la session est ouverte, vu que les variables de sessions sont stockées côté serveur il suffit juste de l'id de session (qui est la seule information côté client qui permet de faire le lien avec la session serveur) pour se l'approprier ainsi que toutes les variables qui sont dedans.
Mais je n'ai pas lu les articles et donc tu as peut être raison. :)

Eléphant du PHP | 290 Messages

10 déc. 2014, 14:57

Merci pour tout :D

Puis-je te poser quelques questions sur 2) xTG:
l'infection du client par un pirate, ça peut avoir quoi comme répercution sur mon site?
Je dois utiliser un clavier virtuel comme me l'a conseillé AB dans ce cas?
Si l'ordinateur du client est infecté et que je n'utilise pas de clavier virtuel je risque beaucoup?

Si AB voit mon message peut-être pourra-t'il répondre à la question 4).

Merci encore :D

Allez, je me remets au travail :)

Mammouth du PHP | 2278 Messages

10 déc. 2014, 16:13

Il ne s'agit pas de parler de crypt, mais de son empoi:
J'interviens après la bataille :D mais j'ai trouvé ceci
http://www.openwall.com/phpass/
et là:
http://us2.php.net/manual/fr/function.crypt.php
remarque utiliseteur n 2
Cette fonction embarque le sel, qui est tiré aléatoirement,dans le mot de passe codé, et c'est cette chaine de caractères qui est stockée/ en Bdd. Nulle part le sel ne parait en clair, et le sel est différent pour chaque mot de passe crypté.
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

ViPHP
AB
ViPHP | 5818 Messages

10 déc. 2014, 17:07

Salut

3/ Si le client est infecté par un keylogger, le pirate pourra récupérer les frappes clavier et donc le login et le mot de passe. Bah les risques sont ceux que les droits de l'authentification autorisent. Si c'est pour gérer ses propres messages sur un forum par exemple, le pirate pourra modifier les messages du client piraté mais pas les autres. Si l'authentification donne les droits pour supprimer des rubriques alors il pourra supprimer des rubriques etc.
Mais bon cette attaque suppose une faille dans le système antivirus/parre feu du visiteur et une imprudence du visiteur qui doit cliquer sur un lien de messagerie non connu qui installera le virus, ou télécharger et installer un fichier infecté, ou sinon la complicité d'une personne qui a accès à l'ordinateur du visiteur. Ensuite il faut que le pirate récupère les informations avant que le virus soit détecté mais après que le visiteur se soit connecté sur le site. C'est donc pas si simple et c'est pour cela que seules les connexions bancaires utilisent les claviers virtuels car il faut aussi penser au confort de l'utilisateur et cette solution est assez contraignante.

4/ Oui enfin le principe est de contrôler l'existence d'une variable de session définie lors du succès de l'authentification. Tu peux bien mettre ce que tu veux dedans et pourquoi pas le grain de sel mais en fait peu importe puisque les variables de session sont spécifiques au navigateur avec l'id de session stocké dans un cookie du navigateur. Et comme l'a dit xTG, si un pirate a piraté ta session il aura accès à toutes les variables de session donc en fait peu importe la valeur de cette variable de session l'important est de contrôler son existence.

Eléphant du PHP | 290 Messages

10 déc. 2014, 17:47

Merci beaucoup pour 3)
J'ai bien compris :D

Il me reste plus qu'un truc à comprendre:
c'est l'intérêt et l'utilisation d'un grain de sel aléatoire,
par rapport à un grain de sel fixe par utilisateur.

Si je peux revenir là-dessus:
dans ma bdd je n'aurai jamais de grain de sel aléatoire car
lors de la comparaison entre les données saisies et celles en bdd
je n'aurai jamais d'égalité du fait de l'aléa créé par le grain de sel aléatoire.
C'est juste?
Par contre, les données de la bdd sorties sur un fichier php et concaténées
au même grain de sel aléatoire que celui utilisé pour la concaténation
des données postées permet d'obtenir l'égalité s'il y a l'égalité,
car le grain de sel aléatoire utilisé dans les deux cas c'est le même.
C'est juste?
Le but du grain de sel aléatoire permet que chaque session soit entre autres
conditionnée par la présence d'une valeur de grain de sel aléatoire absolument unique
pour un même utilisateur et pour une seule session dans sa vie
=> s'il ouvre une autre session dans trois jours le grain de sel aléatoire de ce même utilisateur
sera différente, car si l'utilisateur est bien le même par contre la session n'est plus la même.
Est-ce que je comprends bien ou pas?
Si c'est tout juste, en quoi ce grain de sel aléatoire protège mieux la session du fait de sa nature aléatoire?

Je voudrais vous demander aussi si quelqu'un veux bien voir mon Ajax en mp.
Je l'ai créé cet après-midi et c'est seulement le deuxième que je crée dans ma vie.
J'ai du code dans mon formulaire, une page js et une page php.
Ca serait vraiment sympa :D

Quelque soit votre réponse je vous remercie déjà pour toute l'aide apportée.

Après normalement c'est tout terminé.

ViPHP
AB
ViPHP | 5818 Messages

10 déc. 2014, 19:16

Merci beaucoup pour 3)
J'ai bien compris :D

Il me reste plus qu'un truc à comprendre:
c'est l'intérêt et l'utilisation d'un grain de sel aléatoire,
par rapport à un grain de sel fixe par utilisateur.

Si je peux revenir là-dessus:
dans ma bdd je n'aurai jamais de grain de sel aléatoire car
lors de la comparaison entre les données saisies et celles en bdd
je n'aurai jamais d'égalité du fait de l'aléa créé par le grain de sel aléatoire.
C'est juste?
Par contre, les données de la bdd sorties sur un fichier php et concaténées
au même grain de sel aléatoire que celui utilisé pour la concaténation
des données postées permet d'obtenir l'égalité s'il y a l'égalité,
car le grain de sel aléatoire utilisé dans les deux cas c'est le même.
C'est juste?
OK t'as compris

Pour la suite t'as pas compris.
Le sel aléatoire permet que la valeur de la variable $_POST['reponse'] qui est envoyée dans le formulaire par javascript avec "form.reponse.value = SHA256(str);" soit toujours différente (référence code). Si ce n'était pas le cas alors en piratant cette valeur par sniffage du réseau on pourrait s'authentifier en envoyant cette valeur puisque c'est cette valeur que tu compare pour établir la validité en php. Le pirate ne connaîtrait pas le mot de passe pour autant (sauf à utiliser la force brute pour casser le hash) mais il pourrait quand même se connecter facilement en envoyant cette même valeur de post. Remarque que je n'ai pas parlé de session.

Là on a fait la sécurisation du formulaire en protégeant pour le mieux la transmission dans les tuyaux pour une connexion non sécurisée. Le mieux étant d'utiliser une connexion sécurisée type ssl puisque dans ce cas le pirate n'a accès à rien.

Maintenant reste à protéger les mots de passe dans la bdd. Et comme il est conseillé de saler également ses mots de passe en bdd pour rendre difficile le déchiffrage en cas de piratage de la bdd, il faudra passer ce sel côté client (en complément du sel aléatoire qui lui sert pour l'unicité du post) pour faire une construction de hash que tu pourras comparer côté php. Si chaque sel (de bdd) est différent pour chaque utilisateur, c'est le rôle de la requête ajax dont j'ai parlé plus haut, de rapatrier ce sel en fonction du login pour construire le hash qui sera construit et passé en javascript dans $_POST['reponse']. Compris ?

Bah on peut imaginer différentes solutions, le tout est que la construction de $_POST['reponse'] en javascript puisse être comparée à son équivalent côté php.

Après si on utilise ssl c'est beaucoup plus simple puisque l'on peut zapper la protection de $_POST['reponse']. Le post peut donc être envoyé sans traitement javascript et on a juste à se concentrer sur la protection des mots de passe en bdd (et donc employer la fonction crypt de php qui est plus sécurisée car plus couteuse en ressource processeur).