2012-08-31 15 views
27

Necesito presentar scripts enviados por el usuario en mi sitio (algo así como jsfiddle). Quiero que los scripts se ejecuten en los navegadores visitantes de forma segura, aislados de la página en la que se publican. Dado que el código es enviado por los usuarios, no hay garantía de que sea confiable.¿Cómo puedo resguardar el contenido JavaScript no confiable del usuario?

En este momento me ocurren tres opciones:

  • servir al contenido enviado por el usuario en un iframe de un dominio diferente, y se basan en la política del mismo origen. Esto requeriría configurar un dominio adicional que me gustaría evitar si es posible. Creo que así es como lo hace jsfiddle. La secuencia de comandos todavía puede hacer algún daño, cambiando top.location.href, por ejemplo, que es menos que ideal. http://jsfiddle.net/PzkUw/
  • Utilice sandbox attribute. Sospecho que esto no está bien soportado en todos los navegadores.
  • Sanitice las secuencias de comandos antes de atenderlas. Preferiría no ir allí.

¿Hay alguna otra solución o recomendación sobre lo anterior?

actualización

Si, como sospecho, la primera opción es la mejor solución, qué puede hacer un script malicioso que no sea cambiar la ubicación de la ventana superior, y cómo puedo evitar esto? Puedo manipular o rechazar ciertos guiones basados ​​en el análisis de código estático, pero esto es hard dada la cantidad de formas en que se puede acceder a los objetos y la dificultad para analizar javascript de forma estática en general. Por lo menos, requeriría un analizador completo y una serie de reglas complejas (algunas, pero sospecho que no todas, de las cuales están presentes en JSLint).

+2

Creo que su idea de subdominio es la mejor. He investigado esta cuestión y no he podido encontrar una mejor solución. Una vez jugué con la carga de los scripts dinámicamente a través de XmlHttpRequest y ejecución de eval - No recuerdo por qué lo dejé caer. –

+0

Relacionados: http://stackoverflow.com/questions/958997/frame-buster-buster-buster-code-needed – Petah

+0

Estoy de acuerdo con @JeremyJStarcher. De todos modos, ¿tienes la oportunidad de controlar ciertos elementos JS, ** ventana ** es el más importante? De ser así, intentaría rechazar ciertas solicitudes hechas desde el iframe, pero no estoy seguro de lo fácil que sería. – inhan

Respuesta

4

Algunas ideas de herramientas que podrían ser útiles en su aplicación: atacan el problema desde dos direcciones diferentes: Caja compila el código JavaScript que no es de confianza con algo seguro mientras AdSafe define un subconjunto de JavaScript que es seguro de usar.

Caja

Caja

El compilador de Caja es una herramienta para editar HTML tercero, CSS y JavaScript seguro para incrustar en su sitio web. Permite una rica interacción entre la página de incrustación y las aplicaciones integradas. Caja utiliza un modelo de seguridad con capacidad de objetos para permitir una amplia gama de políticas de seguridad flexibles, de modo que su sitio web pueda controlar de manera efectiva lo que el código de terceros integrado puede hacer con los datos del usuario.

AdSafe

AdSafe

AdSafe hace que sea seguro para poner el código de invitados (como tercero guión publicidad o widgets) en una página web. ADsafe define un subconjunto de JavaScript que es lo suficientemente potente como para permitir que el código de invitado realice interacciones valiosas, al tiempo que previene el daño o la intrusión malintencionados o accidentales. El subconjunto ADsafe puede verificarse mecánicamente con herramientas como JSLint, de modo que no sea necesaria una inspección humana para revisar el código de invitado por razones de seguridad.El subconjunto ADsafe también impone buenas prácticas de codificación, lo que aumenta la probabilidad de que el código de invitado se ejecute correctamente.

+0

He investigado AdSafe. Está diseñado para guiones que no están en marcos y, por lo tanto, es muy restrictivo. Por ejemplo, no puede hacer 'a [i] = 1'. Creo que las restricciones pueden asustar a la mayoría de los usuarios legítimos. Veremos a Caja. – Flash

