Changer le script de hachage js pour la page login #3824

Open
opened 5 years ago by cam.lafit · 19 comments
Collaborator

Le script js de la page login génére une signature du mot de passe. Cette signature est spécifique au fonctionnement SPIP.
Ce comportement empêche de brancher des systèmes d'authentification autre qui souhaiterait utiliser le formulaire. On peut le constater avec les plugins proposant des authentification annexes, ils ont leur propre formulaire de connexion.

Actuellement la solution consiste à supprimer les fichier sha256.js et login.js afin de désactiver le hachage du mot de passe. Ainsi le mot de passe est transmis en clair et non plus sous la forme d'une empreinte salée SPIP.

Une alternative pourrait être d'utiliser des scripts comme :

Le mot de passe est sécurisé lors du transfert mais reste exploitable ainsi par la suite. On peut ainsi reprendre le mot de passe pour le comparer à d'autres types d'empreinte (sha1, md5,clair, ....)

Le script js de la page login génére une signature du mot de passe. Cette signature est spécifique au fonctionnement SPIP. Ce comportement empêche de brancher des systèmes d'authentification autre qui souhaiterait utiliser le formulaire. On peut le constater avec les plugins proposant des authentification annexes, ils ont leur propre formulaire de connexion. Actuellement la solution consiste à supprimer les fichier sha256.js et login.js afin de désactiver le hachage du mot de passe. Ainsi le mot de passe est transmis en clair et non plus sous la forme d'une empreinte salée SPIP. Une alternative pourrait être d'utiliser des scripts comme : * https://github.com/travist/jsencrypt * http://wwwtyro.github.io/cryptico/ * https://github.com/ziyan/javascript-rsa Le mot de passe est sécurisé lors du transfert mais reste exploitable ainsi par la suite. On peut ainsi reprendre le mot de passe pour le comparer à d'autres types d'empreinte (sha1, md5,clair, ....)
Owner

Actuellement la solution consiste à supprimer les fichier sha256.js et login.js afin de désactiver le hachage du mot de passe

Pas tout à fait. Il y a un autre moyen de signaler que tu veux envoyer le mot de passe en clair, par une constante.

define ('_AUTORISER_AUTH_FAIBLE', true);

On peut activer cette constante lorsque le type d'authentification remarque que l'utilisateur peut être logé avec ce type d'authentification (si c'est possible, dans xx_retrouver_login() donc),
ou dès que ce type d'authentification est présent. Cependant c'est une situation pas très heureuse que d'envoyer un mot de passe en clair ; je dis juste qu'il y a un moyen sans supprimer les 2 js en question. Utilisé par exemple avec PMB (il déclare la constante systématiquement lui) :

http://zone.spip.org/trac/spip-zone/browser/plugins/spip-pmb/trunk/auth/pmb.php#L43

> Actuellement la solution consiste à supprimer les fichier sha256.js et login.js afin de désactiver le hachage du mot de passe Pas tout à fait. Il y a un autre moyen de signaler que tu veux envoyer le mot de passe en clair, par une constante. <pre> define ('_AUTORISER_AUTH_FAIBLE', true); </pre> On peut activer cette constante lorsque le type d'authentification remarque que l'utilisateur peut être logé avec ce type d'authentification (si c'est possible, dans xx_retrouver_login() donc), ou dès que ce type d'authentification est présent. Cependant c'est une situation pas très heureuse que d'envoyer un mot de passe en clair ; je dis juste qu'il y a un moyen sans supprimer les 2 js en question. Utilisé par exemple avec PMB (il déclare la constante systématiquement lui) : http://zone.spip.org/trac/spip-zone/browser/_plugins_/spip-pmb/trunk/auth/pmb.php#L43
b_b commented 4 years ago
Owner
There is no content yet.
b_b commented 3 years ago
Owner

Voir aussi #4129 qui signale que ce bug pose aussi problème lors de l'authentification LDAP.

Voir aussi #4129 qui signale que ce bug pose aussi problème lors de l'authentification LDAP.
Owner

Ou probablement et plus simplement, enlever le hashage dès qu'on est en https, car il ne sert à rien d'autre que tout compliquer...

(je pense que la crypto RSA dans le navigateur c'est pas super compliant avec tous les vieux browsers mais j'ai pas creusé)
Version cible mise à 4.0

Ou probablement et plus simplement, enlever le hashage dès qu'on est en https, car il ne sert à rien d'autre que tout compliquer... (je pense que la crypto RSA dans le navigateur c'est pas super compliant avec tous les vieux browsers mais j'ai pas creusé) **Version cible mise à 4.0**
Owner

