Reports
MEDIA[AUTENTICACIÓN]#4071064

Essity: registro oculto permitía a cualquiera crearse una cuenta en un portal interno de proveedores y ver datos de vendedores

Un portal interno de compras de Essity mantenía activa la ruta /Account/Register de ASP.NET Identity. Sin invitación ni aprobación, bastaba un correo para crear cuenta, entrar y recibir datos reales de proveedores.

Resumen
Resumen en castellano de un reporte público, no una traducción literal. El código y los comandos se mantienen como en el original.

Resumen

El programa de Essity tenía un alcance abierto, así que el investigador partió de la enumeración por ASN para localizar subdominios de la empresa. Uno de ellos alojaba un portal interno de compras orientado a proveedores (su nombre aparece censurado en el reporte). La página de inicio de sesión no ofrecía ninguna forma de darse de alta, pero en el JavaScript de la aplicación aparecía una ruta que la interfaz no mostraba, y que además es una de las rutas estándar del controlador de cuentas de ASP.NET Identity:

/Account/Register

Seguía publicada y funcionaba por completo: no pedía invitación, código de cliente o de proveedor, ni aprobación de nadie, y no comprobaba de ninguna manera que quien se registraba tuviese relación con Essity o con alguno de sus proveedores. El único requisito era tener un buzón de correo.

Con la cuenta creada de esta forma, la aplicación cargaba sola, nada más iniciar sesión, datos reales: la lista de proveedores con su número y su nombre, además de regiones y definiciones de referencia. En el fondo es la falta de autenticación en una función crítica: el alta de usuarios en un sistema que debería ser solo para personal y proveedores verificados.

Pasos de reproducción

  1. Abrir directamente la ruta de registro del portal. No hay ningún enlace a ella desde /Account/Login ni desde otra parte de la aplicación, pero responde con HTTP 200 y un formulario operativo:
GET /Account/Register
  1. Rellenar el formulario con datos cualesquiera. No hay restricción por dominio de correo, ni campo de código de proveedor, ni token de invitación, ni paso de aprobación. El investigador usó su alias de correo de HackerOne y estos valores:
Email:        [REDACTADO]
First Name:   [REDACTADO]
Last Name:    [REDACTADO]
Phone Number: (dígitos cualesquiera, no se validan contra ningún registro)
Company Name: HackerOne Security Research
  1. Enviar el formulario. Llega un correo de confirmación con un enlace de este tipo:
/Account/ConfirmEmail?userId=<guid>&code=<token>

Al abrirlo, la aplicación responde "Thank you for confirming your email." La cuenta ya está activa. Como el formulario de registro no tiene campo de contraseña, en este punto la cuenta existe pero sin credenciales.

  1. Ir a /Account/ForgotPassword, introducir el mismo correo y enviar. Llega un correo para restablecer la contraseña.
  1. Abrir ese enlace y fijar una contraseña en /Account/ResetPassword.
  1. Iniciar sesión en /Account/Login con el correo y la contraseña del paso anterior. La cabecera saluda con "Welcome … from HackerOne Security Research", es decir, con los datos del registro sin ninguna verificación. El menú muestra Home, Purchase Orders/Deliveries, Payments, Blanket Orders y Glossary, además de un buscador por número de pedido ("Purchase Order #").
  1. Revisar en el historial del proxy las peticiones XHR que la propia aplicación lanza al entrar, sin hacer nada más:
GET /vendor/Vendors      →  200, application/json, 1719 bytes
GET /vendor/Regions      →  200, application/json
GET /vendor/definitions  →  200, application/json
GET /release/statuses    →  500, text/html, 4391 bytes

La respuesta de /vendor/Vendors es un array JSON con registros reales de proveedores (valores censurados en el reporte):

[{"VendorNumber":"<redacted>","VendorName":"<redacted>"}, ...]

Esto confirma que la cuenta autoregistrada no está aislada ni ve un entorno vacío, sino datos reales.

Impacto

  • Alta de cuentas sin control: cualquier persona en Internet podía darse de alta en un sistema interno de compras de Essity con solo un correo electrónico.
  • Lectura de datos de proveedores: la cuenta recibía, sin pedirlo, la lista de números y nombres de proveedores y los datos de referencia de /vendor/Regions y /vendor/definitions.
  • Acceso a secciones sensibles: la interfaz exponía pedidos y entregas, pagos y pedidos abiertos (blanket orders). Una búsqueda por número de pedido devolvió "please narrow your search", señal de que la consulta llegaba a un conjunto de datos poblado y no a uno vacío.
  • Pretexto para ingeniería social: una cuenta de aspecto legítimo en el portal de proveedores serviría para hacerse pasar por proveedor ante el personal de compras de Essity, o ante los propios proveedores cuyos nombres revela el portal.

El investigador acotó con cuidado lo que comprobó: vio que se devolvían datos de proveedores observando solo las llamadas automáticas de la aplicación, pero no navegó, buscó, exportó ni abrió registros, y no probó si había permisos de escritura ni otros fallos de autorización. El reporte figura con severidad media y como resuelto; no detalla cómo se corrigió.

Qué aprender de este caso

  • En aplicaciones ASP.NET con Identity, prueba siempre las rutas por defecto del controlador de cuentas (/Account/Register, /Account/ConfirmEmail, /Account/ForgotPassword, /Account/ResetPassword) aunque la interfaz no las enlace: la plantilla las genera y es fácil olvidarse de quitarlas.
  • Busca en los ficheros JavaScript del cliente rutas que no aparecen en la navegación; esconder un enlace en la interfaz no desactiva el endpoint del servidor.
  • Si un registro no pide contraseña, revisa si el flujo de "olvidé mi contraseña" sirve para completar la cuenta: aquí convirtió una cuenta a medio crear en un acceso plenamente funcional.
  • Al construir un portal privado sobre una plantilla con registro público, elimina o protege la acción de registro en el servidor (invitaciones, códigos de proveedor o aprobación manual) y asegúrate de que una cuenta nueva no reciba datos hasta estar vinculada a una entidad verificada.