+0

Sin embargo, puede hacer 'a [+ i] = 1'.(Esto es porque cuando alguien escribe 'a = ventana; i = 'ev' + 'al'' entonces' a [i] 'significaría' eval' y sería imposible eliminar estáticamente esa posibilidad.) Pero tienes razón que puede ser demasiado restrictivo para sus necesidades. – rsp

26

Cree una interfaz de mensajes bien definida y use JavaScript Web Worker para el código que desea sandbox. HTML5 Web Workers

Web Los trabajadores no tienen acceso a los siguientes objetos DOM.

  • La ventana de objeto

  • El objeto de documento objeto

  • El padre

para que no puedan redirigir su página o alterar los datos en él.

Puede crear una plantilla y una interfaz de mensajería bien definida para que los usuarios puedan crear scripts de trabajador web, pero su secuencia de comandos tendrá la última palabra sobre lo que se manipula.

EDIT Comentario de Jordan Gray conectando una biblioteca JavaScript que parece hacer lo que describí anteriormente. https://github.com/eligrey/jsandbox

+0

Parece una buena alternativa, pero podría ser demasiado restrictiva. Sin embargo +1 por la idea. – Christoph

+1

Buena sugerencia. Mi preocupación es que los navegadores más antiguos no son compatibles con esto. Además, ¿los trabajadores de la web no pueden realizar solicitudes AJAX (lo que significa que todavía necesitaría atender desde un dominio diferente)? – Flash

+0

@Andrew: ¿En qué situación considera que un trabajador web con capacidades AJAX es un problema? Si le preocupa que el script de trabajador se haga pasar por el usuario en su propio dominio, puede usar sesiones sin cookies y evitar ese problema. En cuanto a la compatibilidad del navegador, sí, IE9 y versiones posteriores no son compatibles con HTML5. –

-4

Si desea sandbox alguna pieza de código mediante la eliminación de su acceso a decir la ventana , documento y padres elemento que podría lograrlo envolviéndolo en un cierre cuando éstas son variables vacías locales:

(function(window, document, parent /* Whatever you want to remove */){ 
    console.log(this);  // Empty object 
    console.log(window); // undefined 
    console.log(document); // undefined 
    console.log(parent); // undefined 
}).call({}); 

invocándola con un objeto vacío es importante porque de lo contrario este apuntará a la ventana objeto

+7

'console.log (function() {return this;}());': P – Flash

2

Como se mencionó, el atributo sandbox de iframe ya es compatible con los principales navegadores, pero también sugeriría una solución mixta: iniciar un trabajador web dentro del iframe de espacio aislado. Eso daría un hilo separado y protegería el evento del DOM del sandbox iframe del código que no es de confianza. Así es como funciona mi biblioteca Jailed. Además, puede solucionar cualquier restricción exportando cualquier conjunto de funciones al entorno limitado.

+0

Pregunta sobre su biblioteca, ¿por qué ejecuta el código en un iframe de espacio aislado Y un trabajador web? ¿No sería lo suficientemente seguro tener un iframe normal y luego ejecutar el código que no es de confianza en un trabajador web? El trabajador web no podía acceder al domo del iframe, ni hacer que hiciera otra cosa realmente, a excepción de lo que haces en las devoluciones de llamada de tus mensajes. ¿Estoy en lo correcto? – lastmjs

+2

Bueno, no exactamente. Inicialmente ejecuté el código solo en un trabajador web, luego me explicaron que no es suficiente, ya que un trabajador todavía tiene acceso a algunas instancias de origen local, como almacenamiento local, indexeddb, etc. Así que tuve que poner a un trabajador en una sandboxed iframe. Un trabajador aún era útil para obtener un hilo y evitar el bloqueo de la página con un ciclo infinito. Pero más tarde apareció que muchos navegadores prohíben ejecutar el trabajador en un iframe bajo https, por lo que ahora la biblioteca solo inicia un trabajador si es posible, de lo contrario, el código simplemente se ejecuta en un iframe. – asvd

Cuestiones relacionadas