Il faut le faire donc, mais plus tard, quand quelqu'un s'y collera
Version cible mise à 4.1

Il faut le faire donc, mais plus tard, quand quelqu'un s'y collera **Version cible mise à 4.1**

Ou probablement et plus simplement, enlever le hashage dès qu'on est en https, car il ne sert à rien d'autre que tout compliquer...

(je pense que la crypto RSA dans le navigateur c'est pas super compliant avec tous les vieux browsers mais j'ai pas creusé)
Version cible mise à 4.0

Alors c'est pire que ca en fait : ca sert aussi à réaliser des attaques de type Pass The Hash (https://en.wikipedia.org/wiki/Pass_the_hash) dans la mesure ou l'on peut s'authentifier directement avec un hash qu'on connaisse ou pas le clair correspondant.

Je peux faire la PR pour faire ces modifs si besoin.

> Ou probablement et plus simplement, enlever le hashage dès qu'on est en https, car il ne sert à rien d'autre que tout compliquer... > > (je pense que la crypto RSA dans le navigateur c'est pas super compliant avec tous les vieux browsers mais j'ai pas creusé) > **Version cible mise à 4.0** Alors c'est pire que ca en fait : ca sert aussi à réaliser des attaques de type Pass The Hash (https://en.wikipedia.org/wiki/Pass_the_hash) dans la mesure ou l'on peut s'authentifier directement avec un hash qu'on connaisse ou pas le clair correspondant. Je peux faire la PR pour faire ces modifs si besoin.
b_b commented 2 weeks ago
Owner

