> Manuales > Taller de HTML5

Cómo proteger tu sitio web con el “Sandbox” de HTML5.

Las aplicaciones actuales combinan toda una serie de experiencias nueva dentro de otra experiencia. Pensemos en los widgets de Twitter que muestran los últimos mensajes sobre un producto. O los comentarios de Facebook sobre un artículo. O incluso la integración de páginas web mediante el empleo de un elemento IFRAME. Estas experiencias pueden provocar agujeros de seguridad en tu sitio Web.

Pero no te alarmes… tenemos un nuevo personaje que nos ayudará, el “Sandbox” de HTML5. Pero antes de entrar a verlo, vamos a echar un vistazo rápido sobre los problemas que plantea el elemento IFRAME.

Una caja negra

Embeber contenidos dentro de n IFRAME es como anunciar una fiesta públicamente en Facebook. Tú crees que sabes a quién has invitado, pero realmente no tienes ni idea de quién le ha metido dentro ni con quién viene.

Lo mismo se aplica a los contenidos dentro de un iframe. Sabemos lo que estamos referenciando, pero no tenemos ninguna pista sobre la forma en que podrá evolucionar ese sitio en el futuro. El contenido o su funcionalidad (o ambas cosas) pueden variar en cualquier momento. Sin que lo sepas… y sin que nadie tenga en cuenta tu opinión.

Los problemas de seguridad al utilizar iframe

Los navegadores utilizan páginas que incluyen IFRAME igual que si fueran una página cualquiera. Se pueden utilizar formularios para que los usuarios escriban datos, se pueden ejecutar scripts, se puede navegar por la página dentro de la ventana del navegador y los plugins de l navegador se pueden ejecutar también. Y al igual que ocurre con los que se salen de madre y revientan las fiestas, apenas podemos controlar lo que puede hacer este contenido.

Existe un mecanismo por defecto que evita algunos tipos de ataques: la política denominada “cross-domain”.

Realojamiento de contenidos procedentes de otros dominios

Si el contenido mostrado procede de otro dominio, se ponen en marcha las políticas de dominios cruzados y se prohíbe al contenido “forastero” el acceso al modelo de objetos del documento.

Así, la página incrustada no puede leer, por ejemplo, cookies ni otras modalidades de almacenamiento local del navegador en el dominio que sirve de entorno. Pero siguen existiendo algunos riesgos.

El contenido alojado puede todavía re-navegar hacia el nivel superior. Mediante la técnica de mostrar contenidos que el cliente supone que son válidos, el sitio puede intentar capturar de forma fraudulenta información privada del usuario. O, mediante el uso de un formulario con un aspecto parecido, intentar que el usuario introduzca a mano información personal sin que se dé cuenta.

Es por eso que, aunque tengamos activa una política de cross-domain, siguen latentes ciertos riesgos.

Realojamiento de contenidos del mismo dominio

El caso de realojamiento de contenidos procedentes del mismo dominio es incluso más grave.

Cuando el contenido procede del mismo dominio, no se aplican las medidas de seguridad por defecto. Los contenidos presentados pueden acceder a todo el DOM cargado en el navegador y manipular cualquier cosa.

Parece de sentido común que el contenido del mismo dominio debería ser seguro. El riesgo aquí estriba sobre todo en contenidos generados por el usuario que se reubiquen dentro de un IFRAME.

La estrategia del aislamiento en “caja de arena” (sandboxing)

Todas estas prevenciones sobre la seguridad no habían sido abordadas con la profundidad por los organismos de estandarización hasta ahora. A falta de un estándar claro del W3C, lo fundamental era conseguir proteger de alguna forma al host frente al contenido alojado en un iframe interno. Por ejemplo, Microsoft ofrecía una implementación propietaria de seguridad para IFRAME en Internet Explorer 8. Otros han abordado también esta cuestión y la han tenido en cuenta como elemento básico para el diseño de sus navegadores. Pero los estándares han avanzado mucho desde IE8.

Los navegadores actuales, como Chrome, Firefox y la Platform Preview de IE10 se basan ya en el Atributo Sandbox del Iframe definido por el W3C.

Esto es lo que podemos hacer a día de hoy con Sandbox. Puedes ver la demo aquí.

Empecemos por aplicar la “caja de arena”. Simplemente añadimos un atributo vacío al elemento IFRAME:

<iframe sandbox src="http://somewebsite.com/default.html"></iframe>

¡Y ya está!

Ahora el contenido aislado del IFRAME queda realojado dentro del navegador aplicándosele las siguientes restricciones:

Esto quiere decir que aunque el contenido proceda del mismo dominio, se trata bajo las políticas de dominio cruzado, de manera que todos los contenidos de IFRAME se verán como procedentes de un origen único y diferente al del dominio de la página contenedora.

Lo único que se permite al contenido embebido es mostrar información. No se admite ningún otro tipo de actividad dentro del IFRAME que pudiera suponer un riesgo para el sitio web que lo aloja o defraudar de alguna manera la confianza del usuario.

Comprobación del atributo sandbox

Sabemos que un IFRAME es una puerta abierta al exterior. Sabemos que el atributo sandbox bloquea el contenido alojado aplicando restricciones de seguridad. Está claro: debes utilizar los elementos IFRAME con el atributo sandbox!

Puedes confirmar que tu navegador soporta el atributo sandbox para los Iframes simplemente con un pequeño código de comprobación hecho en JavaScript:

if( "sandbox" in document.createElement( "IFRAME" ) ) {
// render the iframe element...
} else {
// embed content through other ways,
// as the browser does not support the sandbox
}

