Me pregunto si es posible crear un sandbox de JavaScript en el navegador para evitar el acceso a funciones que normalmente están disponibles para el código JavaScript que se ejecuta en una página HTML.
Por ejemplo, supongamos que quiero proporcionar una API de JavaScript para que los usuarios finales les permitan definir manejadores de eventos que se ejecutarán cuando ocurran "eventos interesantes", pero no quiero que esos usuarios accedan a las propiedades y funciones del window
objeto. ¿Soy capaz de hacer esto?
En el caso más simple, digamos que quiero evitar que los usuarios llamen alert
. Un par de enfoques que puedo pensar son:
- Redefinir
window.alert
globalmente. No creo que este sea un enfoque válido porque podría querer usar otro código que se ejecute en la página (es decir, material no creado por los usuarios en sus controladores de eventos)alert
. - Envíe el código del controlador de eventos al servidor para procesar. No estoy seguro de que enviar el código al servidor para procesar sea el enfoque correcto porque los controladores de eventos deben ejecutarse en el contexto de la página.
¿Quizás una solución en la que el servidor procese la función definida por el usuario y luego genere una devolución de llamada que se ejecutará en el cliente funcionaría? Incluso si ese enfoque funciona, ¿hay mejores maneras de resolver este problema?
fuente
while (1) {}
--- simplemente se cuelga. Del mismo modoa=[]; while (1) { a=[a,a]; }
.Echa un vistazo a ADsafe de Douglas Crockford :
Puede ver un ejemplo de cómo usar ADsafe mirando los archivos
template.html
ytemplate.js
en el repositorio GitHub del proyecto .fuente
this
, lo cual es completamente inaceptable. No puedes escribir un buen JavaScript sin usarlothis
.this
. No es difícil evitar el parámetro mal nombrado.this
, hay una no-this
manera igual y equivalente de hacerlo (es solo un parámetro, después de todo).Creé una biblioteca de sandboxing llamada jsandbox que usa trabajadores web para sandbox el código evaluado. También tiene un método de entrada para proporcionar explícitamente datos de código de espacio aislado que de otro modo no podría obtener.
El siguiente es un ejemplo de la API:
fuente
Creo que vale la pena mencionar js.js aquí. Es un intérprete de JavaScript escrito en JavaScript.
Es aproximadamente 200 veces más lento que el JS nativo, pero su naturaleza lo convierte en un entorno sandbox perfecto. Otro inconveniente es su tamaño: casi 600 kb, que puede ser aceptable para computadoras de escritorio en algunos casos, pero no para dispositivos móviles.
fuente
Como se mencionó en otras respuestas, es suficiente encarcelar el código en iframe de espacio aislado (sin enviarlo al lado del servidor) y comunicarse con mensajes. Sugeriría echar un vistazo a una pequeña biblioteca que creé principalmente debido a la necesidad de proporcionar alguna API al código no confiable, tal como se describe en la pregunta: existe la oportunidad de exportar el conjunto particular de funciones directamente al sandbox donde se ejecuta el código no confiable. Y también hay una demostración que ejecuta el código enviado por un usuario en un sandbox:
http://asvd.github.io/jailed/demos/web/console/
fuente
Todos los proveedores de navegadores y la especificación HTML5 están trabajando hacia una propiedad de espacio aislado real para permitir iframes de espacio aislado, pero aún se limita a la granularidad de iframe.
En general, ningún grado de expresiones regulares, etc. puede desinfectar de forma segura JavaScript arbitrario proporcionado por el usuario, ya que degenera en el problema de detención: - /
fuente
Una versión mejorada del código sandbox de los trabajadores web de @ RyanOHara, en un solo archivo (no
eval.js
se necesita ningún archivo adicional ).Pruébalo:
https://jsfiddle.net/kp0cq6yw/
Debería salir
6
(probado en Chrome y Firefox).fuente
De una manera fea, pero tal vez esto funcione para usted, tomé todos los globales y los redefiní en el ámbito de la caja de arena, y también agregué el modo estricto para que no puedan obtener el objeto global utilizando una función anónima.
https://gist.github.com/alejandrolechuga/9381781
fuente
window
volver de eso.sandboxcode('console.log((0,eval)("this"))')
function sbx(s,p) {e = eval; eval = function(t){console.log("GOT GOOD")}; sandboxcode(s,p); eval =e}
(_=>_).constructor('return this')()
Es más probable que un intérprete de Javascript independiente produzca una caja de arena robusta que una versión enjaulada de la implementación del navegador incorporado. Ryan ya ha mencionado js.js , pero un proyecto más actualizado es JS-Interpreter . Los documentos cubren cómo exponer varias funciones al intérprete, pero su alcance es muy limitado.
fuente
A partir de 2019, vm2 parece la solución más popular y más actualizada regularmente para este problema.
fuente
Con NISP podrás hacer una evaluación de espacio aislado. Aunque la expresión que escribe no es exactamente un JS, en su lugar, escribirá expresiones-s. Ideal para DSL simples que no requieren una programación extensa.
fuente
1) Suponga que tiene un código para ejecutar:
Ahora, suponga que desea ejecutarlo en un sandbox:
Estas dos líneas cuando se ejecuten fallarán, porque la función "alerta" no está disponible desde el "entorno limitado"
2) Y ahora desea exponer un miembro de un objeto de ventana con su funcionalidad:
De hecho, puede agregar citas de escape y hacer otro pulido, pero supongo que la idea es clara.
fuente
¿De dónde viene este usuario JavaScript?
No hay mucho que pueda hacer para que un usuario incruste código en su página y luego lo llame desde su navegador (consulte Greasemonkey, http://www.greasespot.net/ ). Es solo algo que hacen los navegadores.
Sin embargo, si almacena el script en una base de datos, luego lo recupera y lo evalúa (), entonces puede limpiar el script antes de ejecutarlo.
Ejemplos de código que elimina todas las ventanas. y documento. referencias:
Esto intenta evitar que se ejecute lo siguiente (no probado):
Hay muchas limitaciones que deberías aplicar al script de usuario inseguro. Desafortunadamente, no hay un 'contenedor de espacio aislado' disponible para JavaScript.
fuente
He estado trabajando en un sandbox js simplista para permitir a los usuarios crear applets para mi sitio. Aunque todavía enfrento algunos desafíos al permitir el acceso DOM (parentNode simplemente no me permite mantener las cosas seguras = /), mi enfoque fue simplemente redefinir el objeto de ventana con algunos de sus miembros útiles / inofensivos, y luego evaluar () al usuario código con esta ventana redefinida como el alcance predeterminado.
Mi código "central" es así ... (no lo estoy mostrando por completo;)
Por lo tanto, puedo instanciar un Sandbox y usar execute () para ejecutar el código. Además, todas las nuevas variables declaradas dentro del código evaluado finalmente se vincularán con el alcance execute (), por lo que no habrá conflictos de nombres ni alteraciones con el código existente.
Aunque los objetos globales seguirán siendo accesibles, aquellos que deben permanecer desconocidos para el código de espacio aislado deben definirse como proxies en el objeto Sandbox :: scope.
Espero que esto funcione para usted.
fuente
Puede ajustar el código del usuario en una función que redefine los objetos prohibidos como parámetros; estos serían
undefined
cuando se llama:Por supuesto, los atacantes inteligentes pueden evitar esto inspeccionando el DOM de Javascript y encontrando un objeto no anulado que contenga una referencia a la ventana.
Otra idea es escanear el código del usuario utilizando una herramienta como jslint . Asegúrese de que esté configurado para que no tenga variables preestablecidas (o: solo las variables que desee), y luego, si se configuran o acceden algunos globales, no permita que se use el script del usuario. Una vez más, podría ser vulnerable a recorrer el DOM: los objetos que el usuario puede construir utilizando literales pueden tener referencias implícitas al objeto de ventana al que se puede acceder para escapar del entorno limitado.
fuente