
Bitwarden Server v2026.9.2 - Élevé - IDOR - injecter des éléments de coffre déchiffrables dans des collections où l'appelant ne peut pas écrire
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · bitwarden-cipher-create-acl
Write-up : https://abraxaslabs.tech/research/bitwarden-cipher-create-acl
Bitwarden Server v2026.9.2 - Bitwarden
La création de chiffrement d'organisation sur le chemin Entity Framework (MariaDB, Postgres, SQLite) abandonne l'identifiant de l'appelant avant l'attachement à la collection. Un membre confirmé peut implanter un élément à clé d'organisation dans une collection où il ne peut pas écrire. Les membres de la collection le synchronisent comme une connexion partagée normale.
| ID | pas encore de CVE |
| CWE | CWE-863 / CWE-639 |
| CVSS | Élevé : 7.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L |
| Produit | Bitwarden Server |
| Affecté | v2026.9.2 (9ee4e0eb) lite EF (MariaDB / Postgres / SQLite). MSSQL/Dapper conserve @UserId. |
| Auth | membre d'organisation confirmé |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
L'attaquant ajoute des éléments de coffre à une collection partagée. Il ne lit ni ne remplace les secrets qui s'y trouvent déjà.
Un membre d'organisation confirmé possède déjà la clé d'organisation, donc le nouvel élément se déchiffre pour tous ceux qui peuvent voir cette collection. Bitwarden l'affiche comme une connexion, une note, une carte ou une clé SSH partagée normale depuis l'intérieur du coffre de l'entreprise.
Okta, GitHub, VPN, Payroll) dont l'URI pointe vers un hôte qu'ils contrôlent. Les membres de la collection l'ouvrent depuis Bitwarden et atterrissent sur la page de l'attaquant, ou le remplissage automatique s'effectue contre un site sosie.new AWS key, bastion SSH key, DB password after change). Quelqu'un la copie en production ou dans un terminal.Production peut tout de même y déposer un nouvel élément sur lite EF.S'ils n'ont aucun accès à la collection cible, POST /api/ciphers/create peut renvoyer 404 alors que l'écriture est déjà validée. Les victimes reçoivent tout de même l'élément lors de la synchronisation.
J'ai épinglé bitwarden/server v2026.9.2 (9ee4e0eb) après la vague 2026 : TDE sur demande d'admin (CVE-2026-60104), troncature SSO ExternalId (CVE-2026-101878), collections vides à l'import d'organisation (CVE-2026-43638). Ceux-là sont corrigés. L'ACL de collection à la création ne l'était pas.
CiphersController.PostCreate vérifie uniquement l'appartenance à l'organisation, puis passe skipPermissionCheck: true lorsque OrganizationId est défini. SaveDetailsAsync considère ensuite que « cette collection existe dans l'organisation » est la seule vérification de collection.
Lite MariaDB/Postgres/SQLite utilise EF. CreateAsyncReturnCipher définit cipher.UserId = null car un identifiant d'organisation est présent, puis transmet ce null à UpdateCollectionsAsync. Un identifiant utilisateur null signifie toutes les collections de l'organisation. SQL Server Dapper conserve @UserId pour Cipher_UpdateCollections (ReadOnly = 0). Ce chemin est le négatif.
Erreurs déjà consignées : traiter le POST /organizations cloud comme la création en auto-hébergement (il est [NotSelfHostedOnly] ; lite attend un fichier de licence, donc le lab insère les lignes d'organisation après l'enregistrement) ; injecter dans une collection que l'appelant ne peut pas lire et interpréter un HTTP 404 comme un échec (la ligne CollectionCipher est déjà validée) ; supposer que MSSQL lite l'afficherait (Dapper ne supprime pas l'id de l'appelant) ; laisser BW_ENABLE_ADMIN désactivé de sorte que lite ne migre jamais User / OrganizationDomain (admin est le migrateur EF sur cette image) ; omettre Bitwarden-Client-Version sur /identity/connect/token et voir le password grant renvoyer 400. Un reverse shell. Du théâtre.
cd lab
./run.sh
Ciblez uniquement http://127.0.0.1:18160. Image ghcr.io/bitwarden/lite:2026.9.2 plus MariaDB.
SUCCESS BITWARDEN-CIPHER-CREATE-ACL create-http=404 collectioncipher=1 victim-sync-has-cipher=yes cipher=<id> negative-http=404 readonly-http=200 BITWARDEN-CIPHER-CREATE-ACL-WITNESS
Une plante sans accès renvoie 404 après la validation de CollectionCipher. Les requêtes GET /api/ciphers et /api/sync de la victime contiennent toutes deux le nouvel id. En lecture seule sur B, la requête renvoie 200 et la plante persiste. Une collection d'une organisation étrangère reste en 404 sans ligne de jointure.
Transmettez l'id de l'utilisateur qui enregistre à la méthode EF UpdateCollectionsAsync, de la même manière que CipherDetails_CreateWithCollections transmet toujours @UserId après avoir mis à null la colonne UserId stockée. Ne traitez pas un utilisateur null comme « toutes les collections » sur le chemin de création de membre. L'existence dans l'organisation ne constitue pas un droit d'écriture.
CiphersController.cs (Post, PostCreate)CipherService.cs (SaveDetailsAsync)CipherRepository.cs (CreateAsyncReturnCipher, UpdateCollectionsAsync)