
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
Write-up: https://abraxaslabs.tech/research/bitwarden-cipher-create-acl
Bitwarden Server v2026.9.2 - Bitwarden
Das Erstellen eines Org-Ciphers auf dem Entity-Framework-Pfad (MariaDB, Postgres, SQLite) verwirft die Aufrufer-ID, bevor die Collection angehängt wird. Ein bestätigtes Mitglied kann ein Element mit Org-Schlüssel in eine Collection einschleusen, auf die es keinen Schreibzugriff hat. 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üsselbar ist, die diese Collection sehen können. Bitwarden zeigt es als normalen geteilten Login, Notiz, Karte oder SSH-Schlüssel innerhalb des Unternehmens-Vaults an.
Okta, GitHub, VPN, Payroll) einschleusen, dessen URI auf einen vom Angreifer kontrollierten Host zeigt. Collection-Mitglieder öffnen es aus Bitwarden und landen auf der Angreiferseite 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 dennoch ein neues Element dort ablegen.Wenn sie keinen Zugriff auf die Ziel-Collection haben, kann POST /api/ciphers/create nach dem bereits committeten Schreibvorgang 404 zurückgeben. Opfer erhalten das Element dennoch beim Sync.
Ich habe bitwarden/server v2026.9.2 (9ee4e0eb) nach der Welle von 2026 gepinnt: Admin-Request-TDE (CVE-2026-60104), SSO-ExternalId-Truncation (CVE-2026-101878), Org-Import leerer Collections (CVE-2026-43638). Diese sind geschlossen. Die Collection-ACL beim Erstellen 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 reicht dieses Null dann an UpdateCollectionsAsync weiter. Eine Null-User-ID bedeutet jede Collection in der Org. SQL Server Dapper behält @UserId für Cipher_UpdateCollections (ReadOnly = 0). Dieser Pfad ist der Negativfall.
Bereits festgehaltene Fehlversuche: das Cloud-POST /organizations als Self-Host-Erstellung zu behandeln (es ist [NotSelfHostedOnly]; lite will eine Lizenzdatei, daher legt das Lab Org-Zeilen nach der Registrierung an); in eine Collection zu pflanzen, die der Aufrufer nicht lesen kann, und HTTP 404 als Fehltreffer zu lesen (die CollectionCipher-Zeile ist bereits committet); anzunehmen, MSSQL lite würde es zeigen (Dapper verwirft die Aufrufer-ID nicht); BW_ENABLE_ADMIN ausgeschaltet zu lassen, sodass lite niemals User / OrganizationDomain migriert (admin ist der EF-Migrator auf diesem Image); das Weglassen von Bitwarden-Client-Version bei /identity/connect/token und das Beobachten eines Password-Grant-400. Eine Reverse Shell. Theater.
cd lab
./run.sh
Ziele 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
Eine Pflanze ohne Zugriff gibt nach dem Commit von CollectionCipher 404 zurück. Die GET /api/ciphers und /api/sync des Opfers enthalten beide die neue ID. Read-only auf B gibt 200 zurück und pflanzt weiterhin. Eine Collection einer fremden Organisation bleibt 404 ohne Join-Zeile.
Übergeben Sie die ID des speichernden Benutzers an EF UpdateCollectionsAsync auf dieselbe Weise, wie CipherDetails_CreateWithCollections weiterhin @UserId übergibt, nachdem es die gespeicherte Spalte UserId auf null gesetzt hat. Behandeln Sie einen null-Benutzer auf dem Member-Erstellungspfad nicht als „alle Collections“. Existenz in der Organisation ist kein Schreibzugriff.
CiphersController.cs (Post, PostCreate)CipherService.cs (SaveDetailsAsync)CipherRepository.cs (CreateAsyncReturnCipher, UpdateCollectionsAsync)