PHP introduit une nouvelle API de gestion des mots de passe
Fondée sur l'algorithme de hashage sécurisé

Les rubriques (actu, forums, tutos) de Développez
Tags
PHP
Réseaux sociaux


 Discussion forum

Le , par grunk, Modérateur
La RFC "password_hash" vient d'être acceptée et sera ajoutée à PHP 5.5

Pourquoi cette nouvelle API ?
Généralement lorsque l'on parle de hash de mot de passe les utilisateurs se tournent vers md5 ou sha, deux algorithmes qui ne devraient plus être utilisés (nombreuses rainbow tables, failles dans l'algorithme ...)

Une solution efficace pour hasher ses mots de passe est l'utilisation de bcrypt mais malheureusement peu de développeurs l'utilisent notamment à cause de la fonction crypt() de php qui n'est pas des plus faciles à utiliser.

Cette nouvelle API vient donc combler ce manque avec une solution simple et efficace pour protéger ses mots de passe.

Comment ça marche ?
La RFC propose quatre nouvelles fonctions, deux nous intéressent particulièrement puisqu'elles permettent de hasher et vérifier un hash :

Code :
1
2
password_hash($password, $algo, $options = array()); 
password_verify($password, $hash);
Pour hasher et vérifier un mot de passe, c'est donc très simple :

Code :
1
2
3
4
5
6
7
8
$password = "motdepasse"; 
$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10)); 
  
if (password_verify($password, $hash)) { 
    echo 'Mot de passe OK'; 
} else { 
    echo 'Erreur mot de passe'; 
}
Vous aurez remarqué la spécification d'un coût dans les options, ce coût définit la complexité du mot de passe. Plus le coût est élevé plus le hash est long à obtenir et par conséquent difficile à attaquer.

Avec cette API, plus besoin de se soucier des salts aléatoires, tout est géré en interne, le développeur n'a plus qu'à protéger son mot de passe.

La compatibilité future n'a pas été oubliée puisque grâce à password_needs_rehash il sera possible de rehasher un mot de passe si l'algorithme par défaut évolue.

Je n'ai pas PHP 5.5 !
Tout n'est pas perdu , il existe de nombreuses implémentations de bcrypt en PHP. Tel que phpass

Toutes les infos et des exemples sur la RFC password_hash : voir


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :


 Poster une réponse

Avatar de Grabeuh Grabeuh
http://www.developpez.com
Membre expérimenté
le 17/09/2012 2:10
Citation Envoyé par matll  Voir le message
Je ne suis pas expert non plus, mais je suis d'accord avec Neckara. Une attaque de type man in the middle permet ici facilement de récupérer un mot de passe (sauf erreur de ma part). Le mieux n'est-il pas d'encoder le mot de passe côté client avant envoi ?

Déjà, si ton utilisateur est tombé dans le panneau d'une attaque par phishing et a rentré son mdp sur une page qui n'est pas la tienne, ça ne changera strictement rien au fait que le pirate aura son mot de passe en clair et pourra l'utiliser sur ta page. Ou pire, il peut lire le code source de ton JavaScript servant à effectuer le hashage et le reproduira sur sa page d'attaque, ce qui fait qu'il aura le mot de passe et l'utilisateur ne se rendra compte de rien.

La première chose qu'on apprend en sécurité, c'est qu'il ne faut JAMAIS faire confiance au client. Les données malicieuses, intentionnelles ou non, viennent dans 99% des cas du client.
Tu as la main sur le code qui est situé sur ton serveur et si ton application est compromise de l'intérieur, tu es en mesure de réagir. Par contre, tu ne sais pas qui est ton client ni comment il agit car le protocole HTTP fait que tu n'as que les informations qu'il veut bien te donner, et ces informations peuvent de toute façons être falsifiées.

Encoder le mot de passe côté client revient à considérer comme des faits des suppositions impossibles à vérifier, ou alors qui te demanderont de gérer plusieurs cas selon que le mot de passe sera envoyé en clair ou en hashé et donc compliquera inutilement ton travail de développeur :
  • Le client est un navigateur utilisant Javascript (adieu les lecteurs optiques pour personnes malvoyantes ou certains terminaux mobiles bas de gamme)
  • Javascript est activé (adieu les entreprises où le DSI ou l'admin ou même l'utilisateur lui-même un peu trop paranoïaque a bloqué le JS)