Si tu as un plan pour faire ce que propose @cerdic (c'est ce que j'allais proposer de nouveau dans https://git.spip.net/spip-team/securite/issues/4820#issuecomment-27812), fais péter la PR @g0uZ :)

Si tu as un plan pour faire ce que propose @cerdic (c'est ce que j'allais proposer de nouveau dans https://git.spip.net/spip-team/securite/issues/4820#issuecomment-27812), fais péter la PR @g0uZ :)

Si Cedric valide, ce serait mieux de le faire disparaitre complètement non ? Avec ce système la sécurité est moindre.

Sinon, une autre manière de faire pour conserver ce système et de maximiser la sécurité :

Il faudrait utiliser une clé de chiffrement symétrique (AES256 par exemple) stockée sur le disque (config/clés.php) pour chiffrer les hash de tous les mot de passe/token authentifiants/valeurs sensibles stockée en DB (ca pourrait prendre la forme d'un plugin dans un premier temps).

Ca limiterait énormément les conséquences lors d'un accès non autorisé en lecture à la DB (injection SQL, sauvegarde qui fuite), les attaques de type PTH ne serait plus possible et lors du login sur http ou https le mot de passe serait très bien protégé.

Si Cedric valide, ce serait mieux de le faire disparaitre complètement non ? Avec ce système la sécurité est moindre. Sinon, une autre manière de faire pour conserver ce système et de maximiser la sécurité : Il faudrait utiliser une clé de chiffrement symétrique (AES256 par exemple) stockée sur le disque (config/clés.php) pour chiffrer les hash de tous les mot de passe/token authentifiants/valeurs sensibles stockée en DB (ca pourrait prendre la forme d'un plugin dans un premier temps). Ca limiterait énormément les conséquences lors d'un accès non autorisé en lecture à la DB (injection SQL, sauvegarde qui fuite), les attaques de type PTH ne serait plus possible et lors du login sur http ou https le mot de passe serait très bien protégé.
b_b commented 2 weeks ago
Owner

Si Cedric valide, ce serait mieux de le faire disparaitre complètement non ?

Perso je ne valide pas complètement, car dans https://git.spip.net/spip-team/securite/issues/4820#issuecomment-27745 tu dis :

Sachant que https/http2 est devenu obligatoire ou presque, doit on encore hasher le mot de passe coté client (vu que le canal est déjà sécurisé) ?

Tous les sites ne sont pas en https à ce jour, donc il faut garder ce comportement pour les sites en http. Si j'ai bien compris, le problème est sur deux points :

  • la fonctionnalité qui hash le mot de passe coté client via javascript lors du login
  • le faut qu'on stocke ce hash en base

Si c'est bien ça, je me dis qu'on pourrait proposer un plugin qui :

  • désactive la fonctionnalité JS à l'aide d'un define qu'on aurait ajouté au core auparavant
  • efface le contenu (ou supprime le champ hash) de la table auteurs lors de l'installation

Est-ce que ça fixe le problème et vous semble convenable ?

> Si Cedric valide, ce serait mieux de le faire disparaitre complètement non ? Perso je ne valide pas complètement, car dans https://git.spip.net/spip-team/securite/issues/4820#issuecomment-27745 tu dis : > Sachant que https/http2 est devenu obligatoire ou presque, doit on encore hasher le mot de passe coté client (vu que le canal est déjà sécurisé) ? Tous les sites ne sont pas en https à ce jour, donc il faut garder ce comportement pour les sites en http. Si j'ai bien compris, le problème est sur deux points : * la fonctionnalité qui hash le mot de passe coté client via javascript lors du login * le faut qu'on stocke ce hash en base Si c'est bien ça, je me dis qu'on pourrait proposer un plugin qui : * désactive la fonctionnalité JS à l'aide d'un define qu'on aurait ajouté au core auparavant * efface le contenu (ou supprime le champ hash) de la table auteurs lors de l'installation Est-ce que ça fixe le problème et vous semble convenable ?

Mais le core pourrait quand même de base ne rien faire quand on détecte que HTTPS non ?

Mais le core pourrait quand même de base ne rien faire quand on détecte que HTTPS non ?

Il y a bien différents problèmes :

  • algorithme de hash faible : htpass "relativement faible" qui est sotcké en base pour permettre l'authentification via HTTP/htaccess: #4497 : simplement pouvoir désactiver ce système ce serait bien (ces hash sont beaucoup plus rapides a casser que ceux stocké dans la colonne pass hashé avec sha256)

  • mécanisme d'authentification faible : actuellement a cause du hash du mot de passe réalisé en javascript coté client, l'authentication gérée coté PHP est vulnérable à une attaque de type PTH. Ca ne doit pas être possible, hacher les mots de passes en DB perd tout sont intéret.

A mon sens conserver ce mécanisme est inutile et risqué car :

  • expose au attaques de type PTH
  • ne protège en rien contre une écoute du flux HTTP puisqu'il suffit d'envoyer le hash pour s'authentifier
  • faire le distinguo entre http et https me semble être une mauvaise idée car cela dépend principalement de la configuration des services http/reverse proxy & co et il y aura surement des problèmes/vulnérabilités associés.
Il y a bien différents problèmes : * algorithme de hash faible : htpass "relativement faible" qui est sotcké en base pour permettre l'authentification via HTTP/htaccess: https://git.spip.net/spip/spip/issues/4497 : simplement pouvoir désactiver ce système ce serait bien (ces hash sont beaucoup plus rapides a casser que ceux stocké dans la colonne pass hashé avec sha256) * mécanisme d'authentification faible : actuellement a cause du hash du mot de passe réalisé en javascript coté client, l'authentication gérée coté PHP est vulnérable à une attaque de type PTH. Ca ne doit pas être possible, hacher les mots de passes en DB perd tout sont intéret. A mon sens conserver ce mécanisme est inutile et risqué car : * expose au attaques de type PTH * ne protège en rien contre une écoute du flux HTTP puisqu'il suffit d'envoyer le hash pour s'authentifier * faire le distinguo entre http et https me semble être une mauvaise idée car cela dépend principalement de la configuration des services http/reverse proxy & co et il y aura surement des problèmes/vulnérabilités associés.
Owner

Je ne sais pas pour le public, mais pour le stockage du password en base, et son test, il faudra certainement à un moment s’appuyer sur les fonctions PHP prévues pour, qui permettent à la fois d’augmenter la sécurité (PHP se charge de maintenir un chiffrage au mieux), tout en évitant des attaques / tests par timing :

On délègue à PHP la gestion du hachage et du sel. On peut de la même façon qu’actuellement ré-enregistrer le password à chaque connexion (mais PHP gère le sel, on ne s’appuierait plus sur nos aleas auteurs pour ça).

Je ne sais pas pour le public, mais pour le stockage du password en base, et son test, il faudra certainement à un moment s’appuyer sur les fonctions PHP prévues pour, qui permettent à la fois d’augmenter la sécurité (PHP se charge de maintenir un chiffrage au mieux), tout en évitant des attaques / tests par timing : - https://www.php.net/manual/fr/function.password-hash.php - https://www.php.net/manual/fr/function.password-verify.php - https://www.php.net/manual/fr/function.password-needs-rehash.php On délègue à PHP la gestion du hachage et du sel. On peut de la même façon qu’actuellement ré-enregistrer le password à chaque connexion (mais PHP gère le sel, on ne s’appuierait plus sur nos aleas auteurs pour ça). - https://www.php.net/manual/fr/function.password-hash.php#124138 indique aussi d’ajouter un poivre au mot de passe envoyé (le secret du site, chez nous, je suppose).
b_b commented 2 weeks ago
Owner
  • faire le distinguo entre http et https me semble être une mauvaise idée car cela dépend principalement de la configuration des services http/reverse proxy & co et il y aura surement des problèmes/vulnérabilités associés.

Bien d'accord, c'est pour ça que je propose de le faire dans un plugin que le webmestre installera en toute connaissance de cause :)

> * faire le distinguo entre http et https me semble être une mauvaise idée car cela dépend principalement de la configuration des services http/reverse proxy & co et il y aura surement des problèmes/vulnérabilités associés. > Bien d'accord, c'est pour ça que je propose de le faire dans un plugin que le webmestre installera en toute connaissance de cause :)

Je ne sais pas pour le public, mais pour le stockage du password en base, et son test, il faudra certainement à un moment s’appuyer sur les fonctions PHP prévues pour, qui permettent à la fois d’augmenter la sécurité (PHP se charge de maintenir un chiffrage au mieux), tout en évitant des attaques / tests par timing :

On délègue à PHP la gestion du hachage et du sel. On peut de la même façon qu’actuellement ré-enregistrer le password à chaque connexion (mais PHP gère le sel, on ne s’appuierait plus sur nos aleas auteurs pour ça).

Ca ce serait plutot pour une v5 non ? Il faudrait changer la structure de la base non ? Et surtout pas de problème avec sha256 et la gestion des aléas de Spip.

On peut tout mettre dans le plugin qui servirait a faire la transition ? Pour le moment j'ai noté ca :

plugin authentification2

authentification2_fonctions.php
	initialiser_cle()
    supprimer_cle()
	chiffrer()
	dechiffrer()

authentification2_administrations.php
	authentification2_upgrade();
	authentification2_vider_tables();
	authentification2_installation()
	authentification2_desinstallation()
    
surcharge de 
	auth_spip_dist()
	auth_spip_formulaire_login() 
	auth_spip_modifier_pass()
	auteur_attribuer_jeton()
	auteur_verifier_jeton()

Non il faut que ce soit stocké ailleurs que dans la base de données sinon ca perd son intérêt :)

Ca doit également être appliqué au "token authentifiants" utilisé par exemple avec la fonctionnalité de "mot de passe perdu".

> Je ne sais pas pour le public, mais pour le stockage du password en base, et son test, il faudra certainement à un moment s’appuyer sur les fonctions PHP prévues pour, qui permettent à la fois d’augmenter la sécurité (PHP se charge de maintenir un chiffrage au mieux), tout en évitant des attaques / tests par timing : > > - https://www.php.net/manual/fr/function.password-hash.php > - https://www.php.net/manual/fr/function.password-verify.php > - https://www.php.net/manual/fr/function.password-needs-rehash.php > > On délègue à PHP la gestion du hachage et du sel. On peut de la même façon qu’actuellement ré-enregistrer le password à chaque connexion (mais PHP gère le sel, on ne s’appuierait plus sur nos aleas auteurs pour ça). Ca ce serait plutot pour une v5 non ? Il faudrait changer la structure de la base non ? Et surtout pas de problème avec sha256 et la gestion des aléas de Spip. On peut tout mettre dans le plugin qui servirait a faire la transition ? Pour le moment j'ai noté ca : ``` plugin authentification2 authentification2_fonctions.php initialiser_cle() supprimer_cle() chiffrer() dechiffrer() authentification2_administrations.php authentification2_upgrade(); authentification2_vider_tables(); authentification2_installation() authentification2_desinstallation() surcharge de auth_spip_dist() auth_spip_formulaire_login() auth_spip_modifier_pass() auteur_attribuer_jeton() auteur_verifier_jeton() ``` > - https://www.php.net/manual/fr/function.password-hash.php#124138 indique aussi d’ajouter un poivre au mot de passe envoyé (le secret du site, chez nous, je suppose). Non il faut que ce soit stocké ailleurs que dans la base de données sinon ca perd son intérêt :) Ca doit également être appliqué au "token authentifiants" utilisé par exemple avec la fonctionnalité de "mot de passe perdu".

b_b : du coup j'ai fait un tout petit plugin "chiffrer" qui répond a ce problème #3824#.

Ou je peux le mettre pour que ca serve de base à la discussion ?

b_b : du coup j'ai fait un tout petit plugin "chiffrer" qui répond a ce problème https://git.spip.net/spip/spip/issues/3824#. Ou je peux le mettre pour que ca serve de base à la discussion ?
b_b commented 2 weeks ago
Owner

@g0uZ bah dans un repo sur git.spip.net tout simplement :)

