Detección de contenido mediante extensiones no estándar: cómo surge el XSS y cómo protegerse

Detección de contenido mediante extensiones no estándar: cómo surge el XSS y cómo protegerse

Content-sniffing — es un comportamiento de los navegadores en el que el tipo del recurso transmitido se determina no solo por la cabecera Content-Type, sino también por las firmas del contenido. En la situación ideal el servidor establece correctamente el tipo y el navegador lo respeta. En la práctica, configuraciones erróneas, nodos intermedios entre la aplicación y el usuario (CDN, proxy), así como el uso de extensiones no estándar hacen que un documento con una extensión «segura» se interprete como contenido activo (HTML, SVG, XML). Como resultado surgen escenarios de XSS, robo de tokens y otras consecuencias. A continuación hay un panorama sistemático de cómo surge el riesgo, qué vectores de ataque existen y cómo construir la protección.

Qué es Content Sniffing y por qué se activa

Los navegadores han implementado históricamente un mecanismo para determinar el tipo de recurso según el contenido, con el fin de mostrar correctamente los datos incluso cuando las cabeceras son incorrectas. Esto coincide con las expectativas del usuario, pero añade una superficie de ataque para las aplicaciones. Si el servidor entrega un archivo con un Content-Type incorrecto o sin una prohibición explícita del «sniffing» (cabecera X-Content-Type-Options: nosniff), el motor puede redefinir el tipo basándose en los primeros bytes y en marcadores característicos del formato.

  • Causa raíz: desacuerdo entre el declarado Content-Type y el contenido real.
  • Condición de activación: ausencia de X-Content-Type-Options: nosniff y/o tipo débil (por ejemplo, text/plain) para contenido potencialmente activo.
  • Consecuencia: interpretación del archivo como HTML/SVG/XML y ejecución de scripts en el contexto del dominio donde se publicó el archivo.

Por qué las extensiones no estándar aumentan el riesgo

La extensión del archivo es un convenio a nivel de SO e interfaces de carga; el navegador se apoya en las cabeceras y en el contenido. Las extensiones no estándar (.abc, .backup, .txtx, etc.) con frecuencia pasan los filtros, «enmascarando» contenido activo. Si además el servidor entrega un tipo genérico o inadecuado, el navegador tiende a «precisar» el tipo por el contenido y mostrará el documento en lugar de ofrecer la descarga.

  • La combinación «extensión no estándar + Content-Type incorrecto + ausencia de nosniff» crea condiciones para XSS.
  • Los archivos polyglot (válidos en varios formatos a la vez) evaden comprobaciones superficiales por extensión y firmas.
  • SVG tiene un modelo de documento completo; en renderizado inline o documental es posible la ejecución de scripts.

Escenarios típicos de explotación

A continuación se presentan variantes habituales de abuso del content sniffing al subir y publicar archivos de usuario. Los ejemplos sirven para entender los riesgos y definir medidas de protección en el ámbito legítimo de prueba de sistemas propios.

  1. Publicación de archivos subidos en el mismo dominio.

    Un usuario sube «report.backup», que en realidad contiene HTML/JS. El almacenamiento entrega el archivo como text/plain, la cabecera nosniff no está presente. El navegador muestra el documento como HTML. El script adquiere permisos del mismo sitio (según políticas), lo que conduce a XSS y compromiso de sesión.

  2. Host único para la aplicación y archivos de usuario.

    Los archivos están disponibles bajo rutas como /uploads/… en el dominio principal. Con un Content-Type erróneo y sin aislamiento (cookies, CSP), cualquier archivo mal servido se convierte en una página activa en un contexto de confianza.

  3. Sobrescritura de cabeceras en CDN/proxy.

    La aplicación genera cabeceras correctas (application/octet-stream, Content-Disposition: attachment), pero un nodo intermedio optimiza la caché y reemplaza el tipo por text/plain, eliminando nosniff. En la salida el documento se muestra en lugar de descargarse.

  4. Renderizado inline de SVG.

    Los archivos SVG procedentes de cargas de usuarios se muestran como documentos. Sin políticas estrictas (CSP, sandbox) es posible la ejecución de scripts y XSS.

  5. Archivos polyglot.

    Un archivo que combina la firma de una imagen y un HTML válido salva filtros superficiales y puede ser interpretado por el navegador como un documento HTML.

