
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 | 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 и попадают на страницу атакующего или используют автозаполнение на похожем сайте.новый ключ AWS, SSH-ключ bastion, пароль БД после смены). Кто-то копирует его в продакшен или терминал.Production, всё равно может добавить новый элемент в неё на lite EF.Если у них нет доступа к целевой коллекции, POST /api/ciphers/create может вернуть 404 уже после того, как запись зафиксирована. Жертвы всё равно получают элемент при синхронизации.
Я зафиксировал bitwarden/server v2026.9.2 (9ee4e0eb) после волны 2026 года: TDE по запросу администратора (CVE-2026-60104), усечение SSO ExternalId (CVE-2026-101878), пустые коллекции при импорте организации (CVE-2026-43638). Они закрыты. ACL коллекции при создании — нет.
CiphersController.PostCreate проверяет только членство в организации, а затем передаёт skipPermissionCheck: true, когда задан OrganizationId. SaveDetailsAsync затем считает «эта коллекция существует в организации» единственной проверкой коллекции.
Lite MariaDB/Postgres/SQLite используют EF. CreateAsyncReturnCipher устанавливает cipher.UserId = null, поскольку присутствует id организации, а затем передаёт этот null в UpdateCollectionsAsync. Null user id означает все коллекции в организации. SQL Server Dapper сохраняет @UserId для Cipher_UpdateCollections (ReadOnly = 0). Этот путь — отрицательный.
Ошибочные шаги, уже зафиксированные: трактовка облачного POST /organizations как self-host создания (это [NotSelfHostedOnly]; lite требует файл лицензии, поэтому лаборатория заполняет строки организаций после регистрации); внедрение в коллекцию, которую вызывающий не может прочитать, и трактовка HTTP 404 как промаха (строка CollectionCipher уже зафиксирована); предположение, что MSSQL lite это покажет (Dapper не отбрасывает идентификатор вызывающего); оставление BW_ENABLE_ADMIN выключенным, из-за чего lite никогда не мигрирует User / OrganizationDomain (admin — это EF-мигратор в этом образе); пропуск Bitwarden-Client-Version в /identity/connect/token и наблюдение за 400 при password grant. Обратная оболочка. Театр.
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
Растение без доступа возвращает 404 после фиксации CollectionCipher. У жертвы GET /api/ciphers и /api/sync оба содержат новый id. Read-only на B возвращает 200 и всё равно внедряет. Коллекция чужой организации остаётся 404 без строки join.
Передайте id сохраняющего пользователя в EF UpdateCollectionsAsync так же, как CipherDetails_CreateWithCollections по-прежнему передаёт @UserId после того, как он обнуляет сохранённый столбец UserId. Не трактуйте null-пользователя как «все коллекции» на пути создания участника. Наличие в организации не является правом на запись.
CiphersController.cs (Post, PostCreate)CipherService.cs (SaveDetailsAsync)CipherRepository.cs (CreateAsyncReturnCipher, UpdateCollectionsAsync)