@g0uZ bah dans un repo sur git.spip.net tout simplement :)
Owner

Ca ce serait plutot pour une v5 non ? Il faudrait changer la structure de la base non ? Et surtout pas de problème avec sha256 et la gestion des aléas de Spip.

Je pense qu’on peut faire les 2 transitoirement, comme on l’a fait pour le passage md5 à sha256. De toutes façons on ne peut pas up dans connaitre le mot de passe des utilisateurs, donc ça se fait uniquement à leur login (ou alors en les forçant à le recréer). Il suffirait de tester la présence du . dans le champ password en fait. S’il est là c’est que ça serait passé sur password_hash() , sinon c’est la méthode sha.

> Ca ce serait plutot pour une v5 non ? Il faudrait changer la structure de la base non ? Et surtout pas de problème avec sha256 et la gestion des aléas de Spip. Je pense qu’on peut faire les 2 transitoirement, comme on l’a fait pour le passage md5 à sha256. De toutes façons on ne peut pas up dans connaitre le mot de passe des utilisateurs, donc ça se fait uniquement à leur login (ou alors en les forçant à le recréer). Il suffirait de tester la présence du `.` dans le champ password en fait. S’il est là c’est que ça serait passé sur `password_hash()` , sinon c’est la méthode sha.

Hop : https://git.spip.net/g0uZ/chiffrer