Diagnóstico: cómo detectar la vulnerabilidad en su sistema

Se recomienda realizar pruebas en entornos controlados y dentro de un perímetro autorizado. El objetivo es comprobar cómo el sistema gestiona tipos ambiguos de archivos y qué cabeceras llegan realmente al cliente.

  1. Conjunto de muestras de control.
    • HTML con extensión no estándar (.abc, .backup, etc.).
    • SVG con marcador seguro (por ejemplo, salida en consola).
    • Polyglot (firma mínima de imagen + cuerpo HTML) — solo en bancos de pruebas de laboratorio.
  2. Análisis de respuestas.
    • Verifique Content-Type, Content-Disposition, X-Content-Type-Options, Content-Security-Policy.
    • Abra el enlace directo y registre el comportamiento: descarga o visualización.
  3. Verificación de extremo a extremo de la cadena de entrega.
    • Compruebe si CDN/proxy modifican las cabeceras finales.
    • Compare el comportamiento en navegadores principales (Chrome, Firefox, Safari).
  4. Comprobación del aislamiento por dominio.
    • Determine desde qué host se entregan los archivos de usuario (mismo dominio/subdominio/dominio separado).
    • Verifique si ese host aplica cookies y políticas del aplicativo principal.

Herramientas útiles: Burp Suite, OWASP ZAP, DevTools de los navegadores, así como servicios de evaluación de cabeceras: SecurityHeaders, Mozilla Observatory.

Limitaciones de «nosniff» y peculiaridades de formatos

X-Content-Type-Options: nosniff desactiva la heurística de sniffing y fuerza al navegador a confiar en el Content-Type indicado. Sin embargo, con un tipo débil y sin otras medidas la protección será incompleta. De modo similar, los formatos que pueden contener contenido activo (SVG, ciertos casos de PDF/XML) requieren restricciones adicionales incluso con tipos correctos.

  • Asigne un Content-Type correcto y complételo con nosniff.
  • Para contenido potencialmente activo use Content-Disposition: attachment.
  • Controle el comportamiento de nodos intermedios que puedan reescribir cabeceras.

Información de referencia: MDN: X-Content-Type-Options.

Anti-patrones de configuración

  • Mismo dominio para la aplicación y archivos de usuario sin CSP ni sandbox.
  • Uso de tipo genérico (application/octet-stream) para recursos heterogéneos sin Content-Disposition: attachment.
  • Filtrado solo por extensión o solo por bytes mágicos sin validar la estructura del formato.
  • Renderizado inline de SVG/HTML de usuarios sin limpieza ni aislamiento.
  • Confiar en funciones «inteligentes» del CDN que pueden modificar cabeceras sin control explícito.

Estrategia integral de protección

