Todo script de terceros en su página de checkout, de login o de administración se ejecuta con los mismos privilegios que el usuario que la ha cargado. Si el host que sirve ese script resulta comprometido, el atacante obtiene también esos privilegios, igual que ocurre con XSS. La solución empieza por saber qué scripts se cargan, eliminar los que pueda y fijar o restringir el resto.
Sepa qué se ejecuta en las páginas sensibles
La hoja de referencia de OWASP sobre JavaScript de terceros señala tres riesgos: la pérdida de control sobre los cambios en su aplicación cliente, la ejecución de código arbitrario en los sistemas de los clientes y la filtración de información sensible a terceros. Entre sus ejemplos figuran el incidente de Ticketmaster en 2018 y la investigación de ClearSky sobre Magecart y el robo de datos de pago.
Elabore el inventario página por página, empezando por checkout, login y administración. Para cada script, anote la URL, el responsable de negocio, el motivo por el que existe y la vía por la que llega. OWASP describe tres vías de entrega: código del proveedor pegado en la página, un <script src> que apunta al proveedor y una petición indirecta a través de un tag manager.
El tag manager es la vía menos visible. Puede devolver scripts de varios proveedores, y el personal puede cambiar lo que devuelve desde una interfaz web sin tocar su código. Los cambios entran en producción en la siguiente carga de página y el código suele estar ofuscado.
El código fuente HTML no mostrará esos scripts. Abra las herramientas de desarrollo, vaya a la pestaña Network, recorra el checkout y el login, y anote todos los hosts que sirven un script.
Primero eliminar, después alojar una copia propia
Pregunte al responsable de cada entrada si realmente necesita estar en esa página. Una etiqueta de marketing en una página de login o en un panel de administración rara vez tiene una buena justificación.
Para los scripts que se queden, OWASP recoge como defensa el alojamiento propio. Usted aloja una copia revisada, de modo que un tercero no puede alterarla, y el proveedor deja de recibir la dirección IP, el referrer o las cookies del visitante. El precio es el mantenimiento: una copia alojada por usted no incorpora las correcciones del proveedor, así que alguien debe encargarse de volver a revisarla y actualizarla.
Los proveedores abandonados son un problema aparte. Si el dominio que aloja un script caduca porque el proveedor quebró o abandonó el proyecto, cualquiera puede volver a registrarlo y publicar código malicioso. Un proveedor desaparecido en su inventario es un hallazgo en sí mismo.
Fije con Subresource Integrity lo que conserve
Subresource Integrity (SRI) permite que la página indique el hash con el que debe coincidir un archivo. El navegador compara la descarga con ese hash antes de ejecutar un script o aplicar una hoja de estilos, y devuelve un error de red si no coinciden. La guía de SRI de MDN ofrece el comando para generarlo:
cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A
Anteponga sha384- al resultado e insértelo en el elemento:
<script src="https://cdn.example.com/script.js"
integrity="sha384-..."
crossorigin="anonymous"></script>
El marcado tiene algunos requisitos:
- El atributo
crossorigines obligatorio. El navegador rechaza SRI en peticionesno-cors, por lo que una etiqueta sin él fallará siempre. - El CDN debe enviar la cabecera
Access-Control-Allow-Origin. Muchos envían*. - Puede indicar varios hashes. El navegador usa solo los del algoritmo más fuerte presente (SHA-256, SHA-384, SHA-512 en orden ascendente) y acepta el archivo si coincide cualquiera de ellos, lo que permite admitir dos versiones durante una actualización. La especificación del W3C describe el mismo comportamiento.
SRI es adecuado para archivos que permanecen iguales hasta que usted los cambia. Un script que el proveedor modifica a voluntad fallará la comprobación tras cada modificación, y el contenedor de un tag manager es justo ese tipo de script. Restrinja quién puede publicar en él y manténgalo fuera de sus páginas más sensibles.
Restrinja con Content Security Policy
SRI establece qué debe contener un archivo concreto. Una Content Security Policy (CSP) establece desde dónde pueden proceder los scripts en general. La guía de CSP de MDN indica que debe entregarse en la cabecera Content-Security-Policy en todas las respuestas, no solo en el documento principal.
Un punto de partida para una página sensible enumera los hosts que realmente utiliza:
Content-Security-Policy: script-src 'self' cdn.example.com; object-src 'none'
Una vez que existe una directiva script-src o default-src, el JavaScript en línea queda bloqueado salvo que usted lo habilite. MDN recomienda evitar 'unsafe-inline', porque anula buena parte del propósito de una CSP. Cuando necesite scripts en línea, use un nonce: generado en cada respuesta, impredecible e insertado por una plantilla. Para páginas estáticas, MDN sugiere usar hashes, y en ese caso los scripts externos también necesitan el atributo integrity.
OWASP afirma sin rodeos que una data layer no es un sandbox, porque los contenedores de los tag managers pueden ejecutar JavaScript y HTML personalizados. Restrinja el acceso de publicación y revise los cambios como si fueran código de aplicación.
Encuentre las lagunas sin romper el sitio
La cabecera Integrity-Policy hace que el navegador bloquee los scripts que carecen del atributo integrity o que se cargan en modo no-cors. Empiece por la versión de solo informe:
Integrity-Policy-Report-Only: blocked-destinations=(script), endpoints=(integrity-endpoint)
El endpoint necesita una cabecera Reporting-Endpoints correspondiente. Las infracciones llegan como informes de tipo integrity-violation, con la URL bloqueada. Los scripts ya fijados desaparecen de los informes, por lo que estos no constituyen un inventario completo de scripts.
Cuando dejen de llegar informes, MDN indica que se puede activar el bloqueo sin que los usuarios perciban fallos. Un contenedor de tag manager que no pueda fijar seguirá generando informes, así que las páginas que carguen uno deben permanecer en modo de solo informe. Puede inspeccionar las cabeceras que envían sus páginas con nuestro verificador de cabeceras HTTP.
Por dónde empezar
- Elabore el inventario de las páginas de checkout, login y administración a partir de la pestaña Network, anotando para cada script el responsable, la finalidad y la vía de entrega.
- Elimine las entradas que nadie pueda justificar, sobre todo en las páginas de login y administración, y señale cualquier proveedor cuyo dominio parezca abandonado.
- Aloje copias propias de los archivos que esté dispuesto a mantener y volver a revisar. Fije cada script que conserve: genere hashes SHA-384, añada
integrityycrossorigin="anonymous", y pruebe en preproducción. - Despliegue
Integrity-Policy-Report-Onlypara los scripts y lea los informes. ApliqueIntegrity-Policysolo cuando todos los scripts de la página tengan un atributointegrity, y mantenga en modo de solo informe las páginas con tag manager. - Pruebe en preproducción una
Content-Security-Policyconscript-srcyobject-src 'none', ya que bloquea los scripts en línea. Restrinja quién puede publicar en su tag manager. Para una verificación externa, una prueba de penetración puede cubrir estas páginas.
