javascript security eval

¿Por qué es una mala idea usar la función de evaluación de JavaScript?



security (25)

  1. El uso inadecuado de eval abre su código para ataques de inyección

  2. La depuración puede ser más desafiante (sin números de línea, etc.)

  3. el código eval se ejecuta más lentamente (no hay oportunidad de compilar / almacenar el código evaluado)

Edit: Como @Jeff Walden señala en los comentarios, el # 3 es menos verdadero hoy que en 2008. Sin embargo, aunque puede ocurrir un almacenamiento en caché de los scripts compilados, esto solo se limitará a los scripts que se evalúan repetidamente sin modificaciones. Un escenario más probable es que está evaluando scripts que han sufrido una ligera modificación cada vez y, como tal, no se pueden almacenar en caché. Digamos que ALGUNO código evaluado se ejecuta más lentamente.

La función eval es una forma potente y fácil de generar código dinámicamente, ¿cuáles son las advertencias?


A menos que esté 100% seguro de que el código que se está evaluando proviene de una fuente confiable (generalmente su propia aplicación), es una forma segura de exponer su sistema a un ataque de scripts entre sitios.


A menos que permita que eval () un contenido dinámico (a través de cgi o input), es tan seguro y sólido como cualquier otro JavaScript en su página.


Además de los posibles problemas de seguridad si está ejecutando un código enviado por el usuario, la mayoría de las veces hay una mejor manera que no implica volver a analizar el código cada vez que se ejecuta. Las funciones anónimas o las propiedades de los objetos pueden reemplazar la mayoría de los usos de eval y son mucho más seguros y rápidos.


Creo que es porque puede ejecutar cualquier función de JavaScript desde una cadena. Su uso hace que sea más fácil para las personas inyectar código malicioso en la aplicación.


Dos puntos vienen a la mente:

  1. Seguridad (pero siempre que genere la cadena que se evaluará usted mismo, esto podría ser un problema)

  2. Rendimiento: hasta que se desconoce el código que se ejecutará, no se puede optimizar. (Sobre javascript y rendimiento, ciertamente la presentación de Steve Yegge )


El motor de JavaScript tiene una serie de optimizaciones de rendimiento que realiza durante la fase de compilación. Algunos de estos se reducen a ser capaces de analizar estáticamente el código a medida que se desliza, y predeterminar dónde están todas las declaraciones de variables y funciones, por lo que se requiere menos esfuerzo para resolver los identificadores durante la ejecución.

Pero si el Motor encuentra una eval (..) en el código, esencialmente debe asumir que todo su conocimiento de la ubicación del identificador puede no ser válido, ya que no puede saber exactamente qué código puede pasar a eval (...) para modificar el alcance léxico, o el contenido del objeto al que puede pasar para crear un nuevo alcance léxico para consultar.

En otras palabras, en el sentido pesimista, la mayoría de esas optimizaciones que haría no tienen sentido si eval (..) está presente, por lo que simplemente no realiza las optimizaciones en absoluto.

Esto lo explica todo.

Referencia:

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance


Es un posible riesgo de seguridad, tiene un alcance de ejecución diferente y es bastante ineficiente, ya que crea un entorno de scripting completamente nuevo para la ejecución del código. Vea aquí para más información: eval .

Sin embargo, es bastante útil y, si se utiliza con moderación, puede agregar una gran funcionalidad.


Este es uno de los buenos artículos que hablan sobre eval y cómo no es un mal: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

No estoy diciendo que debas salir corriendo y comenzar a usar eval () en todas partes. De hecho, hay muy pocos buenos casos de uso para ejecutar eval (). Definitivamente hay preocupaciones con la claridad del código, la depuración y, ciertamente, el rendimiento que no se debe pasar por alto. Pero no debe tener miedo de usarlo cuando tenga un caso en el que eval () tenga sentido. Trate de no usarlo primero, pero no permita que nadie lo haga pensar que su código es más frágil o menos seguro cuando eval () se usa apropiadamente.


Esto puede convertirse en un problema mayor a medida que la próxima generación de navegadores ofrezca cierto sabor de compilador de JavaScript. Es posible que el código ejecutado a través de Eval no funcione tan bien como el resto de su JavaScript contra estos navegadores más nuevos. Alguien debería hacer algún perfil.


Junto con el resto de las respuestas, no creo que las declaraciones eval puedan tener una minimización avanzada.


Me atrevería a decir que en realidad no importa si usa eval() en javascript que se ejecuta en los navegadores. * (Advertencia)

Todos los navegadores modernos tienen una consola de desarrollador donde puede ejecutar javascript arbitrario de todos modos y cualquier desarrollador semi inteligente puede ver su fuente de JS y poner cualquier parte de ella que necesite en la consola dev para hacer lo que desee.