Les seuls moyens suffisamment efficaces à ce jour de se protéger contre les attaques man in the middle sont une connexion sécurisée type SSL et une sensibilisation des utilisateurs aux questions de sécurité des applications web.
Pour rendre ceci encore plus efficace, une authentification forte à 2 facteurs : ajouter au mot de passe un code à usage unique et limité dans le temps envoyé par SMS, par une clé type RSA SecurID ou encore par une application spécifique pour smartphone. Si le voleur a le mot de passe, il n'aura pas l'élément physique nécessaire à l'attaque et pourra difficilement automatiser l'attaque à cause du laps de temps de validité du code.

Mais comme toujours, sécurité et facilité d'utilisation sont généralement antagoniste, et plus on rajoute des couches pour protéger son site, plus on le rend fastidieux à utiliser (et surtout compliqué à maintenir)
Et surtout, aucune sécurité n'est inviolable, car tout programme informatique est contournable, soit par un autre programme, soit par ingénierie sociale.

Citation Envoyé par Neckara
Je ne suis pas expert en sécurité mais ça veut dire qu'à un moment ou un autre, le serveur est capable de retrouver le mot de passe en clair et je doute que ce soit une bonne chose... non?

Mettons que le propriétaire du serveur en fasse un usage illégal et vole les mots de passe de ses utilisateurs.
S'il veut le voler pour l'utiliser ailleurs (vu que la plupart des gens utilisent le même mot de passe un peu partout, de leur compte facebook à leur banque en ligne) , pourquoi attendre que l'utilisateur retape son mot de passe une nouvelle fois ? Il enregistrera la version en clair dès la création du compte.
S'il veut usurper l'identité d'un utilisateur sur son propre site, il n'a qu'à modifier le mot de passe et lui donner la valeur qu'il veut, et ensuite remettre l'ancien hash à la place, ni vu ni connu.

De toute façons, il faut bien qu'à un moment, le serveur puisse faire la comparaison. Et comme je l'a dit plus haut, le client n'est pas digne de confiance. C'est donc forcément au serveur de s'occuper de rehasher le mot de passe pour pouvoir la faire. Car tu es seul à avoir la main dessus (du moins, en théorie) est tu es donc capable de juger de la confiance que tu peux accorder à ton propre code.
Avatar de Neckara Neckara
http://www.developpez.com
Responsable Sécurité
le 17/09/2012 6:52
Je sais qu'il ne fait jamais faire confiance au client, mais dans ce cas là envoyer le hash ou le mot de passe revient au même niveau sécurité.

Pour les spécificités côtés clients hors navigateur utilisés (JavaScript activé ou non, etc.), personnellement je ne m'en occuperais pas (juste mettre un petit message) quitte à perdre une petite partie du public (bon après je ne suis pas professionnel).
Mais rien ne dit que le JavaScript n'est pas obligatoire pour l'utilisation du site ou que le client utilise bien du JavaScript (ex : client en C++).

Mais dans mon raisonnement, je pensais que d'envoyer le hash plutôt que le mot de passe réduit le "moment" où il serait possible (mais très faiblement probable) de retrouver le mot de passe.
De plus comme on ne peut jamais garantir une sécurité à 100%, si jamais une faille est découverte, le mot de passe n'est pas mis en danger.
Avatar de gene69 gene69
http://www.developpez.com
Membre Expert
le 19/09/2012 15:44
je me souviens que j'avais écrit un systeme de échange de mdp "sécurisé" (lol) sur du http avec un nomus pour vérifier la formule hash(hash(password) xor nomus) en provenance d'une lib js du client. Pas de mdp stocké en clair, et pas de mdp qui circulent en clair. la sécu s'arrêtait là.

