Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
lago-invite-ato — Laboratorio de prueba de concepto que demuestra un bypass de autenticación crítico en el acceptInvite de GraphQL de Lago, el cual permite la toma de control de cuentas entre organizaciones mediante la aceptación de invitaciones sin autenticación. | Kitploit
Herramientas/GitHubGitHub/abraxas/lago-invite-ato
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad WebPruebas de PenetraciónAutenticaciónSeguridad de APIsLabs y Práctica
GitHubabraxas/lago-invite-ato

lago-invite-ato

Laboratorio de prueba de concepto que demuestra un bypass de autenticación crítico en el acceptInvite de GraphQL de Lago, el cual permite la toma de control de cuentas entre organizaciones mediante la aceptación de invitaciones sin autenticación.

11hace 15 díasAún no revisado
Ver Repositorio

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Abraxas Labs - lago-invite-ato

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  lago-invite-ato

lago-invite-ato

Lago v1.53.0 - GetLago

Mutations::Invites::Accept no tiene AuthenticableApiUser. Create/revoke sí. Accept no. register_from_invite carga el usuario por el email de la invitación. Si esa cuenta ya tiene membresías, la contraseña enviada se descarta. AuthToken.encode(user:) igual se ejecuta. El JWT está acotado al usuario. Sin claim de organización. El cliente envía x-lago-organization para la organización a la que ese usuario ya pertenece. Incluida la de la víctima. createInvite ya devuelve el token al invitador.

Invita a cfo@victim a una organización desechable, acéptala tú mismo, y eres esa persona en cada organización en la que ese email ya esté. El buzón nunca interviene. La contraseña de la víctima no cambia.

IDaún sin CVE
CWECWE-287, CWE-306
CVSSCrítico: 9.6 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N
ProductoLago / lago-api
Afectadohasta v1.53.0 acceptInvite con email/contraseña
Authadmin de organización (organization:members:create); basta con registrarse en Cloud
LicenciaGNU Affero GPL v3.0
Labsolo 127.0.0.1

Qué puede hacer un atacante

Necesitas una organización que controles. Basta con registrarse en Cloud (LAGO_DISABLE_SIGNUP es false por defecto). Invita un email de la víctima, acepta sin autenticación con una contraseña ficticia, y luego cambia la cabecera a Victim Corp. Facturas, claves de API, Stripe, wallets.

No es un visitante aleatorio sin cuenta. No es un restablecimiento de contraseña. El login ficticio falla. La contraseña real de la víctima sigue funcionando. El accept de Google/Okta vincula el email del IdP y no es este bug. Un self-host de una sola organización sin el email de nadie más en la base de datos no te da acceso a otro comerciante. La misma base de datos, dos organizaciones, el mismo email: sí lo hace.

Mismo árbol que el IDOR de factura única de Stripe. Bug distinto.

Cómo lo encontré

Leí Accept (sin AuthenticableApiUser), luego find_or_initialize_by(email:), luego la rama de membresías presentes que omite la contraseña, luego AuthToken.encode(user:). Luego el accept de Google, que sí comprueba google_oidc["email"] == invite.email. El accept con email/contraseña no vincula la contraseña de un usuario existente.

El primer cliente que mire esto invitará una dirección sin usar, la aceptará, y obtendrá un usuario de Lago completamente nuevo con la contraseña que envió. Esa es la funcionalidad. El testigo es el id del usuario víctima existente que regresa.

Desvíos ya registrados: aceptar con Google/Okta; tratar el 401 de createInvite sin un JWT como toda la historia (create está autenticado, accept no); mirar solo la organización del atacante en currentUser (la pista es Victim Corp en la lista); que la contraseña ficticia inicie sesión (eso significaría que el hash fue sobrescrito - el lab afirma que no lo fue); una reverse shell. Teatro. Sin bandeja de entrada.

Luego: dos llamadas a registerUser plantan Victim Corp y Attacker Corp. Emails nuevos en cada ejecución para que un volumen sucio no devuelva 422 user_already_exists. createInvite sobre el email de la víctima. acceptInvite sin autenticación con una contraseña ficticia. El id de usuario devuelto coincide con el de la víctima. currentUser.organizations lista ambas. El cambio de cabecera devuelve Victim Corp.

Lab

cd lab
./run.sh

Objetivo solo http://127.0.0.1:13000. El IDOR de Stripe usó 13001. Sin puerto de UI.

IOC victim_password_unchanged
IOC victim_real_password_still_works
SUCCESS LAGO-INVITE-ATO acceptInvite JWT is existing victim; lists Victim Corp; no inbox

La solución

Si el usuario ya existe, exige que se autentique como él mismo (o que demuestre el buzón / IdP) antes de adjuntar la membresía. No emitas un JWT para un usuario existente desde un accept sin autenticación. Deja de devolver el token de la invitación al invitador si es una capacidad.

Referencias

  • github.com/getlago/lago tag v1.53.0 · lago-api
  • accept.rb · accept_service.rb · users_service.rb · create.rb · object.rb · google_service.rb
  • Mismo producto: lago-stripe-invoice-idor
  • CWE-287 · CWE-306

Licencia

GNU Affero GPL v3.0. Ver LICENSE. Solo lab en loopback. Sin garantía.

Descargar herramienta