
Plausible Analytics master d44e104 - Élevé - À distance - Reliquat de privilèges - éditeur personnes HTML fuites transfert nanoid
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · plausible-editor-invite
Plausible Analytics édition communautaire, master GitHub d44e104ae3943a9240d5cb6b62e67dff0f069d3a (2026-10-16) - Plausible Insights OÜ
Classe : privilège résiduel (fuite de jeton d'invitation). Portée : à distance (éditeur invité ou éditeur d'équipe de ce site).
Sites.list_people/1 sélectionne les champs bruts guest_invitations.invitation_id et team_site_transfers.transfer_id. settings_people.html.heex place ce nanoid de 21 caractères dans id="invitation-#{invitation.invitation_id}" pour chaque ligne en attente. Les paramètres People ne figurent pas dans @special_cased_actions de SiteController, donc AuthorizeSiteAccess autorise :editor. L'éditeur invité correspond au rôle de site :editor. Le spectateur invité reçoit une 404.
Nanoid.generate/0 est le porteur d'authentification pour l'inscription depuis une invitation. La requête non authentifiée GET /register/invitation/:invitation_id effectue la recherche uniquement par id. Le LiveView register écrase l'e-mail soumis par invitation.email. L'édition CE par défaut utilise DISABLE_REGISTRATION=invite_only et ENABLE_EMAIL_VERIFICATION=false. L'acceptation se fait via POST /sites/invitations/:id/accept par correspondance d'e-mail citext.
Un éditeur invité qui peut déjà voir le HTML de People lit un nanoid de transfert de propriété en attente, s'inscrit en tant que destinataire de l'invitation, puis accepte. Le site bascule sur l'équipe personnelle de l'attaquant.
| ID | aucun CVE pour l'instant |
| CWE | CWE-200 / CWE-269 |
| CVSS | Élevé : 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L |
| Produit | Plausible Analytics |
| Affecté | master GitHub d44e104ae3943a9240d5cb6b62e67dff0f069d3a (2026-10-16). Le dernier tag CE v3.2.1 (e4f5a87a5570bd61605217e7ceb376636db8eddb, 2026-05-15) a cinq mois de retard. SECURITY.md demande aux opérateurs d'utiliser :latest. L'épinglage correspond au HEAD actuel. CE MIX_ENV=ce ne compile que lib/. |
| Authentification | éditeur invité authentifié (:guest_member, :editor) ou éditeur d'équipe de ce site. Pas non authentifié. Pas spectateur invité. |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18180 (http) 18181 (postgres) 18182 (clickhouse http) uniquement |
Résidu n°1 de Plausible Analytics leftovers. Même épinglage, autre pack : plausible-traffic-notify (affectation de masse de site_id dans PUT traffic-change-notification). Ce pack-ci est celui qui dérobe un transfert de propriété en attente.
Éditeur invité authentifié ou éditeur d'équipe d'un site ayant une invitation d'invité et/ou un transfert de propriété en attente. Nécessite un cookie de session normal. Pas de propriétaire, pas d'admin, pas de LiveView super-admin. Il ne force pas le nanoid de 21 caractères. Il le lit dans le HTML qu'il est autorisé à charger, puis s'inscrit en tant que destinataire de l'invitation.
Table des privilèges (exhaustive). Même niveau d'exigence que Signal-Server Dropwizard admin : méthode + chemin, ce que cet appel accorde, reconnaissance vs intégrité vs disponibilité, prouvé en labo vs déduit, surface adjacente qui reste fermée.
| Axe | Méthode + chemin | Accorde | Provenance |
|---|---|---|---|
| Recon | GET /:domain/settings/people en tant qu'invité/éditeur d'équipe | Les lignes en attente affichent id="invitation-<nanoid>". Le nanoid est invitation_id ou transfer_id. Même site uniquement. L'e-mail de l'invité figure aussi dans le tableau. | Prouvé en labo. L'éditeur people 200 a divulgué le nanoid Hc8DiBC2q08mv5LFmBysu |
| Recon | GET /register/invitation/:id non authentifié | E-mail de l'invité sur le formulaire d'inscription. La recherche se fait uniquement par id (find_by_id_unified). | Prouvé en labo. Le HTML d'inscription affichait [email protected] |
| Intégrité | LiveView register sur /register/invitation/:id | Le user[email] soumis est écrasé par invitation.email. Nouveau compte CE à l'adresse de l'invité. Vérification d'e-mail CE désactivée par défaut. L'inscription sur invitation autorise toujours :invitation. | Prouvé en labo. [email protected] soumis ; l'e-mail stocké était [email protected] |
| Intégrité | POST /sites/invitations/:id/accept avec ce nouveau compte | Le transfert de propriété en attente déplace sites.team_id vers l'équipe personnelle du nouveau propriétaire. La ligne de transfert a disparu. | Prouvé en labo. sites.team_id 1 → 2 |
| Intégrité | même acceptation sur une invitation invité en attente pour cet e-mail | Nouvelle adhésion sur ce site (éditeur-pour-éditeur n'est pas un gain). Les autres lignes équipe/invité/transfert en attente pour cet e-mail deviennent également acceptables. | Source (InvitationController.accept_invitation) |
| Disponibilité | après acceptation du transfert | L'équipe d'origine perd le site. Les statistiques continuent d'être servies sur la nouvelle équipe. | Prouvé en labo. team_id déplacé |
Reste fermé sur ce pin
| Axe | Méthode + chemin | Pourquoi c'est fermé |
|---|---|---|
| Recon | GET /:domain/settings/people par un spectateur invité | 404. Le spectateur n'est pas :editor. Prouvé en labo. |
| Intégrité | POST /sites/invitations/:id/accept par un éditeur de l'id de transfert divulgué | Correspondance d'e-mail. L'éditeur n'est pas [email protected]. Le site reste sur l'équipe 1. Prouvé en labo. |
| Intégrité | inscription non authentifiée sans id d'invitation valide | check_registration_enabled(:default) vs :invitation. whoareme Bug 02, corrigé. |
| Recon | force brute de nanoid de 21 caractères | Alphabet URL-safe, 21 caractères. Hors de portée de ce reliquat. |
| Recon | événements ClickHouse, SMTP, pages people d'autres sites | Même site uniquement. Pas d'admin ClickHouse. Pas de lecture de boîte mail. |
| Intégrité | invitation et transfert par propriétaire/admin | Ils peuvent déjà. Ce reliquat concerne l'éditeur qui ne peut pas. |
| Intégrité | LiveView super-admin, shell OS, SSO EE extra/lib | Fermé. Labo CE. Pas de shell. |