Si está soportado, utiliza el atributo sandbox. Si no, trata de integrar el contenido de otras formas o recomienda al usuario, con algún tipo de aviso, que actualice a un navegador más moderno.

Personalización del sandbox

En algunas ocasiones vamos a necesitar modificar en parte las restricciones de seguridad, y podemos hacerlo. Para ello podemos emplear algunos valores del atributo que relajan las políticas estándar aplicables al sandbox:

allow-forms
Si quieres que los formularios dentro de un elemento Iframe puedan enviar datos, simplemente indica el valor allow-forms en el atributo sandbox:

<iframe sandbox="allow-forms" src="xyz.html"></iframe>

Si está presente este valor, la página embebida tiene permiso para submitir datos dentro del iframe.

allow-scripts
JavaScript es un lenguaje muy potente y con frecuencia se utiliza para generar interacciones dinámicas en el lado del cliente sin tener que renviar información al servidor. Pero esta potencia también conlleva riesgos, cuando hablamos de alojar páginas ajenas a nuestro sitio web. Así pues, piénsatelo mucho antes de activar JavaScript dentro IFRAME, sobre todo cuando el contenido procede de fuentes desconocidas.

Para habilitar el JavaScript indicamos el valor allow-scripts:

<iframe sandbox="allow-scripts" src="xyz.html"></iframe>

allow-same-origin
Por defecto, una página en un IFRAME que corresponde al mismo dominio, tiene la capacidad de acceder al modelo de objeto de documento de la página padre. SI hemos añadido el atributo sandbox, la página será tratada como si no procediera del mismo dominio, es decir, no tendrá acceso a los recursos, aun viniendo del mismo dominio.

Para recuperar el trato como página del mismo dominio en un entorno de aislamiento, tenemos que indicar el valor allow-same-origin al atributo sandbox:

<iframe sandbox="allow-same-origin" src="xyz.html"></iframe>

Por sí solo, este valor no es muy útil, ya que necesitaremos añadirle algo de scripting para poder aprovecharlo.

Por ejemplo, si lo que queremos es acceder un elemento del almacén local del dominio actual, más o menos así:

function loadFromStorage( key ) {
   if( localStorage ) {
      return localStorage.getItem( key );
   }
});

…también necesitaremos añadirle al atributo sandbox el valor allow-scripts:

<iframe sandbox="allow-scripts allow-same-origin" src="xyz.html"></iframe>

¡Y ahora funciona!

¡Pero cuidado!: permitir que se ejecuten múltiples scripts dentro del mismo sandbox puede ocasionar nuevas vulnerabilidades en nuestras páginas. Por ejemplo, nuestro contenido embebido puede manipular los atributos sandbox del Iframe padre y eliminar cualquier otra restricción.

allow-top-navigation
Al utilizar el atributo sandbox, los enlaces que apuntan a otros contextos de navegación se ignoran y no se ejecutan por defecto. Así se protege al sitio web que aloja el contenido IFRAME frente a la posibilidad de ser sustituido por el contenido de dicho Iframe..

Por ejemplo, este enlace no se ejecutaría por defecto en un sandbox, ya que el destino del enlace sustituiría a toda la página web:

<a href="xyz.html" target="_top">Click me</a>

Solo se recomienda relajar esta restricción si confiamos plenamente en el contenido alojado.

<iframe sandbox="allow-top-navigation" src="xyz.html"></iframe>

ms-allow-popups
A veces interesa que el contenido embebido pueda abrir nuevas ventanas emergentes. Un ejemplo concreto es el servicio de mapas de Bing Maps.

Al integrar Bing Maps en nuestras páginas, ciertas fucnionaliades como el cálculo de rutas o la información de destino se pueden ver en ventanas emergentes. Pero dado que sandbox lo prohíbe, en Internet Explorer 10 contamos con un parámetro que permite los popups sin afectar al resto de medidas de seguridad.

El código siguiente muestra cómo se utiliza el valor ms-allow-popups.

<iframe sandbox="ms-allow-popups" src="xyz.html"></iframe>

Al indicar este valor, los sitios integrados pueden mostrar su información en ventanas emergentes.

<a href="xyz.html" target="_new">Show Info</a>

Combinación de directivas

Podemos combinar más de un valor en mismo atributo sandbox. Por ejemplo, si queremos enviar datos desde un formulario, navegar en el nivel superior y activar JavaScript, podemos indicarlo así:

<iframe sandbox="allow-forms allow-top-navigation allow-scripts" src="xyz.html"></iframe>

Conviene también saber que el sandbox funciona correctamente bajo esquemas de jerarquía, utilizando algunos Iframes anidados con distintos valores de atributo sandbox. El sandbox de mayor nivel siempre domina sobre el resto de la jerarquía.

Manos a la obra!

Te recomiendo que pruebes con el sandbox de HTML5 en esta demo. Y también puedes descargarte una copia de la misma demo desde Github. Si quieres activar la demo de envío de datos desde formulario, abre la carpeta de proyecto en WebMatrix y empieza desde ahí a modificar los valores.

Lo siguiente será que te descargues un navegador moderno (por ejemplo Internet Explorer 10 Platform Preview) y practicar con el sandbox siguiendo las explicaciones de la Guía de Desarrollo de IE. Este atributo tan sencillo es un gran paso adelante hacia una web más segura, y los navegadores modernos por fin están preparados para aislar adecuadamente los contenidos embebidos.

Dariusz Parys

Desarrollador evangelista en Microsoft Alemania

Manual