parce qu'envoyer simplement le hash sur le réseau fait que l'on transforme une empreinte avec un super niveau d'entropie en un mot de passe en clair de longueur fixe. on ne doit envoyer que des "transformés" le réseau. Celui qui comprends pas qu'un hash peut être bruteforcé ou rejoué... est une proie.
Avatar de X_Cli X_Cli
http://www.developpez.com
Invité régulier
le 21/09/2012 9:01
Ce qu'il ne faut pas lire quand même... la cryptographie, ça ne s'improvise pas. Je recommande la lecture de "Applied Cryptography" et de "Secret and Lies" de Schneier pour éviter de raconter des bêtises à ce sujet

MD5 (et encore davantage SHA1) n'ont aucun problème de sécu à ce jour pour ce qui est de leur utilisation pour le hachage de mot de passe. La dernière cryptanalyse dont j'ai science sur les attaques par pré-image (retrouver un antécédant à un condensat) était de l'ordre de 2^123, alors qu'on peine à atteindre (en fait, on en est loin) les 2^100 en terme depuissance de calcul. Ce n'est pas le cas de leur usage lorsqu'il y a risque d'attaques par *collision*, qui est ce jour considéré comme triviales pour MD5.

Hacher le mot de passe coté client est inutile : le secret n'est plus le mot de passe, mais son condensat : apport en capacité d'authentification : zéro-toto. De toutes les manières, si la sécu vous importe sur votre mécanisme d'auth (et elle devrait), utilisez TLS. On peut avoir des certificats pour 0 à 15 euros par an, qui suffisent amplement pour un petit site perso.
Se substituer à TLS est TOUJOURS une mauvaise idée.

Concernant le salt : n'utilisez jamais de sel constant sur plusieurs utilisateurs. Un par user.
Privilégiez des salts vraiment aléatoires (pas rand(om)(), donc). Prévoyez un salt qui complète la taille du bloc de votre algo de hachage, au mini, et mieux un salt qui fasse au moins la taille du bloc (les tailles de blocs sont dispos dans toute bonne doc sur les-dits algo). Idéalement, faites un open de urandom sur les systèmes unix, voire de /dev/random si vous avez un générateur d'entropie à disposition (je ne parle pas de votre femme, messieurs :p) : le PRNG de PHP a été prouvé maintes fois peut fiable : autant l'éviter comme la peste pour la crypto.

"Mais pour qui il se prend, celui là ?" Pour qqn qui fait ça à longueur de journée, de se renseigner, lire et se former pour donner les meilleurs conseils sécu à ses clients
Avatar de grunk grunk
http://www.developpez.com
Modérateur
le 21/09/2012 9:16
Citation Envoyé par X_Cli  Voir le message
Ce qu'il ne faut pas lire quand même... la cryptographie, ça ne s'improvise pas. Je recommande la lecture de "Applied Cryptography" et de "Secret and Lies" de Schneier pour éviter de raconter des bêtises à ce sujet

On est quand même d'accord sur le fait que md5 et sha sont vulnérables à cause des tables de comparaison (combien d'utiilisateur n'utilise pas un mot de passe "simple" ?) qu'on trouve partout et de leur risque de collision ?
Avatar de X_Cli X_Cli
http://www.developpez.com
Invité régulier
le 21/09/2012 9:38
Citation Envoyé par grunk  Voir le message
On est quand même d'accord sur le fait que md5 et sha sont vulnérables à cause des tables de comparaison (combien d'utiilisateur n'utilise pas un mot de passe "simple" ?) qu'on trouve partout et de leur risque de collision ?

Non, ce qui est vuln, c'est d'utiliser des sels très courts, comme "b9" ou autre. Mais si on fournit un salt avec ne serait ce que 4 octets complètement aléatoires (2^32 valeurs), ca fait 4 milliards de rainbow table à générer pour avoir des "dicos" précalculés. Improbable.

Par ailleurs, il y a des rainbow aussi pour les autres algo...
Avatar de grunk grunk
http://www.developpez.com
Modérateur
le 21/09/2012 9:52
Citation Envoyé par X_Cli  Voir le message
Non, ce qui est vuln, c'est d'utiliser des sels très courts, comme "b9" ou autre. Mais si on fournit un salt avec ne serait ce que 4 octets complètement aléatoires (2^32 valeurs), ca fait 4 milliards de rainbow table à générer pour avoir des "dicos" précalculés. Improbable.

