La función eval es una manera poderosa y fácil de generar código dinámicamente, ¿cuáles son las advertencias?
javascript
security
eval
Brian Singh
fuente
fuente
Respuestas:
El uso incorrecto de eval abre su código para ataques de inyección
La depuración puede ser más desafiante (sin números de línea, etc.)
el código evaluado se ejecuta más lentamente (no hay oportunidad de compilar / almacenar en caché el código evaluado)
Editar: como señala @Jeff Walden en los comentarios, el n. ° 3 es menos cierto 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úen repetidamente sin ninguna modificación. Un escenario más probable es que está evaluando scripts que han sufrido ligeras modificaciones cada vez y, como tal, no se pueden almacenar en caché. Digamos que ALGUNOS códigos evaluados se ejecutan más lentamente.
fuente
badHackerGuy'); doMaliciousThings();
y si toma mi nombre de usuario, lo concatena en un script y lo evalúa en los navegadores de otras personas, entonces puedo ejecutar cualquier javascript que quiera en sus máquinas (por ejemplo, forzarlos a hacer +1 en mis publicaciones, publicar sus datos en mi servidor, etc.)debugger;
declaración a su código fuente. Esto detendrá la ejecución de su programa en esa línea. Luego, después de eso, puede agregar puntos de interrupción de depuración como si fuera solo otro archivo JS.eval no siempre es malo. Hay momentos en que es perfectamente apropiado.
Sin embargo, eval es sobreutilizado actualmente e históricamente 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. Cada vez que usa eval necesita verificar con cordura lo que está haciendo, porque es probable que lo esté haciendo 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 'papa':
Si los autores del tipo de código anterior tuvieran una idea sobre los conceptos básicos de cómo funcionan los objetos JavaScript, se habrían dado cuenta de que se pueden usar corchetes en lugar de nombres de puntos literales, lo que evita la necesidad de evaluar:
... que es mucho más fácil de leer y con menos errores.
(Pero entonces, alguien que / realmente / sabía lo que estaba haciendo diría:
que es más confiable que el viejo truco poco fiable de acceder a elementos DOM directamente desde el objeto del documento).
fuente
JSON.parse()
lugar deeval()
JSON?Creo que es porque puede ejecutar cualquier función de JavaScript desde una cadena. Usarlo hace que sea más fácil para las personas inyectar código falso en la aplicación.
fuente
Me vienen a la mente dos puntos:
Seguridad (pero siempre que genere la cadena para evaluarla usted mismo, esto podría no ser un problema)
Rendimiento: hasta que se desconozca el código a ejecutar, no se puede optimizar. (sobre JavaScript y rendimiento, ciertamente la presentación de Steve Yegge )
fuente
eval
evaluado y luego, ese pequeño fragmento de código se ejecuta en el navegador B del usuarioPasar 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 gran recurso.
fuente
En general, solo es un problema si está pasando la entrada del usuario eval.
fuente
Principalmente, es mucho más difícil de mantener y depurar. Es como una
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.fuente
Una cosa a tener en cuenta es que a menudo puede usar eval () para ejecutar código en un entorno de otro modo 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.
Entonces, si está buscando ejecutar algún código JavaScript donde de otra manera no se permitiría ( 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 el control completo: simplemente no es necesario, y es mejor relegarlo al estante de 'trucos de JavaScript difíciles'.
fuente
[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()
A menos que permita que eval () sea un contenido dinámico (a través de cgi o input), es tan seguro y sólido como el resto de JavaScript en su página.
fuente
Junto con el resto de las respuestas, no creo que las declaraciones de evaluación puedan tener una minimización avanzada.
fuente
Es un posible riesgo de seguridad, tiene un alcance de ejecución diferente y es bastante ineficiente, ya que crea un entorno de secuencias de comandos completamente nuevo para la ejecución del código. Vea aquí para más información: eval .
Sin embargo, es bastante útil y se usa con moderación para agregar una gran cantidad de buenas funciones.
fuente
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), entonces es una forma segura de exponer su sistema a un ataque de secuencias de comandos entre sitios.
fuente
Sé que esta discusión es antigua, pero realmente me gusta esto enfoque de Google y quería compartir ese sentimiento con otros;)
La otra cosa es que cuanto mejor obtienes, más tratas de entender y, finalmente, simplemente no crees que algo es bueno o malo solo 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 uses sin pensar :)
fuente
No es necesariamente tan malo siempre que sepa en qué contexto lo está utilizando.
Si su aplicación está usando
eval()
para crear un objeto de algún JSON que ha regresado de un XMLHttpRequest a su propio sitio, creado por su código confiable del lado del servidor, probablemente no sea un problema.El código JavaScript del lado del cliente no confiable no puede hacer tanto de todos modos. Siempre que lo que está ejecutando
eval()
proviene de una fuente razonable, está bien.fuente
Reduce en gran medida su nivel de confianza sobre la seguridad.
fuente
Si desea que el usuario ingrese algunas funciones lógicas y evalúe AND Y, entonces la función de evaluación de JavaScript es perfecta. Puedo aceptar dos cadenas y
eval(uate) string1 === string2
, etc.fuente
Si ve el uso de eval () en su código, recuerde el mantra "eval () is evil".
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 se determina en 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, simplemente usar la notación de corchetes para acceder a las propiedades dinámicas es mejor y más simple:
El uso
eval()
también tiene implicaciones de seguridad, ya que podría estar ejecutando código (por ejemplo, procedente de la red) que ha sido alterado. Este es un antipatrón común cuando se trata con una respuesta JSON de una solicitud de Ajax. En esos casos, es mejor usar los métodos integrados de los navegadores para analizar la respuesta JSON para asegurarse de que sea segura y válida. Para navegadores que no admitenJSON.parse()
forma nativa, puede usar una biblioteca de JSON.org.También es importante recordar que pasar cadenas a
setInterval()
,setTimeout()
y elFunction()
constructor es, en su mayor parte, similar al usoeval()
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:
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 debes usar
eval()
, puede considerar usar una 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 las variables definidas con var en el código que se evalúa no se convertirán en globales automáticamente.
Otra forma de prevenir los globales automáticos es envolver la
eval()
llamada en una función inmediata.fuente
Además de los posibles problemas de seguridad si está ejecutando 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 objeto pueden reemplazar la mayoría de los usos de eval y son mucho más seguras y rápidas.
fuente
Esto puede convertirse en un problema ya que la próxima generación de navegadores sale con un poco de compilador de JavaScript. El código ejecutado a través de Eval puede no funcionar tan bien como el resto de su JavaScript en estos navegadores más nuevos. Alguien debería hacer algunos perfiles.
fuente
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/
fuente
eval () es muy poderoso y puede usarse para ejecutar una declaración JS o evaluar una expresión. Pero la pregunta no se trata de los usos de eval (), sino que 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 se relaciona mucho con la función eval () pero este artículo tiene bastante buena información: 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
fuente
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 la capacidad de analizar esencialmente el código estáticamente a medida que se relaja, y predeterminar dónde están todas las declaraciones de variables y funciones, por lo que se necesita menos esfuerzo para resolver los identificadores durante la ejecución.
Pero si el motor encuentra una evaluación (..) en el código, esencialmente tiene que suponer que toda su conciencia de la ubicación del identificador puede ser inválida, porque no puede saber en el momento exacto qué código puede pasarle a evaluación (..) para modificar el alcance léxico, o el contenido del objeto con el que puede pasar para crear un nuevo alcance léxico para ser consultado.
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
fuente
No siempre es una mala idea. Tomemos, por ejemplo, la generación de código. Recientemente escribí una biblioteca llamada Hyperbars que cierra la brecha entre virtual-dom y el manillar . Lo hace analizando una plantilla de manillar y convirtiéndola en hiperescrito que posteriormente es utilizado por virtual-dom. El hiperescrito se genera primero como una cadena y, antes de devolverlo,
eval()
lo convierte en código ejecutable. Eneval()
esta situación particular he encontrado exactamente lo contrario del mal.Básicamente de
A esto
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 la salida ejecutable muchas veces.Puedes ver cómo se logró la generación del código si tienes curiosidad aquí .
fuente
Me atrevería a decir que realmente no importa si usa
eval()
JavaScript que se ejecuta en navegadores. * (Advertencia)Todos los navegadores modernos tienen una consola de desarrollador donde puedes ejecutar JavaScript arbitrario de todos modos y cualquier desarrollador semi-inteligente puede mirar tu fuente JS y poner lo que necesiten en la consola de desarrollo para hacer lo que deseen.
* Siempre y cuando los puntos finales de su servidor tengan la validación y desinfección correctas de los valores proporcionados por el usuario, no debería importar lo que se analice y evalúe en su javascript del lado del cliente.
eval()
Sin embargo, si tuviera que preguntar si es adecuado para usar en PHP, la respuesta es NO , a menos que incluya en la lista blanca cualquier valor que pueda pasar a su sentencia eval.fuente
No intentaré refutar nada de lo dicho hasta ahora, pero ofreceré este uso de eval () que (hasta donde yo sé) no se puede hacer de otra manera. Probablemente hay otras formas de codificar esto, y probablemente formas de optimizarlo, pero esto se hace a mano y sin ningún tipo de campanas y silbatos por razones de claridad para ilustrar un uso de eval que realmente no tiene otras alternativas. Es decir: nombres de objeto dinámicamente (o más exactamente) creados mediante programación (en oposición a los valores).
EDITAR: por cierto, no sugeriría (por todas las razones de seguridad señaladas hasta ahora) que base sus nombres de objetos en la entrada del usuario. Sin embargo, no puedo imaginar ninguna buena razón por la que quieras hacer eso. Aún así, pensé en señalar que no sería una buena idea :)
fuente
namespaceToTest[namespaceParts[i]]
, sin necesidad de eval aquí, por lo que laif(typeof namespaceToTest[namespaceParts[i]] === 'undefined') { namespaceToTest[namespaceParts[i]] = {};
única diferencia para elelse namespaceToTest = namespaceToTest[namespaceParts[i]];
Recolección de basura
La recolección de basura de los navegadores no tiene idea de si el código evaluado puede eliminarse de la memoria, por lo que simplemente lo mantiene almacenado hasta que se vuelve a cargar la página. No está mal si sus usuarios solo están en su página en breve, pero puede ser un problema para las aplicaciones web.
Aquí hay un script para demostrar el problema
https://jsfiddle.net/CynderRnAsh/qux1osnw/
Algo tan simple como el código anterior hace que se almacene una pequeña cantidad de memoria hasta que la aplicación muera. Esto es peor cuando el script evadido es una función gigante, y se llama a intervalos.
fuente