
Bitwarden Server v2026.9.2 – Hoch – IDOR – entschlüsselbare Vault-Elemente in Collections einpflanzen, in die der Aufrufer nicht schreiben kann
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · bitwarden-cipher-create-acl
Bitwarden Server v2026.9.2 - Bitwarden
Beim Anlegen eines Org-Ciphers auf dem Entity-Framework-Pfad (MariaDB, Postgres, SQLite) geht die Aufrufer-ID verloren, bevor die Collection angehängt wird. Ein bestätigtes Mitglied kann ein Element mit dem Org-Schlüssel in eine Collection einschleusen, in die es nicht schreiben darf. Collection-Mitglieder synchronisieren es als normalen geteilten Login.
| ID | noch keine CVE |
| CWE | CWE-863 / CWE-639 |
| CVSS | Hoch: 7.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L |
| Produkt | Bitwarden Server |
| Betroffen | v2026.9.2 (9ee4e0eb) lite EF (MariaDB / Postgres / SQLite). MSSQL/Dapper behält @UserId. |
| Auth | bestätigtes Org-Mitglied |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
Der Angreifer fügt Vault-Elemente zu einer geteilten Collection hinzu. Er liest oder ersetzt nicht die bereits darin befindlichen Secrets.
Ein bestätigtes Org-Mitglied besitzt bereits den Org-Schlüssel, sodass das neue Element für alle entschlüsselt wird, die diese Collection sehen können. Bitwarden zeigt es als normalen geteilten Login, Notiz, Karte oder SSH-Schlüssel aus dem Unternehmens-Vault an.
Okta, GitHub, VPN, Payroll) und dessen URI auf einen vom Angreifer kontrollierten Host zeigt. Collection-Mitglieder öffnen es aus Bitwarden und landen auf der Angreifer-Seite oder lassen es gegen eine nachgeahmte Seite automatisch ausfüllen.neuer AWS-Key, Bastion-SSH-Key, DB-Passwort nach Änderung). Jemand kopiert es in die Produktion oder ein Terminal.Production nur lesen darf, kann auf lite EF trotzdem ein neues Element hineinlegen.Wenn sie keinen Zugriff auf die Ziel-Collection haben, kann POST /api/ciphers/create 404 zurückgeben, nachdem der Schreibvorgang bereits committet wurde. Opfer erhalten das Element trotzdem beim Sync.
Ich habe bitwarden/server v2026.9.2 (9ee4e0eb) nach der Welle von 2026 gepinnt: Admin-Request-TDE (CVE-2026-60104), SSO-ExternalId-Trunkierung (CVE-2026-101878), Org-Import leerer Collections (CVE-2026-43638). Diese sind geschlossen. Die Collection-ACL beim Anlegen war es nicht.
CiphersController.PostCreate prüft nur die Org-Mitgliedschaft und übergibt dann skipPermissionCheck: true, wenn OrganizationId gesetzt ist. SaveDetailsAsync behandelt dann „diese Collection existiert in der Org“ als einzige Collection-Prüfung.
Lite MariaDB/Postgres/SQLite verwenden EF. CreateAsyncReturnCipher setzt cipher.UserId = null, weil eine Org-ID vorhanden ist, und übergibt dieses Null dann an UpdateCollectionsAsync. Null-Benutzer-ID bedeutet jede Collection in der Org. SQL Server Dapper behält @UserId für Cipher_UpdateCollections (ReadOnly = 0). Dieser Pfad ist das Negativ.
Bereits dokumentierte Irrwege: Cloud-POST /organizations als Self-Host-Anlegen zu behandeln (es ist [NotSelfHostedOnly]; lite will eine Lizenzdatei, also legt das Lab Org-Zeilen nach der Registrierung an); in eine Collection einzuschleusen, die der Aufrufer nicht lesen kann, und HTTP 404 als Fehlschlag zu deuten (die CollectionCipher-Zeile ist bereits committet); anzunehmen, dass MSSQL lite es zeigen würde (Dapper verwirft die Aufrufer-ID nicht); BW_ENABLE_ADMIN ausgeschaltet zu lassen, sodass lite nie User / OrganizationDomain migriert (Admin ist der EF-Migrator auf diesem Image); Bitwarden-Client-Version bei /identity/connect/token wegzulassen und zu beobachten, wie der Password-Grant 400 liefert. Eine Reverse Shell. Theater.
cd lab
./run.sh
Ziel nur 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
Das Einschleusen ohne Zugriff liefert 404, nachdem CollectionCipher committet wurde. GET /api/ciphers und /api/sync des Opfers enthalten beide die neue ID. Read-only auf B liefert 200 und schleust trotzdem ein. Eine Collection einer fremden Org bleibt 404 ohne Join-Zeile.
Die speichernde Benutzer-ID genauso in EF UpdateCollectionsAsync übergeben, wie CipherDetails_CreateWithCollections noch @UserId übergibt, nachdem es die gespeicherte UserId-Spalte auf null gesetzt hat. Einen Null-Benutzer auf dem Mitglieder-Anlegepfad nicht als „alle Collections“ behandeln. Existenz in der Org ist kein Schreibzugriff.
CiphersController.cs (Post, PostCreate)CipherService.cs (SaveDetailsAsync)CipherRepository.cs (CreateAsyncReturnCipher, UpdateCollectionsAsync)