Pas de problèmes pour ajouter encore un autre format de hash mais bon. Dans la mesure ou l'actuel n'a aucun problème je vois pas encore l'intéret.

Et vu que la graine est gérée par php ca change pas mal de choses non ?

Hop : https://git.spip.net/g0uZ/chiffrer Pas de problèmes pour ajouter encore un autre format de hash mais bon. Dans la mesure ou l'actuel n'a aucun problème je vois pas encore l'intéret. Et vu que la graine est gérée par php ca change pas mal de choses non ?
g0uZ commented 1 week ago

Ca ce serait plutot pour une v5 non ? Il faudrait changer la structure de la base non ? Et surtout pas de problème avec sha256 et la gestion des aléas de Spip.

Je pense qu’on peut faire les 2 transitoirement, comme on l’a fait pour le passage md5 à sha256. De toutes façons on ne peut pas up dans connaitre le mot de passe des utilisateurs, donc ça se fait uniquement à leur login (ou alors en les forçant à le recréer). Il suffirait de tester la présence du . dans le champ password en fait. S’il est là c’est que ça serait passé sur password_hash() , sinon c’est la méthode sha.

J'ai intégré les modifications demandées dans https://git.spip.net/g0uZ/chiffrer. J'ai par contre conservé la génération des alea_actuel/alea_futur par Spip. Pour ne pas tout changer d'un coup (et surtout la structure de la DB), on peut imaginer laisser PHP générer les aléas, mais les enregistrer tout de même en DB pour la cohérence.

> > Ca ce serait plutot pour une v5 non ? Il faudrait changer la structure de la base non ? Et surtout pas de problème avec sha256 et la gestion des aléas de Spip. > > Je pense qu’on peut faire les 2 transitoirement, comme on l’a fait pour le passage md5 à sha256. De toutes façons on ne peut pas up dans connaitre le mot de passe des utilisateurs, donc ça se fait uniquement à leur login (ou alors en les forçant à le recréer). Il suffirait de tester la présence du `.` dans le champ password en fait. S’il est là c’est que ça serait passé sur `password_hash()` , sinon c’est la méthode sha. > J'ai intégré les modifications demandées dans https://git.spip.net/g0uZ/chiffrer. J'ai par contre conservé la génération des alea_actuel/alea_futur par Spip. Pour ne pas tout changer d'un coup (et surtout la structure de la DB), on peut imaginer laisser PHP générer les aléas, mais les enregistrer tout de même en DB pour la cohérence.
Sign in to join this conversation.
No Milestone
No project
No Assignees
6 Participants
Notifications
Due Date

No due date set.

Dependencies

This issue currently doesn't have any dependencies.

Loading…
There is no content yet.