* Mientras los puntos finales de su servidor tengan la correcta validación y desinfección de los valores proporcionados por el usuario, no importa lo que se analice y evalúe en el javascript del lado del cliente.

Sin embargo, si preguntara si es adecuado usar eval() en PHP, la respuesta es NO , a menos que incluya en la lista blanca cualquier valor que pueda pasar a su declaración eval.


No es necesariamente tan malo siempre que sepas en qué contexto lo estás utilizando.

Si su aplicación está utilizando eval() para crear un objeto de algún JSON que haya regresado de un XMLHttpRequest a su propio sitio, creado por su código de servidor de confianza, probablemente no sea un problema.

El código de JavaScript del lado del cliente que no es de confianza no puede hacer mucho de todos modos. Siempre que lo que está ejecutando eval() proviene de una fuente razonable, está bien.


No intentaré refutar nada de lo dicho anteriormente, pero ofreceré este uso de eval () que (por lo que sé) no se puede hacer de otra manera. Probablemente haya otras formas de codificar esto, y probablemente formas de optimizarlo, pero esto se hace a largo plazo y sin ningún tipo de timbres y de claridad para ilustrar un uso de eval que realmente no tiene otras alternativas. Es decir: nombres de objetos dinámicos (o más precisos) creados por programación (en lugar de valores).

//Place this in a common/global JS lib: var NS = function(namespace){ var namespaceParts = String(namespace).split("."); var namespaceToTest = ""; for(var i = 0; i < namespaceParts.length; i++){ if(i === 0){ namespaceToTest = namespaceParts[i]; } else{ namespaceToTest = namespaceToTest + "." + namespaceParts[i]; } if(eval(''typeof '' + namespaceToTest) === "undefined"){ eval(namespaceToTest + '' = {}''); } } return eval(namespace); } //Then, use this in your class definition libs: NS(''Root.Namespace'').Class = function(settings){ //Class constructor code here } //some generic method: Root.Namespace.Class.prototype.Method = function(args){ //Code goes here //this.MyOtherMethod("foo")); // => "foo" return true; } //Then, in your applications, use this to instantiate an instance of your class: var anInstanceOfClass = new Root.Namespace.Class(settings);

EDITAR: por cierto, no sugeriría (por todos los motivos de seguridad señalados hasta ahora) que basa sus nombres de objeto en la entrada del usuario. No puedo imaginar ninguna buena razón por la que quieras hacer eso. Aun así, pensé en señalar que no sería una buena idea :)


No siempre es una mala idea. Tomemos, por ejemplo, la generación de código. Hace poco escribí una biblioteca llamada Hyperbars que cierra la brecha entre virtual-dom y el handlebars . Para ello, analiza una plantilla de manillares y la convierte en hyperscript que posteriormente utiliza virtual-dom. El hyperscript se genera primero como una cadena y antes de devolverlo, eval() para convertirlo en código ejecutable. He encontrado que eval() en esta situación particular es exactamente lo opuesto al mal.

Básicamente desde

<div> {{#each names}} <span>{{this}}</span> {{/each}} </div>

A esto

(function (state) { var Runtime = Hyperbars.Runtime; var context = state; return h(''div'', {}, [Runtime.each(context[''names''], context, function (context, parent, options) { return [h(''span'', {}, [options[''@index''], context])] })]) }.bind({}))

El rendimiento de eval() no es un problema en una situación como esta porque solo necesita interpretar la cadena generada una vez y luego reutilizar el resultado ejecutable varias veces.

Puedes ver cómo se logró la generación de código si tienes curiosidad here .


Pasar la entrada del usuario a eval () es un riesgo de seguridad, pero también cada invocación de eval () crea una nueva instancia del intérprete de JavaScript. Esto puede ser un recurso de cerdo.


Por lo general, solo es un problema si está pasando la entrada del usuario de eval.


Principalmente, es mucho más difícil de mantener y depurar. Es como un goto . Puede usarlo, pero hace que sea más difícil encontrar problemas y más difícil para las personas que pueden necesitar hacer cambios más adelante.


Reduce en gran medida su nivel de confianza sobre la seguridad.


Sé que esta discusión es antigua, pero realmente me gusta this enfoque de Google y quería compartir ese sentimiento con los demás;)

La otra cosa es que cuanto mejor consigas, más intentas entender y, finalmente, simplemente no crees que algo sea bueno o malo simplemente porque alguien lo dijo :) Este es un video muy inspirador que me ayudó a pensar más por mí mismo. :) LAS BUENAS PRÁCTICAS son buenas, pero no las use sin pensar :)


Si desea que el usuario ingrese algunas funciones lógicas y evalúe para AND el OR, la función de evaluación de JavaScript es perfecta. Puedo aceptar dos cadenas y eval(uate) string1 === string2 , etc.


Si ve el uso de eval () en su código, recuerde el mantra "eval () es malo".