Par ailleurs, il y a des rainbow aussi pour les autres algo...

Je parlais d'une utilisation sans grain de sel , comme on le trouve dans la majorité des cas , hélas.
Avatar de Fladnag Fladnag
http://www.developpez.com
Membre Expert
le 21/09/2012 11:05
Citation Envoyé par X_Cli  Voir le message
Hacher le mot de passe coté client est inutile : le secret n'est plus le mot de passe, mais son condensat : apport en capacité d'authentification : zéro-toto.

Je ne serais pas aussi catégorique.
Si tu hache le pass avant l'envoi coté client AVEC un salt fourni par le serveur (unique par client, et unique par demande de connexion), comme le système d'authentification de SPIP, tu fait circuler sur le réseau un hash qui n'est valable que pour un utilisateur et surtout une seule utilisation.
Avatar de X_Cli X_Cli
http://www.developpez.com
Invité régulier
le 22/09/2012 8:46
@grunk: dans ce cas, ce ne sont pas les algos qui sont en tort mais leur mise en oeuvre.

@Fladnag: l'algo que tu décris est une authentification par challenge/response : ce n'est pas un salt mais un nonce qui est envoyé. En l'occurence, cela ne dit rien sur la façon dont est stocké le mot de passe dans la base : si le token est généré par le hachage du mot de passe avec le nonce, alors le mot de passe doit carrément être stocké en clair ou de manière réversible dans la base. Vu l'historique de sécurité de SPIP, ca m'inquièterait, mais ne m'étonnerait pas.
De plus, cette authentification est parfaitement inutile, et est juste l'expression déraisonnable de geeks du Javascript : au travers de Https, un tel mécanisme est parfaitement superflu, puisque la confidentialité est déjà assurée par TLS. Si cela transiste à travers HTTP, alors le JS qui effectue le traitement n'est pas garanti fiable : il peut avoir été altéré par un attaquant en position de faire un Man In The Middle (le même qui écoute le mot de passe en clair quand il transite ainsi), et par exemple exfiltrer le mot de passe avant son utilisation dans la génération du condensat.

En un mot: TLS.
En plus de mots : suivez la formation SANS Dev522 (Web Application Security Essentials), qui détaille tous ces problèmes très bien (ce n'est pas de la pub, il y a plusieurs centres de formation)
Avatar de Fladnag Fladnag
http://www.developpez.com
Membre Expert
le 22/09/2012 11:45
Citation Envoyé par X_Cli  Voir le message
En l'occurence, cela ne dit rien sur la façon dont est stocké le mot de passe dans la base : si le token est généré par le hachage du mot de passe avec le nonce, alors le mot de passe doit carrément être stocké en clair ou de manière réversible dans la base.

Rien n'oblige le pass a être codé de manière réversible. Tu peux très bien garder dans la base une version haché par du md5 qu'il est possible de recoder en JS afin d'obtenir le même hash que ce qu'il y a dans la base. Le jeton envoyé a l'utilisateur n'est pas généré uniquement a partir du pass, mais a partir d'un salt généré a partir de la milliseconde de demande de connexion et d'une combinaison qui d'autre champs (tu peux utiliser le password mais aussi le login par exemple, ou autre, genre le mail, l'age, etc...)

Citation Envoyé par X_Cli  Voir le message
De plus, cette authentification est parfaitement inutile, et est juste l'expression déraisonnable de geeks du Javascript : au travers de Https, un tel mécanisme est parfaitement superflu, puisque la confidentialité est déjà assurée par TLS. Si cela transiste à travers HTTP, alors le JS qui effectue le traitement n'est pas garanti fiable : il peut avoir été altéré par un attaquant en position de faire un Man In The Middle (le même qui écoute le mot de passe en clair quand il transite ainsi), et par exemple exfiltrer le mot de passe avant son utilisation dans la génération du condensat.

