Resumen
En un dominio de Essity seguía publicado un script CGI escrito en Perl, una herramienta interna antigua (los metadatos de la página la atribuyen a SCA/Essity). El script tiene una acción Register que recibe varios datos de contacto y los vuelve a pintar en la respuesta. Uno de esos parámetros (su nombre está tapado en la divulgación) se insertaba en el HTML sin ningún tipo de codificación de salida, así que cualquier etiqueta que llegase en él se interpretaba como parte de la página.
El resultado es un XSS reflejado clásico: no hace falta estar autenticado y funciona tanto por GET como por POST. La ruta, el host y el nombre del parámetro aparecen ocultos (████████) en el reporte publicado.
El reporte se envió el 29 de junio de 2026 y se divulgó al día siguiente, ya resuelto, con severidad alta.
Pasos de reproducción
- Sin iniciar sesión, abrir esta URL, que mete un
<script>codificado en URL dentro del parámetro vulnerable:
https://████████/cgi-bin/████████.pl?action=Register&████████=%3Cscript%3Ealert(document.domain)%3C%2Fscript%3E&last=████████&████████=123
- Mirar el cuerpo de la respuesta. El payload aparece decodificado y sin escapar, junto al resto de datos del "registro":
<br>
<script>alert(document.domain)</script> ████████, Tel: 123
<br>
- Para confirmarlo fuera del navegador, el investigador usó curl con la cabecera de identificación de investigación de HackerOne:
curl -sk -H "X-HackerOne-Research: ████████" \
"https://████████/cgi-bin/████████.pl?action=Register&████████=%3Cscript%3Ealert(document.domain)%3C%2Fscript%3E&last=████████&████████=123"
- Enviar los mismos parámetros por POST da el mismo resultado: el fallo no depende del método.
Según el reporte, el parámetro last y otro más (también oculto en la divulgación) se reflejan igualmente en la respuesta, pero el investigador solo confirmó que aparecían, sin llegar a explotarlos.
Impacto
Quien abriese un enlace preparado ejecutaría JavaScript del atacante en el origen del dominio de Essity, sin necesidad de autenticación. A partir de ahí, el reporte señala:
- Robo de sesión de los usuarios de ese origen.
- Phishing de credenciales servido desde un dominio de Essity, lo que lo hace mucho más creíble.
- Inyección de contenido o desfiguración de la página.
Además, el código fuente de la página filtraba metadatos de infraestructura interna, en concreto el nombre de un host interno.
Remediación
El reporte figura como resuelto, pero no detalla qué se hizo (si se retiró el script o se añadió codificación de salida). La corrección natural es escapar en HTML cada valor antes de escribirlo en la respuesta o, si la herramienta ya no se usa, retirarla del servidor.
Qué aprender de este caso
- Los directorios
/cgi-bin/de dominios corporativos antiguos merecen un repaso: los scripts.plque nadie mantiene suelen imprimir los parámetros conprintdirectamente, sin ninguna plantilla que escape por defecto. - Las acciones que "confirman" lo que acaba de enviar el usuario (registro, resumen de un formulario, "Gracias, X, te llamaremos al Y") son el sitio típico donde buscar un reflejo: prueba cada campo, no solo el primero, y con GET y POST.
- En Perl, cualquier valor que acabe en HTML debe pasar por una función de escape como
escapeHTMLde CGI.pm oencode_entitiesde HTML::Entities antes delprint; sin eso, el script es vulnerable por diseño. - Revisa también la etiqueta
<meta name="generator">y los comentarios del HTML de estas herramientas: en este caso dejaban ver un host interno, una pista útil para un atacante.