Problème de sécurité/confidentialité : Email exposé dans l'URL de redirection du fournisseur DiscourseConnect

Décrire le bogue

Lors de l’utilisation de Discourse comme Fournisseur DiscourseConnect (Fournisseur SSO), l’adresse e-mail de l’utilisateur est exposée dans l’URL de redirection 302 vers le relying party (partie prenante). Cela se produit car la méthode populate_user_data dans lib/second_factor/actions/discourse_connect_provider.rb définit toujours l’e-mail :

  def populate_user_data(sso)
    sso.name = current_user.name
    sso.username = current_user.username
    sso.email = current_user.email  # <-- Toujours inclus
    sso.external_id = current_user.id.to_s
    # ...
  end

Cet e-mail est ensuite encodé en Base64 et inclus dans l’URL de redirection :
https://site-cible.com/callback?sso=<payload_base64>&sig=<signature_hmac>

Le décodage de la charge utile base64 révèle l’adresse e-mail en texte clair.

Impact

  1. Historique du navigateur : L’e-mail est enregistré dans l’historique du navigateur
  2. Journaux Nginx : L’URL complète est enregistrée dans les journaux d’accès nginx
  3. Journaux du site cible : Le relying party reçoit l’e-mail sans consentement explicite de l’utilisateur
  4. Attente de l’utilisateur : Les utilisateurs autorisent généralement pour prouver « Je suis un utilisateur légitime » - ils ne s’attendent pas à ce que leur e-mail soit partagé

Comportement attendu

Les utilisateurs devraient pouvoir contrôler si leur e-mail est partagé avec le relying party. Il devrait y avoir une option de configuration similaire à discourse_connect_overrides_groups, discourse_connect_overrides_avatar, etc.

Actuellement, il n’y a aucun paramètre de site pour désactiver ce comportement. Écrire un plugin pour remplacer ce comportement est possible mais pas idéal.

Étapes de reproduction

  1. Activer enable_discourse_connect_provider
  2. Configurer discourse_connect_provider_secrets (par exemple, *.example.com|secret123)
  3. Faire authentifier un utilisateur via le Fournisseur DiscourseConnect
  4. Vérifier l’URL de redirection 302 - l’e-mail est visible dans les paramètres de l’URL

L’URL de redirection ressemble à :
https://relying-party.com/sso?sso=nonce=xxx&sig=xxx

Le décodage du paramètre sso révèle :
nonce=xxx&return_sso_url=xxx&email=user@example.com&external_id=123

Environnement

  • Version de Discourse : (la plus récente)
  • Auto-hébergé

Suggestions de correction possibles

  1. Ajouter un paramètre de site comme discourse_connect_provider_includes_email (par défaut : true pour la rétrocompatibilité) pour contrôler si l’e-mail est inclus dans la réponse
  2. Ou implémenter un rappel basé sur POST au lieu d’une redirection GET 302 pour éviter l’enregistrement de l’URL

N’est-ce pas également chiffré avec le secret partagé ?

1 « J'aime »

Bonjour Falco,

La signature HMAC garantit uniquement que la charge utile n’a pas été falsifiée - elle ne chiffre pas les données. Le Base64 est un encodage, pas un chiffrement, donc n’importe qui peut le décoder pour lire le contenu.

Le problème fondamental est le suivant : nous ne voulons pas exposer des informations utilisateur inutiles (comme l’e-mail) aux « sites tiers utilisant Discourse pour la connexion SSO ». Les utilisateurs autorisent uniquement pour prouver « Je suis un utilisateur légitime » - ils ne s’attendent pas à ce que leur e-mail soit partagé.

Un paramètre de site pour contrôler si l’e-mail est renvoyé serait-il acceptable ?

Je suis curieux, quel est ce tiers en aval qui a implémenté notre protocole SSO personnalisé ?

Je dirais que c’est pr-welcome tant que ce n’est pas la valeur par défaut, afin de ne pas casser les sites existants.

Merci pour vos commentaires !

Pour vous donner un peu de contexte sur le cas d’utilisation : notre forum est un « forum de campus », et un étudiant a créé un site web gratuit pour que d’autres étudiants puissent l’utiliser. Ils souhaitent utiliser notre forum de campus basé sur Discourse pour authentifier si un utilisateur est bien un étudiant de notre établissement — prouvant essentiellement « Je suis un étudiant légitime ici ».

Dans ce scénario, le site web externe n’a besoin de savoir que « ceci est un utilisateur valide de notre forum de campus » — ils n’ont pas nécessairement besoin de l’e-mail de l’utilisateur, qui est une information sensible qui ne devrait pas être partagée inutilement.

Je vais travailler sur une demande de tirage (PR) qui ajoutera un paramètre de site pour contrôler ce comportement, avec une valeur par défaut qui maintient la compatibilité ascendante pour les installations existantes.

1 « J'aime »