Aucun système de sécurité ne protège complètement d'une attaque Man In The Middle. Même quand tu fait de l'https, a moins de forcer l'utilisation de routes TCP/IP différentes lors de l'envoi d'information sur le réseau, ou d'échanger les certificats de manière réellement sécurisée (genre sur une clé USB dans le monde physique), le MITM interceptera l'échange initial avec les certificats et les clés publiques et sera donc en mesure de faire croire a A qu'il discute avec B, et a B qu'il discute avec A en introduisant son propre certificat et en décodant / recodant la requête. Même les autorités de certification se font pirater et il est possible de générer de "faux-vrais" certificats qui ne demandent pas de confirmation a l'utilisateur final... et même avec un certificat envoyé par le MITM non "officiel", la plupart des utilisateurs l'accepterons parce qu'ils n'auront aucun moyen de déterminer facilement que c'est un faux.

La solution de SPIP n'est évidemment pas parfaite, mais elle est un bon compromis relativement facile a mettre en place quand tu n'a pas besoin d'un niveau de sécurité digne d'une interface web de lancement de missile nucléaire ;o)

Après on peux aussi se demander l’intérêt de crypter des échanges quand on sait que la majorité des serveurs mails autorisent l'envoi des mots de passe mail en clair, mais c'est un autre débat...
Avatar de X_Cli X_Cli
http://www.developpez.com
Invité régulier
le 22/09/2012 19:21
Citation Envoyé par Fladnag  Voir le message
Rien n'oblige le pass a être codé de manière réversible. Tu peux très bien garder dans la base une version haché par du md5 qu'il est possible de recoder en JS afin d'obtenir le même hash que ce qu'il y a dans la base. Le jeton envoyé a l'utilisateur n'est pas généré uniquement a partir du pass, mais a partir d'un salt généré a partir de la milliseconde de demande de connexion et d'une combinaison qui d'autre champs (tu peux utiliser le password mais aussi le login par exemple, ou autre, genre le mail, l'age, etc...)

Rien n'oblige à ce qu'il le soit. Mais de toute façon, le sujet n'est pas comment est envoyé le mot de passe, mais comment il est stocké. En l’occurrence, le protocole expliqué pour SPIP est un challenge/response et sans information supplémentaire, il ne permet nullement de déterminer quelle est la méthode de stockage.
Le point intéressant est que tant que le JS n'est pas sécurisé avec une signature numérique ou un contrôle d'intégrité vérifiable cryptographiquement, alors il peut être altéré par un attaquant en coupure, et la sécurité qu'il apporte ne vaut pas plus que du pipi de chat

Après, on peut considérer qu'il s'agit de "défense en profondeur" : si l'attaquant parvient à casser la confidentialité du tunnel TLS, alors il ne verra pas le mot de passe transiter en clair sur le canal TLS.
Ce scénario est absurde car si un attaquant est en mesure de casser la confidentialité de TLS, il est très probablement en mesure de casser également son intégrité...

Donc en résumé :
Cryptographie JS sans TLS : aucun apport de sécurité, zéro-toto.
Cryptographie JS avec TLS : aucun apport de sécurité : TLS fait déjà tout le travail, et avec du code probablement mature, et écrit et/ou vérifié par des cryptographes : intérêt : zéro-toto.

Le seul intérêt que j'entrevois à faire de la crypto en JS, d'une manière générale, est si l'intégrité du script JS est cryptographiquement vérifié et si l'on a besoin de faire de l'AJAX cross-domain avec un tiers qui supporte la crypto dans son code coté-serveur mais que son (mauvais) hébergeur ne supporte pas TLS.
Sinon, aucun intérêt, si ce n'est avoir l'impression de se la toucher.

Citation Envoyé par Fladnag
Aucun système de sécurité ne protège complètement d'une attaque Man In The Middle. Même quand tu fait de l'https, a moins de forcer l'utilisation de routes TCP/IP différentes lors de l'envoi d'information sur le réseau, ou d'échanger les certificats de manière réellement sécurisée (genre sur une clé USB dans le monde physique), le MITM interceptera l'échange initial avec les certificats et les clés publiques et sera donc en mesure de faire croire a A qu'il discute avec B, et a B qu'il discute avec A en introduisant son propre certificat et en décodant / recodant la requête. Même les autorités de certification se font pirater et il est possible de générer de "faux-vrais" certificats qui ne demandent pas de confirmation a l'utilisateur final... et même avec un certificat envoyé par le MITM non "officiel", la plupart des utilisateurs l'accepterons parce qu'ils n'auront aucun moyen de déterminer facilement que c'est un faux.

