Bitwarden Server v2026.9.2 - 高危 - IDOR - 将可解密的保险库项目植入调用者无权写入的集合中
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · bitwarden-cipher-create-acl
技术分析文章:https://abraxaslabs.tech/research/bitwarden-cipher-create-acl
Bitwarden Server v2026.9.2 - Bitwarden
在 Entity Framework 路径(MariaDB、Postgres、SQLite)上创建组织密码库条目时,会在附加集合之前丢弃调用者 id。已确认的组织成员可以将一个使用组织密钥加密的条目植入到其无权写入的集合中。集合成员会将其作为普通共享登录条目同步。
| ID | 暂无 CVE |
| CWE | CWE-863 / CWE-639 |
| CVSS | 高危: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 年那一波漏洞之后,我锁定了 bitwarden/server v2026.9.2(9ee4e0eb):管理员请求 TDE(CVE-2026-60104)、SSO ExternalId 截断(CVE-2026-101878)、组织导入空集合(CVE-2026-43638)。这些均已修复。但创建时的集合 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。一个反向 shell。戏剧。
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 且仍会植入。外部组织的集合保持 404,且没有 join 行。
将保存用户的 id 传入 EF 的 UpdateCollectionsAsync,方式与 CipherDetails_CreateWithCollections 在将存储的 UserId 列置空后仍传递 @UserId 相同。在成员创建路径上,不要将 null 用户视为“所有集合”。在组织中的存在性并不等于写入权限。
CiphersController.cs(Post、PostCreate)CipherService.cs(SaveDetailsAsync)CipherRepository.cs(CreateAsyncReturnCipher、UpdateCollectionsAsync)