[Résolu] Echec création de compte invité depuis le front - apparu spip 4.4.17

Description du problème

Depuis SPIP 4.4.17, lors de la création d’un compte via le formulaire natif :

#FORMULAIRE_INSCRIPTION{6forum}

l’inscription semble fonctionner correctement :

  • l’auteur est créé dans spip_auteurs ;
  • son login est correctement généré ;
  • son statut est nouveau ;
  • prefs contient bien 6forum ;
  • l’email d’inscription est envoyé ;
  • cet email contient bien le mot de passe aléatoire généré.

En revanche, le champ pass de spip_auteurs reste vide.

Le compte créé ne peut donc pas se connecter avec le mot de passe reçu par email.

Versions testées

  • SPIP 4.4.16 : fonctionnement OK
  • SPIP 4.4.20 : problème reproductible
  • La régression semble avoir été introduite en 4.4.17.
  • PHP 8.4
  • MySQL 8.x

Le problème est également reproductible sans le plugin Inscription 3, avec uniquement le formulaire natif #FORMULAIRE_INSCRIPTION{6forum}.

Diagnostic

Dans ecrire/action/inscrire_auteur.php, action_inscrire_auteur_dist() appelle :

$desc['pass'] = creer_pass_pour_auteur($desc['id_auteur']);

La fonction creer_pass_pour_auteur() génère correctement le mot de passe puis appelle :

auteur_instituer($id_auteur, ['pass' => $pass]);

Un traçage confirme que le mot de passe est bien généré :

PASS GENERE longueur=16

mais qu’après auteur_instituer() :

'id_auteur' => '6127',
'login' => 'nicolas_essai5',
'pass' => '',
'statut' => 'nouveau',
'source' => 'spip'

Cause identifiée

En comparant SPIP 4.4.16 et 4.4.20, la différence se trouve dans ecrire/action/editer_auteur.php.

En 4.4.16 :

if (isset($c['pass']) and strlen($c['pass'])) {
	$champs['pass'] = $c['pass'];
}

Depuis le correctif de sécurité spip-security/securite#4894, auteur_instituer() vérifie maintenant l’autorisation :

if (
	isset($c['pass'])
	&& strlen($c['pass'])
	&& autoriser('modifier', 'auteur', $id_auteur, null, ['pass' => '?'])
) {
	$champs['pass'] = $c['pass'];
}

Lors d’une inscription publique, le visiteur n’est évidemment pas authentifié comme l’auteur qui vient d’être créé.

Le traçage donne donc :

isset=OUI
longueur=16
autoriser=NON
CHAMPS APRES AUTORISATION=

Par conséquent, $champs['pass'] n’est jamais défini et auth_modifier_pass() n’est jamais appelé.

auteur_instituer() retourne par ailleurs une chaîne vide, ce qui ne permet pas à creer_pass_pour_auteur() de détecter le problème.

Comparaison avec inscription_nouveau()

Le problème semble d’autant plus identifiable que inscription_nouveau() gère déjà ce cas en levant temporairement l’autorisation :

autoriser_exception('modifier', 'auteur', $id_auteur);
auteur_modifier($id_auteur, $desc);
autoriser_exception('modifier', 'auteur', $id_auteur, false);

Mais creer_pass_pour_auteur() ne fait pas de même avant :

auteur_instituer($id_auteur, ['pass' => $pass]);

Test d’un correctif

Le problème disparaît en appliquant le même principe dans creer_pass_pour_auteur() :

function creer_pass_pour_auteur($id_auteur) {
	include_spip('inc/acces');
	$pass = creer_pass_aleatoire(max(_PASS_LONGUEUR_MINI, 16), $id_auteur);

	include_spip('inc/autoriser');
	include_spip('action/editer_auteur');

	autoriser_exception('modifier', 'auteur', $id_auteur);

	auteur_instituer($id_auteur, ['pass' => $pass]);

	autoriser_exception('modifier', 'auteur', $id_auteur, false);

	return $pass;
}

Après cette modification, le champ pass contient bien le hash attendu dans spip_auteurs.

Remarque

Une logique similaire semble déjà avoir été appliquée dans prive/formulaires/mot_de_passe.php, où une autoriser_exception('modifier', 'auteur', $id_auteur) est utilisée avant la modification du mot de passe.

Il semble donc que le renforcement des autorisations de modification de login / pass ait corrigé un problème de sécurité, mais que le cas de creer_pass_pour_auteur() lors d’une inscription publique n’ait pas été adapté en conséquence.

Résultat attendu

Après :

#FORMULAIRE_INSCRIPTION{6forum}

le mot de passe aléatoire envoyé à l’utilisateur doit être enregistré/hashé dans spip_auteurs.pass, comme c’était le cas en SPIP 4.4.16.

Résultat actuel

L’utilisateur reçoit bien son mot de passe par email, mais spip_auteurs.pass reste vide et la connexion est impossible.

2 « J'aime »

Merci ! Bien détaillé et oui, très certainement il manque un autoriser_exception donc maintenant.

J’ai ouvert un ticket en reprenant ton message

On regardera cela sous peu.

Merci bcp !

Savez vous si la correction est comprise dans la 4.4.21 ?

En principe, oui :wink:

De toute manière, compte tenu du fait que les failles des versions précédentes sont déjà exploitées, il faut mettre à jour !

1 « J'aime »