Je suis l'auteur de l'article sur la sécurité de PKIX et comment DNSSEC permet d'améliorer cette sécurité, qui est actuellement en kiosque dans le dernier numéro de MISC (n°63).
Je résumerai mon point par : si ton ennemi est une entité (que d'aucuns appelle Men-In-Black) étatique ou mafieuse ayant la capacité de casser une Autorité de Certification ou d'obtenir un CA valide et ayant la créance des navigateurs, ce n'est pas de la crypto JS qui va sauver ton site
Pour tous les autres, TLS tient, et suffit.

Pour ce qui est de l'utilisateur qui valide un certificat invalide : on se trompe de cible : l'objectif d'assurer la confidentialité du mot de passe du client, et son stockage sécurisé est avant tout une obligation de moyen en vue de prévenir toute action en justice contre ton employeur pour faute dans la sécurisation de données personnelles.

Si un utilisateur valide un certificat invalide, d'un point de vue légal, ce n'est pas ton problème, et tu n'es pas en faute. Je ne dis pas que ce n'est pas triste, mais pour ta part, tu as fait tout ce qui était nécessaire pour que ça n'arrive pas, et tu peux difficilement faire plus (à part utiliser HSTS, et le certificate pinning, qui provoque un hard-fail, sous Chrome).

Citation Envoyé par Fladnag
La solution de SPIP n'est évidemment pas parfaite, mais elle est un bon compromis relativement facile a mettre en place quand tu n'a pas besoin d'un niveau de sécurité digne d'une interface web de lancement de missile nucléaire ;o)

Non, elle est l'exemple typique de l'utilisation de moyens cryptographiques et de sécurité sans avoir fait une étude de risques et compris contre quoi on se battait.
Utiliser un Challenge/Response en JS au travers de HTTP dans l'objectif de sécuriser un mot de passe est d'une inutilité flagrante en terme de sécurité et d'une dangerosité patente pour la disponibilité du service car elle complexifie sans le moindre intérêt le mécanisme. Cela le rend donc plus difficile à comprendre, et à déboguer sans aucun apport en échange.
En un mot : KISS.

Citation Envoyé par Fladnag
Après on peux aussi se demander l’intérêt de crypter des échanges quand on sait que la majorité des serveurs mails autorisent l'envoi des mots de passe mail en clair, mais c'est un autre débat...

Autre débat, mais oui,et l'énoncé n'est pas clair : si on parle de mots de passe d'accès aux sites, alors c'est effectivement à bannir : un mot de passe ne devrait JAMAIS être envoyé par email.
Si on parle des mots de passe d'accès aux boites emails, ce qui est absurde, c'est surtout que la plupart des clients emails qui implémentent TLS l'implémentent très mal, ce qui fait qu'on peut de toute façon faire une attaque de type MITM et intercepter le mot de passe quand même.
Pour ma part, l'accès à mes boites emails se fait par authentification TLS mutuelle, ce qui coupe les jambes aux attaquants : il y a pas de mot de passe du tout... hélas, cela signifie que je suis très limité dans le choix de mes clients emails =)
Offres d'emploi IT
Analyste développeur .net h/f
CDI
STUDIEL - Provence Alpes Côte d'Azur - Sophia antipolis
Parue le 03/07/2014
Reconversion ingénieur informatique h/f
CDI
Adaming - Ile de France - Ile de France
Parue le 17/07/2014
Développeur C++ H/F
CDI
BULL FR - Provence Alpes Côte d'Azur - Marseille (13000)
Parue le 09/07/2014

Voir plus d'offres Voir la carte des offres IT
 
 
 
 
Partenaires

PlanetHoster
Ikoula