Las versiones más modernas de los mejores navegadores incluyen una funcionalidad para que los sitios web puedan controlar cómo se carga su código JavaScript y así evitar que sea modificado por usuarios maliciosos.
Esta nueva funcionalidad, llamada "Integridad de Recursos" (en inglés, "SRI" o Subresource Integrity), permite a los sitios web incluir código JavaScript que no se ejecuta si su contenido ha sido modificado.
La gran ventaja que aporta es que puedes usar CDNs (Content Delivery Networks) para servir el contenido de tus sitios lo más rápido posible, pero al mismo tiempo asegurarte que los archivos no han sufrido ninguna modificación.
Usar la "integridad de recursos" es muy sencillo, tal y como muestra el siguiente ejemplo:
<script src="https://code.jquery.com/jquery-2.1.4.min.js"
integrity="sha384-R4/ztc4ZlRqWjqIuvf6RX5yb/v90qNGx6fS48N0tRxiGkqveZETq72KgDVJCp2TC"
crossorigin="anonymous"></script>
La idea consiste en añadir al elemento <script>
una firma digital (en inglés,
cryptographic hash) de sus contenidos. Cuando el navegador cargue la página,
descargará los contenidos, calculará la firma digital y comprobará que su valor
coincida con el del atributo integrity
. Si no coinciden, el código JavaScript
no se ejecuta. Por lo tanto, se trata de una medida de seguridad sencilla pero
eficaz para protegerte frente a CDNs que han sido atacadas y frente a administradores
de sistemas con malas intenciones.
La función utilizada para generar la firma digital debe ser lo suficientemente segura y resistente a las colisiones, de manera que cualquier mínimo cambio en el contenido genere una firma totalmente diferente y única.
Un detalle importante para utilizar esta funcionalidad es que la CDN debe
soportar CORS (Cross-Origin Resource Sharing). Por eso en el ejemplo anterior
se incluye el atributo crossorigin
para forzar la activación de CORS al cargar
los contenidos.
El valor anonymous
del atributo crossorigin
significa que el navegador debe
ignorar cualquier cookie o información de autenticación que el usuario pueda
tener asociado con ese dominio. Además de mejorar el rendimiento (al enviar
menos información en la petición) esto impide que se filtre información entre
diferentes dominios.
Sintaxis del atributo integrity
Como puedes ver en el ejemplo anterior, el atributo integrity
no solo contiene
el valor de la firma digital, sino que también incluye la función utilizada para
generarlo. De hecho, puedes añadir varias firmas digitales que utilicen
diferentes funciones (separa cada firma con una coma):
<script src="https://code.jquery.com/jquery-2.1.4.min.js"
integrity="sha384-R4/ztc4ZlRqWjqIuvf6RX5yb/v90qNGx6fS48N0tRxiGkqveZETq72KgDVJCp2TC
sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw="
crossorigin="anonymous"></script>
El primer uso de las firmas múltiples es que puedes utilizar firmas de diferentes niveles de seguridad (bajo para navegadores antiguos y más alto para los navegadores modernos). También puedes usar las firmas múltiples cuando una misma URL acoge a varios scripts diferentes, como por ejemplo cuando el navegador usa la negociación de contenido.
Recuperándose de los errores
Si el valor del atributo integrity
no coincide con el del contenido descargado
por el navegador, el código JavaScript no se ejecuta. En la práctica, esto
significa que los usuarios se encontrarán en un sitio web en el que no funciona
nada.
La solución a este problema es muy sencilla. En primer lugar, guarda en tu sitio web una copia de los contenidos que estás sirviendo a través de la CDN. Después, utiliza algo de código JavaScript para comprobar si se han cargado los contenidos externos. Si no, carga los archivos desde tu propio servidor.
En el ejemplo anterior se está cargando la librería jQuery. Así que el código que comprueba si se ha cargado puede ser tan sencillo como el siguiente:
<script>window.jQuery || /* cargar aquí nuestros archivos */;</script>
Este código comprueba si se ha definido el objeto jQuery
y en caso contrario,
insertaría una etiqueta para cargar el archivo JavaScript desde el propio
servidor.
Ten en cuenta que muchos scripts se actualizan continuamente, sobre todo los
que no definen un número de versión. En estos casos, es mejor fijar la versión
exacta que se carga desde la CDN y no usar archivos que incluyen versiones
genéricas como latest
.
¿HTTP o HTTPS?
La "integridad de recursos" funciona tanto con HTTP como con HTTPS. Si usas
HTTP, el navegaodr puede comprobar si el valor del atributo integrity
es
correcto, pero no es capaz de defenderde de los ataques que se produzcan sobre
ese acnal de comunicación no seguro. Esto por ejemplo puede hacer que un
atacante elimine el atributo integrity
.
Así que, como siempre, es aconsejable que utilices HTTPS para que al combinarlo
con el atributo integrity
los usuarios disfruten del mayor nivel posible de
confidencialidad y seguridad.
Soporte para hojas de estilos
Todavía se está trabajando para ampliar esta funcionalidad a otros tipos de
recursos diferentes a los archivos JavaScript. No obstante, ya puedes utilizarlo
también para las hojas de estilos CSS. Simplemente añade al atributo integrity
al elemento <link>
de tus páginas.
Prueba hoy mismo la integridad de recursos
Visita el sitio srihash.org para comprobar el soporte de tu navegador y para echar un vistazo a los ejemplos disponibles. En este sitio también puedes generar las firmas digitales y comprobar si tus CDN soportan esta funcionalidad.
También está disponible en varias de las CDNs y sitios más importantes, como BootstrapCDN, CloudFlare y GitHub.
Recursos adicionales
Sobre el autor
Este artículo fue publicado originalmente por Frederik Braun y ha sido traducido con permiso por Javier Eguiluz.