
Bitwarden Server v2026.9.2 - 高 - IDOR - 呼び出し元が書き込みできないコレクションに復号可能な保管庫アイテムを植え付ける
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · bitwarden-cipher-create-acl
Bitwarden Server v2026.9.2 - Bitwarden
Entity Framework パス(MariaDB、Postgres、SQLite)での組織暗号アイテム作成は、コレクションへのアタッチ前に呼び出し元 ID を破棄する。確認済みメンバーは、書き込み権限のないコレクションに組織キーのアイテムを植え付けることができる。コレクションメンバーはそれを通常の共有ログインとして同期する。
| ID | CVE 未割当 |
| CWE | CWE-863 / CWE-639 |
| CVSS | High: 7.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L |
| 製品 | Bitwarden Server |
| 影響範囲 | v2026.9.2 (9ee4e0eb) lite EF (MariaDB / Postgres / SQLite)。MSSQL/Dapper は @UserId を保持する。 |
| 認証 | 確認済み組織メンバー |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1 のみ |
攻撃者は共有コレクションに保管庫アイテムを追加する。既に存在するシークレットを読み取ったり置き換えたりはしない。
確認済み組織メンバーは既に組織キーを所持しているため、新しいアイテムはそのコレクションを閲覧できる全員に対して復号される。Bitwarden はそれを社内保管庫内の通常の共有ログイン、ノート、カード、または SSH キーとして表示する。
Okta、GitHub、VPN、Payroll)に似た名前のログインを植え付け、その URI を攻撃者が制御するホストに向ける。コレクションメンバーは Bitwarden からそれを開いて攻撃者ページに到達するか、類似サイトに対して自動入力する。new AWS key、bastion SSH key、DB password after change)を植え付ける。誰かがそれを本番環境やターミナルにコピーする。Production を読み取りのみ許可された請負業者でも、lite EF 上では新しいアイテムをそこに投入できる。対象コレクションへのアクセス権がない場合、POST /api/ciphers/create は書き込みが既にコミットされた後に 404 を返すことがある。被害者は同期時にそのアイテムを受け取る。
2026 年の一連の脆弱性(admin-request TDE (CVE-2026-60104)、SSO ExternalId 切り捨て (CVE-2026-101878)、組織インポートの空コレクション (CVE-2026-43638))の後、bitwarden/server v2026.9.2 (9ee4e0eb) を固定した。これらは修正済みである。作成時のコレクション ACL は修正されていなかった。
CiphersController.PostCreate は組織メンバーシップのみを確認し、OrganizationId が設定されている場合は skipPermissionCheck: true を渡す。SaveDetailsAsync は「このコレクションが組織内に存在する」ことだけをコレクションのチェックとして扱う。
lite MariaDB/Postgres/SQLite は EF を使用する。CreateAsyncReturnCipher は組織 ID が存在するため cipher.UserId = null を設定し、その null を UpdateCollectionsAsync に渡す。ユーザー ID が null であることは組織内の全コレクションを意味する。SQL Server Dapper は Cipher_UpdateCollections に対して @UserId を保持する(ReadOnly = 0)。そのパスがネガティブケースである。
既に記録済みの誤った道筋:クラウドの POST /organizations をセルフホストの作成とみなす(これは [NotSelfHostedOnly] であり、lite はライセンスファイルを要求するため、ラボでは登録後に組織行をシードする);呼び出し元が読み取れないコレクションに植え付けて HTTP 404 を失敗と解釈する(CollectionCipher 行は既にコミットされている);MSSQL lite でそれが表示されると仮定する(Dapper は呼び出し元 ID を破棄しない);BW_ENABLE_ADMIN をオフのままにして lite が User / OrganizationDomain をマイグレーションしないようにする(このイメージでは admin が EF マイグレーターである);/identity/connect/token で Bitwarden-Client-Version を省略してパスワードグラントが 400 になるのを眺める。リバースシェル。芝居である。
cd lab
./run.sh
対象は必ず http://127.0.0.1:18160 のみ。イメージは ghcr.io/bitwarden/lite:2026.9.2 と 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
アクセス権なしの植え付けは CollectionCipher がコミットされた後に 404 を返す。被害者の GET /api/ciphers と /api/sync の両方に新しい ID が含まれる。B に対する読み取り専用は 200 を返し、それでも植え付けが成功する。外部組織のコレクションは join 行なしで 404 のままである。
保存ユーザー ID を EF の UpdateCollectionsAsync に渡す。CipherDetails_CreateWithCollections が保存された UserId カラムを null にした後でも @UserId を渡し続けているのと同じ方法で。メンバー作成パスにおいて、null ユーザーを「全コレクション」として扱ってはならない。組織内に存在することは書き込みアクセスではない。
CiphersController.cs (Post, PostCreate)CipherService.cs (SaveDetailsAsync)CipherRepository.cs (CreateAsyncReturnCipher, UpdateCollectionsAsync)