Esta función toma una cadena arbitraria y la ejecuta como código JavaScript. Cuando el código en cuestión se conoce de antemano (no determinado en el tiempo de ejecución), no hay razón para usar eval (). Si el código se genera dinámicamente en tiempo de ejecución, a menudo hay una mejor manera de lograr el objetivo sin eval (). Por ejemplo, solo usar la notación de corchetes para acceder a las propiedades dinámicas es mejor y más simple:

// antipattern var property = "name"; alert(eval("obj." + property)); // preferred var property = "name"; alert(obj[property]);

El uso de eval() también tiene implicaciones de seguridad, ya que puede estar ejecutando código (por ejemplo, proveniente de la red) que ha sido manipulado. Este es un antipattern común cuando se trata de una respuesta JSON de una solicitud Ajax. En esos casos, es mejor usar los métodos incorporados de los navegadores para analizar la respuesta JSON para asegurarse de que sea segura y válida. Para los navegadores que no admiten JSON.parse() forma nativa, puede usar una biblioteca de JSON.org.

También es importante recordar que pasar cadenas a setInterval() , setTimeout() y el constructor Function() es, en su mayor parte, similar al uso de eval() y, por lo tanto, debe evitarse.

Detrás de escena, JavaScript todavía tiene que evaluar y ejecutar la cadena que pasa como código de programación:

// antipatterns setTimeout("myFunc()", 1000); setTimeout("myFunc(1, 2, 3)", 1000); // preferred setTimeout(myFunc, 1000); setTimeout(function () { myFunc(1, 2, 3); }, 1000);

El uso del nuevo constructor Function () es similar a eval () y debe abordarse con cuidado. Podría ser una construcción poderosa pero a menudo se usa mal. Si absolutamente debe usar eval() , puede considerar usar nueva Función () en su lugar.

Hay un pequeño beneficio potencial porque el código evaluado en la nueva función () se ejecutará en un ámbito de función local, por lo que cualquier variable definida con var en el código que se está evaluando no se convertirá en globales de forma automática.

Otra forma de evitar los globales automáticos es envolver la llamada eval() en una función inmediata.


Una cosa a tener en cuenta es que a menudo se puede usar eval () para ejecutar código en un entorno restringido (los sitios de redes sociales que bloquean funciones específicas de JavaScript a veces se pueden engañar al dividirlos en un bloque eval)

eval(''al'' + ''er'' + ''t(/''' + ''hi there!'' + ''/')'');

Por lo tanto, si está buscando ejecutar algún código JavaScript en el que no se pueda permitir ( Myspace , lo estoy mirando ...) entonces eval () puede ser un truco útil.

Sin embargo, por todas las razones mencionadas anteriormente, no debe usarlo para su propio código, donde tiene un control completo; simplemente no es necesario, y está más relegado a la plataforma de los "trucos de JavaScript difíciles".


eval () es muy poderoso y puede usarse para ejecutar una declaración JS o evaluar una expresión. Pero la pregunta no es acerca de los usos de eval (), pero digamos de alguna manera cómo la cadena que ejecuta con eval () se ve afectada por una parte maliciosa. Al final estarás ejecutando código malicioso. Con el poder viene una gran responsabilidad. Así que úsalo sabiamente si lo estás usando. Esto no está muy relacionado con la función eval (), pero este artículo tiene información bastante buena: http://blogs.popart.com/2009/07/javascript-injection-attacks/ Si está buscando los conceptos básicos de eval () mira aquí: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval


eval no siempre es malvado Hay momentos en que es perfectamente apropiado.

Sin embargo, eval es actualmente e históricamente masivamente utilizado por personas que no saben lo que están haciendo. Eso incluye a personas que escriben tutoriales de JavaScript, desafortunadamente, y en algunos casos esto puede tener consecuencias de seguridad o, más a menudo, errores simples. Entonces, cuanto más podamos hacer para lanzar un signo de interrogación sobre eval, mejor. En cualquier momento que use eval, debe comprobar la cordura lo que está haciendo, porque es probable que pueda hacerlo de una manera mejor, más segura y más limpia.

Para dar un ejemplo demasiado típico, para establecer el color de un elemento con una identificación almacenada en la variable ''potato'':

eval(''document.'' + potato + ''.style.color = "red"'');

Si los autores del tipo de código anterior tuvieran una pista sobre los conceptos básicos de cómo funcionan los objetos de JavaScript, se habrían dado cuenta de que se pueden usar corchetes en lugar de nombres de puntos literales, obviando la necesidad de evaluar:

document[potato].style.color = ''red'';

... que es mucho más fácil de leer y menos potencialmente buggy.

(Pero entonces, alguien que / realmente / sabía lo que estaban haciendo diría:

document.getElementById(potato).style.color = ''red'';

que es más confiable que el truco viejo y falso de acceder a elementos DOM directamente desde el objeto del documento.)