Resumen
El investigador db3wy encontró en Remitly, servicio de envío de dinero, un fallo crítico de control de acceso en el proceso de "contraseña olvidada". El punto clave es el endpoint:
/orchestrator/v1/password_reset/start
Al iniciar un restablecimiento para un correo cualquiera, una de las respuestas de ese endpoint devolvía un JWT con el email del usuario y otros datos. Junto a ese JWT viajaba la cookie AMP_d0cf3ed24c, que según el reporte contiene deviceId, userId y sessionId. Con esos dos valores, el atacante podía completar el restablecimiento usando su propio código de un solo uso (OTP) y, en el último paso, presentarse como la víctima. El servidor no comprobaba que el OTP validado perteneciera a la misma cuenta cuya contraseña se cambiaba.
La víctima no tenía que hacer nada (de ahí lo de "0-click"): ni pulsar un enlace ni introducir un código. HackerOne lo clasifica como Improper Access Control - Generic, con severidad crítica. Se envió el 10 de noviembre de 2024, quedó resuelto y se divulgó el 21 de julio de 2025. Hubo recompensa, pero su importe no es público.
Pasos de reproducción
El investigador usó Firefox para la cuenta atacante y el navegador de Burp Suite para la de la víctima, todo con un proxy que intercepta el tráfico.
- Abrir la página de "Contraseña olvidada" de Remitly.
- Iniciar el restablecimiento con el correo de la víctima e interceptar el tráfico con Burp Suite u OWASP ZAP.
- Localizar la respuesta de
/orchestrator/v1/password_reset/startque incluye un JWT. Hay dos llamadas con el mismo nombre y solo una lo devuelve; no siempre aparece al primer intento (al investigador le salió en el segundo). La extensión JSON Web Token de Burp resalta en verde las peticiones con JWT y ayuda a encontrarla. Un JWT de la víctima sacado de cualquier otro endpoint no sirve. - Guardar dos valores de esa petición: el JWT de la víctima y su cookie
AMP_d0cf3ed24c. - Iniciar ahora el restablecimiento con el correo del atacante y escribir el OTP que le llega a su email o teléfono.
- Antes de enviar la petición que fija la nueva contraseña, sustituir en ella el JWT y la cookie
AMP_d0cf3ed24cdel atacante por los de la víctima guardados en el paso 4. - Enviar la petición modificada.
- Iniciar sesión con el correo de la víctima y la contraseña nueva.
El reporte original incluía un vídeo y capturas, que no son públicos.
Impacto
Bastaba con conocer el correo de la víctima para quedarse con su cuenta:
- Control total de la cuenta y acceso a los datos personales que guarda.
- Posibilidad de cambiar el email asociado y otros ajustes sin que la víctima lo autorice.
- Dejar a la víctima fuera de su propia cuenta al cambiarle la contraseña.
- Al ser una plataforma de transferencias, el investigador señala que el atacante podría enviar a su cuenta el dinero disponible de la víctima.
Qué aprender de este caso
- En cualquier restablecimiento en varios pasos, prueba a validar el OTP con tu cuenta y cambiar en el paso final los identificadores (JWT, cookies de sesión,
userId) por los de otra cuenta: si el servidor no lo rechaza, no está ligando el código a la cuenta. - Revisa todas las respuestas del inicio del reset, también las que se repiten con el mismo endpoint: aquí una de las dos llamadas a
/orchestrator/v1/password_reset/startdevolvía un JWT de la víctima a quien no había demostrado nada. - Al programar, el servidor debe guardar en su lado qué cuenta ha superado el OTP y aceptar el cambio de contraseña solo para esa cuenta, sin fiarse de tokens o cookies que manda el cliente.
- Un token de "reset iniciado" no debe servir para fijar la contraseña: solo debería emitirse uno válido para ese paso después de verificar el código de la cuenta afectada.