La protección eficaz se apoya en la combinación de aislamiento, tipado correcto, forzar la descarga y políticas del navegador. A continuación se ofrece un conjunto práctico de medidas.

  1. Aislamiento de archivos de usuario por dominio.

    Aloje las subidas de usuarios en un dominio/subdominio separado que no comparta cookies con la aplicación (por ejemplo, files.exampleusercontent.com). Esto reduce los privilegios del contenido incluso si se muestra como documento.

  2. Content-Type correcto y prohibición del sniffing.
    • Asigne tipos precisos para los formatos soportados.
    • Establezca X-Content-Type-Options: nosniff para todas las respuestas de estáticos y descargas.
  3. Forzar la descarga de formatos activos.
    • Use Content-Disposition: attachment; filename="..." para HTML, SVG, XML y para PDF cuando haya dudas.
    • No renderice inline archivos de usuario sin necesidad y sin limpieza.
  4. Validación del contenido.
    • Compruebe la estructura de los archivos y use decodificadores de librería.
    • Para imágenes aplique re-encode en el servidor a un formato de confianza, descartando segmentos no estándar.
  5. Políticas del navegador (CSP y complementarias).

    Implemente una estricta Content-Security-Policy para los dominios de la aplicación y para los dominios donde pueda mostrarse contenido. Prohíba scripts inline y eval, limite las fuentes. Guía: MDN: CSP.

  6. Control del comportamiento de CDN/servicios en la nube.

    En S3 y equivalentes fije metadatos de objetos con el tipo exacto y Content-Disposition. En el edge (CloudFront/Cloudflare/Fastly) prohíba explícitamente la reescritura de cabeceras críticas y verifique las vistas previas.

  7. Automatización del control.

    Añada en CI/CD pruebas de cabeceras y del comportamiento al abrir archivos. Ejecute regularmente DAST sobre rutas clave de entrega de archivos.

Lista de verificación para Dev, DevOps y AppSec

  • Los archivos de usuario se entregan desde un dominio/subdominio separado sin cookies compartidas con la aplicación principal.
  • Cada formato tiene un Content-Type correcto; no hay valores genéricos sin necesidad.
  • X-Content-Type-Options: nosniff está habilitado para respuestas estáticas y de archivos.
  • Content-Disposition: attachment se aplica a formatos potencialmente activos.
  • SVG de cargas de usuario no se muestra inline o se convierte a ráster.
  • CDN/proxy no modifican cabeceras críticas (verificado con pruebas end-to-end).
  • Se aplica CSP sin unsafe-inline ni unsafe-eval, y las fuentes de scripts están estrictamente limitadas.
  • En CI/CD existen pruebas básicas sobre cabeceras y comportamiento real del navegador.

Análisis de combinaciones críticas

HTML con extensión no estándar

El archivo «report.backup» contiene HTML. El servidor responde con Content-Type: text/plain, la cabecera nosniff falta. Algunos navegadores interpretan el contenido como documento HTML. Medidas: tipo correcto (o deliberadamente no visualizable), nosniff obligatorio, Content-Disposition: attachment y aislamiento por dominio.

SVG como documento

SVG puede incluir scripts y referencias a recursos externos. Si se muestra como documento es posible XSS. Recomendación: no mostrar SVG de usuarios inline; si es necesario, convertir a imagen ráster en el servidor y servir como adjunto.

Polyglot: imagen + HTML

Un polyglot puede pasar comprobaciones simples de firmas y ser interpretado por el navegador como HTML. El enfoque fiable es evitar el renderizado inline de archivos de usuario, re-encode de imágenes y cabeceras correctas.

Pruebas: orden de trabajo

Organice las pruebas en entornos autorizados. El objetivo es confirmar o descartar la posibilidad de que archivos de usuario se muestren como contenido activo.

  1. Identifique todos los puntos de entrega de archivos (enlaces directos, vistas previas, API con solicitudes range, ruta del CDN).
  2. Prepare un conjunto de muestras de control (HTML, SVG, polyglot) con distintas extensiones.
  3. Compruebe las cabeceras de respuesta y el comportamiento real en navegadores principales.
  4. Repita las comprobaciones a través del perímetro externo (CDN/proxy), compare cabeceras end-to-end.
  5. Documente las discrepancias e introduzca cambios en la configuración de la aplicación y en la capa edge.

Guías y herramientas: OWASP File Upload Cheat Sheet, OWASP Top 10, MDN: MIME types.

Configuración de cabeceras y políticas

