
Nextcloud 35.0.0 — un administrateur délégué aux Webhooks peut générer un mot de passe d'application administrateur d'une durée de 1 h via la mise à jour d'un webhook tokenNeeded
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · nextcloud-webhook-tokenneeded
Write-up : https://abraxaslabs.tech/research/nextcloud-webhook-tokenneeded
Nextcloud Server 35.0.0 - Nextcloud GmbH
WebhooksController::create() met tokenNeeded à null sauf si l'appelant est un administrateur complet de l'instance. update() ne le fait pas. Un administrateur délégué des paramètres Webhooks (absent du groupe admin) peut stocker tokenNeeded.user_ids: ["admin"] sur un webhook existant, puis recevoir un mot de passe d'application PERMANENT_TOKEN non restreint d'une heure pour cet uid lorsque l'événement se déclenche.
Un acteur malveillant à qui l'on avait seulement confié la gestion des webhooks peut se connecter en tant que admin (ou tout utilisateur qu'il désigne) pendant une heure, contourner la 2FA et lire ou écraser les fichiers de cette personne.
| ID | pas encore de CVE |
| CWE | CWE-863, CWE-269 |
| CVSS | Élevé : 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Produit | Nextcloud Server |
| Affecté | 35.0.0 (da02f41) officiel nextcloud:35.0.0-apache |
| Auth | administrateur délégué des paramètres Webhooks (IDelegatedSettings) |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Vous avez confié à quelqu'un la tâche de gestion des paramètres Webhooks. Cette personne n'est pas dans le groupe admin. Nextcloud lui permet tout de même de modifier un webhook existant afin que, lors du prochain événement correspondant, le serveur lui envoie par e-mail une connexion d'une heure pour tout uid qu'il liste, y compris admin.
Avec cette connexion, il peut :
Il n'a pas besoin d'un shell PHP sur l'hôte. Il n'a pas besoin d'être administrateur complet de l'instance. Un inconnu sur Internet sans compte ne peut pas faire cela. La faille, c'est le membre du personnel à qui vous avez déjà fait confiance pour les webhooks, qui usurpe l'identité des personnes à qui vous ne l'avez pas accordée.
WebhooksController est #[AuthorizedAdminSetting(settings: Admin::class)]. Admin implémente IDelegatedSettings. C'est ainsi que Nextcloud confie un panneau de paramètres à un groupe qui n'est pas admin.
tokenNeeded demande au serveur d'attacher des jetons d'authentification pour les uid nommés lorsque le webhook se déclenche. TokenService::createEphemeralToken génère un IToken::PERMANENT_TOKEN avec password = null. Mot de passe d'application. La 2FA est déjà derrière vous.
La PR #60543 a verrouillé la création : sauf si vous êtes administrateur complet de l'instance, tokenNeeded est mis à null. J'ai créé un webhook en tant qu'utilisateur délégué hooker avec tokenNeeded.user_ids: ["admin"]. Le tokenNeeded stocké était []. La création est verrouillée. Pendant une minute, cela ressemble à un correctif terminé.
Puis j'ai envoyé en POST le même corps à /webhooks/{id}. Le user_ids stocké était ['admin']. update() n'a jamais copié le if.
J'ai envoyé en PUT un fichier en tant que hooker pour déclencher NodeCreatedEvent. Cron exécute WebhookCall. Le JSON du catcher contient authentication.user_ids.admin.token. Un GET Bearer du fichier témoin privé de l'admin a renvoyé 200, X-User-Id: admin.
Les façons dont cela échoue sans rien vous apprendre : update 403 (le contrôleur correspond déjà à create) ; create génère déjà des jetons (#60543 absent du build) ; authentication vide dans le catcher (cron n'a pas généré de jeton) ; chemin d'en-tête ExApp (l'utilisateur du lab est le délégué hooker).
cd lab
./run.sh
Ciblez uniquement http://127.0.0.1:18320 (Nextcloud) et :18321 (catcher).
SUCCESS NEXTCLOUD-WEBHOOK-TOKENNEEDED who=delegated-webhook-admin uid=admin NEXTCLOUD-WEBHOOK-TOKENNEEDED-WITNESS
Copiez la mise à null de isAdmin de la création dans update(). Tant que ce correctif n'est pas livré, ne déléguez pas les paramètres des Webhooks à des groupes non administrateurs.
da02f41)GNU Affero GPL v3.0. Voir LICENSE. Laboratoire en boucle locale uniquement. Aucune garantie.