Concéntrese en los siguientes elementos de configuración. No son intercambiables y funcionan de forma complementaria.

  • X-Content-Type-Options: nosniff — impide que el navegador reemplace el tipo del recurso basándose en el contenido.
  • Content-Type — debe corresponder al formato real y ser coherente en todo el sistema.
  • Content-Disposition: attachment — fuerza la descarga de formatos potencialmente peligrosos.
  • Content-Security-Policy — restringe orígenes de scripts/frames y reduce el daño incluso si hay visualización errónea.
  • Políticas cross-origin (CORP/COOP/COEP) — refuerzan el aislamiento de procesos y recursos.
  • Referrer-Policy — minimiza fugas de metadatos relacionadas.

Almacenamiento en la nube y CDN

Una causa frecuente de problemas es la discrepancia entre la entrega real y la configuración esperada de la aplicación. Es necesario fijar metadata de objetos y reglas en el nivel edge.

  • Para objetos en S3 o equivalentes establezca metadatos explícitos: metadata con Content-Type y Content-Disposition.
  • En el edge (CloudFront/Cloudflare/Fastly) impida la reescritura de cabeceras críticas; desactive la vista previa que puede mostrar SVG/HTML como documento.
  • Realice comprobaciones end-to-end periódicas comparando cabeceras de la aplicación y cabeceras finales en el cliente.

Equilibrio entre UX y seguridad

En algunos escenarios el usuario necesita vista previa de documentos en el navegador. Controle qué contenido puede renderizarse inline y en qué contexto.

  • Permita vistas previas inline solo para formatos de confianza generados por el sistema (por ejemplo, PDF generado por su propio motor, imágenes después del re-encode).
  • Las cargas externas muéstrelas solo tras normalización/sanitización; permita renderizado en iframe con sandbox y en un dominio separado.
  • Para las «zonas grises» aplique attachment y evite la visualización inline.

Plan de implementación en un sprint

Orden realista de acciones que reduce sustancialmente el riesgo sin proyectos largos.

  1. Inventario. Reúna la lista de todas las rutas de entrega de archivos, estáticas y de usuario. Registre las cabeceras actuales.
  2. Correcciones básicas. Active nosniff, homologue Content-Type, añada Content-Disposition: attachment para formatos activos.
  3. Aislamiento. Mueva los archivos de usuario a un dominio/subdominio separado, configure CSP, prohíba inline-SVG.
  4. Normalización de imágenes. Añada re-encode en servidor para imágenes de usuario.
  5. Control en edge. Fije reglas en CDN/proxy que impidan la reescritura de cabeceras.
  6. Pruebas automáticas. Incluya comprobaciones de cabeceras y apertura en CI/CD para rutas clave.

FAQ

  • ¿Es suficiente activar nosniff? No basta. Se requieren tipos correctos, attachment para formatos activos, aislamiento por dominio y políticas CSP.
  • ¿Garantiza la filtración por extensión? No. La extensión se puede modificar fácilmente y no refleja el contenido real.
  • ¿Se puede mostrar SVG inline? No se recomienda mostrar SVG de usuarios inline. Si es necesario, convierta a ráster y/o renderice en un iframe aislado en un dominio separado.
  • ¿El PDF es seguro por defecto? No siempre. Depende del renderizador y del contexto. Para PDF de usuario conviene usar attachment o un visor de confianza en un contexto aislado.

Materiales y herramientas recomendadas

Conclusiones

El content-sniffing en sí no es un defecto, pero combinado con cabeceras incorrectas y falta de aislamiento genera riesgos importantes. La explotación mediante extensiones no estándar es una práctica común que se basa en la discrepancia entre el tipo declarado y el contenido real. La reducción del riesgo se logra mediante una combinación de medidas: aislar los archivos de usuario en un dominio separado, tipado correcto y prohibición del sniffing, forzar la descarga de formatos activos, aplicar CSP estricta, normalizar imágenes y controlar rigurosamente el comportamiento de CDN/proxy. Las comprobaciones automatizadas regulares de cabeceras y de los escenarios de renderizado deben formar parte obligatoria del CI/CD.

Alt text