¿Por qué las características de evaluación se consideran malvadas, en contraste con otras características posiblemente dañinas?

51

La mayoría de los lenguajes modernos (que de alguna manera se interpretan) tienen algún tipo de función eval . Dicha función ejecuta un código de lenguaje arbitrario, la mayoría de las veces pasa como argumento principal como una cadena (diferentes idiomas pueden agregar más características a la función eval).

Entiendo que a los usuarios no se les debe permitir ejecutar esta función ( editar, es decir, tomar información arbitraria directa o indirectamente de un usuario arbitrario al que se pasará eval), especialmente con el software del lado del servidor, ya que podrían obligar al proceso a ejecutar código malicioso. De esa manera, los tutoriales y las comunidades nos dicen que no usemos eval. Sin embargo, hay muchas veces en que eval es útil y utilizado:

  • Reglas de acceso personalizadas a elementos de software (IIRC OpenERP tiene un objeto ir.ruleque puede usar código dinámico de Python).
  • Cálculos y / o criterios personalizados (OpenERP tiene campos como ese para permitir cálculos de códigos personalizados).
  • Analizadores de informes de OpenERP (sí, sé que te estoy volviendo loco con las cosas de OpenERP ... pero es el principal ejemplo que tengo).
  • Codificación de efectos de hechizo en algunos juegos de rol.

Por lo tanto, tienen un buen uso, siempre que se usen correctamente. La principal ventaja es que la característica permite a los administradores escribir código personalizado sin tener que crear más archivos e incluirlos (aunque la mayoría de los marcos que usan características de evaluación también tienen una forma de especificar un archivo, módulo, paquete, ... para leer).

Sin embargo, eval es malo en la cultura popular. Me vienen a la mente cosas como irrumpir en su sistema.

Sin embargo, hay otras funciones que podrían ser perjudiciales si los usuarios acceden de alguna manera: desvincular, leer, escribir (semántica de archivos), asignación de memoria y aritmética de puntero, acceso al modelo de base de datos (incluso si no se consideran casos inyectables con SQL).

Entonces, básicamente, la mayoría de las veces cuando un código no se escribe correctamente o no se mira correctamente (recursos, usuarios, entornos, ...), el código es malo y puede conducir incluso a un impacto económico.

Pero hay algo especial con las evalfunciones (independientemente del idioma).

Pregunta : ¿Existe algún hecho histórico para que este miedo se convierta en parte de la cultura popular, en lugar de prestar la misma atención a las otras características posiblemente peligrosas?

Luis Masuelli
fuente
11
No estoy de acuerdo con que esto sea demasiado amplio, y como evidencia presento las cuatro respuestas que tienen una extensión razonable.
12
¿Votaron para cerrar como demasiado amplio ? (No puedo ver votos cerrados todavía en esta comunidad) Esa razón cercana se está convirtiendo en una razón comodín sin ningún significado últimamente. Especialmente cuando el punto que pido es bastante claro con ejemplos y un punto específico para preguntar. Preguntaré este tema en Meta ...
Luis Masuelli
13
¿Por qué se convierte en parte de la cultura popular, con más atención que otras características peligrosas? Debido a que la aliteración eval - el mal es fácil de recordar
Bergi
55
La asignación de memoria y la aritmética de punteros son vistos como malos, por muchos.
user253751
55
Cabe señalar que OpenERP (ahora Odoo) no solo llama eval, tiene una función interna llamada safe_evalque prepara el entorno para evitar que el código haga cosas peligrosas. Sin embargo, se han encontrado errores, ya que Python es un lenguaje bastante flexible y, por lo tanto, difícil de controlar.
André Paramés

Respuestas:

76

Una evalfunción en sí misma no es mala, y hay un punto sutil que no creo que estés haciendo:

Permitir que un programa ejecute entradas arbitrarias del usuario es malo

He escrito código que usaba un evaltipo de función y era seguro: el programa y los parámetros estaban codificados. A veces, no hay una función de lenguaje o biblioteca para hacer lo que el programa necesita y ejecutar un comando de shell es la ruta corta. "Tengo que terminar de codificar esto en unas pocas horas, pero escribir Java / .NET / PHP / cualquier código llevará dos días. O puedo evalhacerlo en cinco minutos".

Una vez que permite que los usuarios ejecuten lo que quieran, incluso si está bloqueado por privilegios de usuario o detrás de una pantalla "segura", crea vectores de ataque. Cada semana, algunos CMS aleatorios, software de blogs, etc. tienen un agujero de seguridad parcheado donde un atacante puede explotar un agujero como este. Confía en todo el paquete de software para proteger el acceso a una función que puede ser utilizada rm -rf /u otra cosa catastrófica (nota: es poco probable que el comando tenga éxito, pero fallará después de causar un poco de daño).

¿Existe algún hecho histórico para que este miedo se convierta en parte de la cultura popular, en lugar de poner la misma atención en otras características posiblemente peligrosas?

Sí, hay un precedente histórico. Debido a los numerosos errores que se han solucionado a lo largo de los años en varios programas que permiten a los atacantes remotos ejecutar código arbitrario, la idea evalha caído en desgracia. Los lenguajes y las bibliotecas modernas tienen un amplio conjunto de funcionalidades que hacen que sean evalmenos importantes, y esto no es accidental. Ambas hacen que las funciones sean más fáciles de usar y reducen el riesgo de un exploit.

Se ha prestado mucha atención a muchas características potencialmente inseguras en los idiomas populares. Si uno recibe más atención es principalmente una cuestión de opinión, pero las evalcaracterísticas ciertamente tienen un problema de seguridad comprobable que es fácil de entender. Por un lado, permiten ejecutar comandos del sistema operativo, incluidos programas integrados de shell y programas externos que son estándar (por ejemplo, rmo del). Dos, combinados con otros exploits, un atacante puede cargar su propio script ejecutable o shell y luego ejecutarlo a través de su software, abriendo la puerta para que suceda casi cualquier cosa (nada de bueno).

Este es un problema dificil. El software es complejo, y una pila de software (por ejemplo, LAMP ) son múltiples piezas de software que interactúan entre sí de formas complejas. Tenga cuidado al usar funciones de lenguaje como este, y nunca permita que los usuarios ejecuten comandos arbitrarios.


fuente
2
Eres el indicado :). Aunque si hay un buen ejemplo bien conocido que contribuyó a esta cultura, me gustaría verlo en la respuesta.
Luis Masuelli
55
No estoy al tanto de cualquier sola ejemplo, creo que esto es más "muerte por mil cortes" con muchos ejemplos de pequeñas hazañas que se utiliza y parcheado. No exagero cuando digo que algunas vulnerabilidades remotas se revisan semanalmente en algún software.
1
Mi IDE es un programa que me permite, es usuario, ejecutar entradas arbitrarias. Lo encuentro más útil que malo.
Den
3
@Den eso sería una excepción. Siendo un IDE, estoy seguro de que podrías causar un caos sin esa habilidad. Solo escríbelo en tu código fuente. Además, ya tiene acceso completo a la computadora en la que se ejecuta. La implicación aquí es que evalpuede elevar los privilegios. lo cual no es un problema si ya están elevados.
3
@ Den: es lo que Raymond Chen resumió como "el otro lado de la esclusa de aire". Ya puede ejecutar rm -rf /, no hay necesidad de hacerlo de manera complicada a través de un IDE. El problema evales que abre esa capacidad a muchos actores que no deberían tener esa capacidad.
MSalters
38

Parte de esto es simplemente que los matices son difíciles. Es fácil decir algo como nunca usar goto, campos públicos, interpolación de cadenas para consultas sql o eval. Estas declaraciones no deberían entenderse realmente como que dicen que, bajo ninguna circunstancia, hay una razón para usarlas. Pero evitarlos como regla general es una buena idea.

Eval se desaconseja porque combina varios problemas comunes.

En primer lugar, es susceptible a los ataques de inyección. Aquí es como la inyección SQL en que cuando los datos controlados por el usuario se insertan en el código, es fácil permitir accidentalmente que se inserte un código arbitrario.

En segundo lugar, los principiantes tienden a usar eval para sortear código mal estructurado. Un codificador principiante podría escribir código que se vea así:

x0 = "hello"
x1 = "world"
x2 = "how"
x3 = "are"
x4 = "you?"
for index in range(5):
   print eval("x" + index)

Esto funciona, pero es realmente la forma incorrecta de resolver este problema. Obviamente, usar una lista sería mucho mejor.

En tercer lugar, eval suele ser ineficiente. Se dedica mucho esfuerzo a acelerar nuestras implementaciones de lenguaje de programación. Pero evaluar es difícil de acelerar y su uso generalmente tendrá efectos perjudiciales en su rendimiento.

Entonces, eval no es malo. Podríamos decir que eval es malo, porque bueno, es una forma pegadiza de decirlo. Cualquier codificador principiante debe mantenerse estrictamente alejado de eval porque, sea lo que sea que quieran hacer, eval es casi seguramente la solución incorrecta. Para ciertos casos de uso avanzado, eval tiene sentido, y debe usarlo, pero obviamente tenga cuidado con las trampas.

Winston Ewert
fuente
13
Tu segundo caso es muy importante. En los lenguajes que tienen eval pero también se compilan, evaluar una cadena para producir una referencia variable no es trivial. Por ejemplo, si var x = 3; print(x)se compila , no es necesario que se sepa en tiempo de ejecución que la fuente usó el nombre "x". Para var x = 3; print(eval("x"))que funcione, ese mapeo debe registrarse. Este es un problema real: en Common Lisp se (let ((x 3)) (print (eval 'x)))generará una excepción de variable no vinculada porque la variable léxica x no tiene ninguna conexión con el nombre después de compilar el código.
Joshua Taylor
@JohnuaTaylor ¿Quieres decir la tercera razón, no la segunda?
user253751
1
@immibis, creo que se está refiriendo al código en la segunda razón. Pero tienes razón, está realmente relacionado con la tercera razón: el rendimiento.
Winston Ewert
Vio esta pregunta , ¿no? ;)
jpmc26
@ jpmc26, no. Pero he visto muchas cosas así.
Winston Ewert
20

Todo se reduce a que la "ejecución de código arbitrario" es una charla tecnológica para "poder hacer cualquier cosa". Si alguien puede explotar la ejecución de código arbitrario en su código, esta es literalmente la peor vulnerabilidad de seguridad posible, porque significa que puede hacer cualquier cosa que su sistema pueda hacer.

"Otros errores posiblemente dañinos" pueden tener límites, lo que significa que son, por definición, capaces de causar menos daño que una ejecución de código arbitrario que se explota.

Mason Wheeler
fuente
2
En aras de la discusión, el mal uso de los punteros también conduce a la ejecución de código arbitrario , sin embargo, los punteros están mal vistos mucho menos de lo que evales.
Dmitry Grigoryev
12
@DmitryGrigoryev ¿Son realmente? Fuera de C ++, los punteros generalmente se consideran extremadamente peligrosos y se evitan. C # admite punteros, por ejemplo, pero tiende a ser lo último que intenta después de agotar todas las demás opciones (generalmente, por razones de rendimiento en la manipulación de datos). La mayoría de los idiomas modernos no tienen soporte para punteros. Incluso C ++ se está moviendo hacia punteros "más seguros" que intentan aliviar los problemas con punteros arbitrarios (por ejemplo, usando listas / matrices verdaderas en lugar de solo punteros, usando safe_ptr, paso de referencia ...).
Luaan
2
@DmitryGrigoryev: ¿Puede proporcionar una referencia para cualquiera que diga que los punteros son menos peligrosos que eval?
JacquesB
2
@JacquesB aquí tienes :)
Dmitry Grigoryev
1
@JacquesB, sí; fue pensado como una broma (esperaba que la sonrisa lo aclarara lo suficiente) El OP hizo esa declaración, no yo, así que debes pedirle pruebas.
Dmitry Grigoryev
15

Hay una razón práctica y teórica.

La razón práctica es que observamos que con frecuencia causa problemas. Es raro que eval resulte en una buena solución, y a menudo resulta en una mala solución donde habría obtenido una mejor al final si fingiera que eval no existía y abordara el problema de manera diferente. Entonces, el consejo simplificado es ignorarlo, y si se te ocurre un caso en el que quieres ignorar el consejo simplificado, bueno, esperemos que lo hayas pensado lo suficiente como para entender por qué el consejo simplificado no es aplicable y lo común las trampas no te afectarán.

La razón más teórica es que si es difícil escribir un buen código, es aún más difícil escribir un código que escriba un buen código. Ya sea que esté utilizando eval, o generando sentencias SQL uniendo cadenas o escribiendo un compilador JIT, lo que intenta es a menudo más difícil de lo que espera. El potencial para la inyección de código malicioso es una gran parte del problema, pero aparte de eso, en general es más difícil saber que su código es correcto si su código ni siquiera existe hasta el tiempo de ejecución. Por lo tanto, el consejo simplificado es mantener las cosas más fáciles para usted: "use consultas SQL parametrizadas", "no use eval".

Tomando su ejemplo de efectos de hechizo: una cosa es construir un compilador o intérprete de Lua (o lo que sea) en su juego para permitir a los diseñadores de juegos un lenguaje más fácil que C ++ (o lo que sea) para describir los efectos de hechizo. La mayoría de los "problemas de evaluación" no se aplican si todo lo que está haciendo es evaluar el código que ha sido escrito y probado e incluido en el juego o en el DLC o lo que sea que tenga. Eso es solo mezclar idiomas. Los grandes problemas te afectan cuando intentas generar Lua (o C ++, o SQL, o comandos de shell, o lo que sea) sobre la marcha, y lo arruinas.

Steve Jessop
fuente
1
Por supuesto, la generación de código de tiempo de ejecución se puede hacer correctamente y eval puede ser útil. Por ejemplo, con frecuencia uso eval para metaprogramación / cosas similares a macros, especialmente cuando quiero más rendimiento del que podría proporcionar una OOP "más limpia" o una solución funcional. El código resultante es a menudo mejor y más simple porque tiene menos repetitivo. Sin embargo, ser consciente de varios problemas relacionados con el sandboxing, los mecanismos de escape, la inyección de código, las reglas de alcance, los informes de errores, la optimización, etc. requiere un nivel no trivial de dominio del idioma, y ​​evaluar es positivamente peligroso sin ese conocimiento.
amon
11

No, no hay un hecho histórico obvio.

Los males de eval son fáciles de ver desde el principio. Otras características son levemente peligrosas. Las personas pueden eliminar datos. Las personas pueden ver datos que no deberían ver. Las personas pueden escribir datos que no deberían. Y solo pueden hacer la mayoría de esas cosas si de alguna manera lo arruinas y no validas la entrada del usuario.

Con eval, pueden hackear el pentágono y hacer que parezca que lo hiciste. Pueden inspeccionar sus pulsaciones de teclas para obtener sus contraseñas. Asumiendo un lenguaje completo de Turing, literalmente pueden hacer cualquier cosa que su computadora sea capaz de hacer.

Y no puede validar la entrada. Es una cadena de forma libre arbitraria. La única forma de validarlo sería crear un analizador sintáctico y un motor de análisis de código para el idioma en cuestión. Mucha suerte con eso.

Telastyn
fuente
1
... o que la entrada provenga de una fuente confiable, como los archivos de definición de hechizos para un juego.
user253751
3
@immibis pero si la entrada está predefinida y se prueba de forma segura, ¿por qué usar eval cuando podría incluirse en la fuente del sistema?
Jules
3
@immibis - porque nadie hackea archivos de juegos ...
Telastyn
2
... eso no es lo que significa "Turing completo" (la integridad de Turing está a un paso de lo irrelevante a la informática del mundo real).
Leushenko
1
@Telastyn: lo que un programa Javascript no puede hacer. O incluso un programa C ++. Javascript se ejecuta dentro de un sandbox (navegador) que está en otro sandbox (anillo 3 en x86 speak). El vector de interrupción está fuera de ese entorno limitado, bajo control del sistema operativo. Y esa caja de arena externa, anillo 3, se aplica a la CPU.
MSalters
6

Creo que se reduce a los siguientes aspectos:

  • Necesidad
  • Uso (guardado)
  • Acceso
  • Verificabilidad
  • Ataques de múltiples etapas

Necesidad

Hola, he escrito esta herramienta de edición de imágenes extremadamente genial (disponible por $ 0.02). Después de abrir la imagen, puede pasar una multitud de filtros sobre su imagen. Incluso puede escribir algunos usted mismo usando Python (el programa en el que he escrito la aplicación). Solo lo usaré evalen tu entrada, confiando en que serás un usuario respetable.

(más tarde)

Gracias por comprarlo. Como puede ver, funciona exactamente como lo prometí. ¿Quieres abrir una imagen? No puedes. No usaré el readmétodo ya que es algo inseguro. ¿Ahorro? No, no lo usaré write.

Lo que estoy tratando de decir es: necesita leer / escribir para casi las herramientas básicas. Lo mismo para almacenar los puntajes más altos de tu juego tan increíble.

Sin lectura / escritura, su editor de imágenes es inútil. Sin eval? ¡Te escribiré un complemento personalizado para eso!

Uso (guardado)

Muchos métodos pueden ser potencialmente peligrosos. Como, por ejemplo, el ready write. Un ejemplo común es un servicio web que le permite leer imágenes de un directorio específico especificando el nombre. Sin embargo, el 'nombre' de hecho puede ser cualquier ruta válida (relativa) en el sistema, lo que le permite leer todos los archivos a los que tiene acceso el servicio web, no solo las imágenes. Abusar de este simple ejemplo se llama 'recorrido transversal'. Si su aplicación permite el recorrido de la ruta, es malo. A readsin defenderse de la travesía del camino se le puede llamar malvado.

Sin embargo, en otros casos, la cadena para readestá completamente bajo el control de los programadores (¿tal vez codificada?). En ese caso, no es malo usarlo read.

Acceso

Ahora, otro ejemplo simple, usando eval.

En algún lugar de su aplicación web, desea contenido dinámico. Vas a permitir que los administradores ingresen algún código que sea ejecutable. Dado que los administradores son usuarios de confianza, esto teóricamente puede estar bien. Solo asegúrate de no ejecutar el código enviado por personas que no son administradores, y estás bien.

(Es decir, hasta que despidió a ese buen administrador pero olvidó revocar su acceso. Ahora su aplicación web está en la papelera).

Verificabilidad

Otro aspecto que es importante, creo, es lo fácil que es verificar la entrada del usuario.

¿Usando la entrada del usuario en una llamada de lectura? Solo asegúrese (muy) de que la entrada para la llamada de lectura no contenga nada malicioso. Normalice la ruta y verifique que el archivo que está abierto esté en su directorio de medios. Ahora eso es seguro.

¿Entrada del usuario en una llamada de escritura? ¡Mismo!

¿Inyección SQL? Simplemente escape, o use consultas parametrizadas y estará a salvo.

Eval? ¿Cómo va a verificar la entrada que se utiliza para la evalllamada? Puedes trabajar muy duro, pero es realmente muy difícil (si no imposible) hacer que funcione de manera segura.

Ataques de múltiples etapas

Ahora, cada vez que usa la entrada del usuario, debe sopesar los beneficios de usarla, contra los peligros. Protege su uso tanto como puedas.

Considere nuevamente las evalcosas capaces en el ejemplo de administrador. Te dije que estaba bien.

Ahora, considere que en realidad hay un lugar en su aplicación web donde olvidó escapar del contenido del usuario (HTML, XSS). Esa es una ofensa menor que la evaluación accesible para el usuario. Pero, usando el contenido de usuario sin escape, un usuario puede hacerse cargo del navegador web de un administrador y agregar un evalblob capaz a través de la sesión de administradores, permitiendo nuevamente el acceso completo al sistema.

(El mismo ataque de múltiples etapas se puede hacer con inyección SQL en lugar de XSS, o algunas escrituras arbitrarias de archivos reemplazan el código ejecutable en lugar de usar eval)

Sjoerd Job Postmus
fuente
2
"Puedes trabajar muy duro, pero es realmente muy difícil (si no imposible) hacer que funcione de manera segura". - Se es imposible. Prueba simple: en lugar de tratar de averiguar si el código que proporcionó el usuario es "seguro" o no, simplemente trate de descubrir algo mucho, mucho más simple, y vea cuán difícil es eso : ¿se detiene el código proporcionado por el usuario?
Jörg W Mittag
2
@ JörgWMittag: dame un programa escrito en Coq y lo probaré.
André Paramés
1
@ JörgWMittag: De acuerdo. Dependiendo del idioma y el alcance de la entrada del usuario. Bien podría ser eval("hard coded string" + user_input_which_should_be_alphanumeric + "remainder"). Es posible verificar que la entrada sea alfanumérica. Además, 'se detiene' es ortogonal a 'se modifica / accede al estado que no debe tocar' y 'califica los métodos que no debería llamar'.
Sjoerd Job Postmus
3
@ JörgWMittag Es imposible demostrar que un programa dado no hará algo, pero no es imposible definir de manera conservadora un conjunto restringido de programas para los que pueda probarlo, y hacer cumplir que los programas de entrada son miembros de ese conjunto.
user253751
3

Para que esta característica funcione, significa que necesito mantener una capa de reflexión alrededor que permita el acceso completo al estado interno de todo el programa.

Para los idiomas interpretados, simplemente puedo usar el estado del intérprete, que es fácil, pero en combinación con los compiladores JIT aún aumenta significativamente la complejidad.

Sin eval, el compilador JIT a menudo puede probar que no se accede a los datos locales de un hilo desde ningún otro código, por lo que es perfectamente aceptable reordenar los accesos, omitir bloqueos y almacenar en caché los datos de uso frecuente durante más tiempo. Cuando otro subproceso ejecuta una evaldeclaración, puede ser necesario sincronizar el código compilado JIT en ejecución contra eso, por lo que de repente el código generado JIT necesita un mecanismo de reserva que regrese a la ejecución no optimizada dentro de un marco de tiempo razonable.

Este tipo de código tiende a tener muchos errores sutiles y difíciles de reproducir, y al mismo tiempo también pone un límite a la optimización en el compilador JIT.

Para los lenguajes compilados, la compensación es aún peor: la mayoría de las optimizaciones están prohibidas, y necesito mantener una amplia información de símbolos y un intérprete, por lo que la flexibilidad adicional generalmente no vale la pena; a menudo es más fácil definir una interfaz para algunos internos estructuras, por ejemplo, dando un scripting vista y controlador de acceso concurrente a del programa modelo .

Simon Richter
fuente
"Para que esta característica funcione, significa que necesito mantener una capa de reflexión alrededor que permita el acceso completo al estado interno de todo el programa", no, solo a las partes que desea afectar. En el caso de OpenERP / Odoo, el código que se está evadiendo solo tiene acceso a un número muy limitado de variables y funciones a las que puede llamar, y todas son subprocesas locales.
André Paramés
1

Rechazo la premisa de que evalse considera más mal que la aritmética de punteros o más peligroso que la memoria de acceso directo y sistema de archivos. No conozco a ningún desarrollador sensato que lo crea. Además, los lenguajes que admiten el acceso directo a memoria aritmética / puntero generalmente no son compatibles evaly viceversa, por lo que estoy seguro de con qué frecuencia tal comparación sería relevante.

Pero evalpodría ser una vulnerabilidad más conocida , por la sencilla razón de que es compatible con JavaScript. JavaScript es un lenguaje de espacio aislado sin memoria directa o acceso al sistema de archivos, por lo que simplemente no tiene estas vulnerabilidades, salvo debilidades en la implementación del lenguaje en sí. EvalPor lo tanto, es una de las características más peligrosas del lenguaje, ya que abre la posibilidad de ejecución de código arbitrario. Creo que muchos más desarrolladores se desarrollan en JavaScript que en C / C ++, por lo que evales más importante tener en cuenta que los desbordamientos de búfer para la mayoría de los desarrolladores.

JacquesB
fuente
0

Ningún programador serio consideraría que Eval es "malvado". Es simplemente una herramienta de programación, como cualquier otra. El miedo (si hay miedo) a esta función no tiene nada que ver con la cultura popular. Es simplemente un comando peligroso que a menudo se usa incorrectamente y puede introducir graves agujeros de seguridad y degradar el rendimiento. Desde mi propia experiencia, diría que es raro encontrar un problema de programación que no se puede resolver de manera más segura y eficiente por otros medios. Los programadores que tienen más probabilidades de usar eval, son aquellos que probablemente están menos calificados para hacerlo de manera segura.

Dicho esto, hay idiomas en los que el uso de eval es apropiado. Perl viene a la mente. Sin embargo, personalmente considero que rara vez se necesita en otros lenguajes más modernos, que admiten de forma nativa el manejo estructurado de excepciones.

usuario1751825
fuente
esto ni siquiera intenta abordar la pregunta formulada, "¿Hay algún hecho histórico para que este miedo se convierta en parte de la cultura popular". Vea cómo responder
mosquito
La pregunta, en mi opinión, se basa en una premisa falsa, así que la respondí como tal.
user1751825
0

Creo que lo cubres bastante bien en la siguiente parte de tu pregunta (énfasis mío):

tienen un buen uso, siempre que se usen correctamente

Para el 95% que podría usarlo correctamente, todo está bien; pero siempre habrá personas que no lo usen correctamente. Algunos de ellos se deben a la inexperiencia y la falta de capacidad, el resto será malicioso.

Siempre habrá personas que quieran superar los límites y encontrar agujeros de seguridad, algunos para bien, otros para mal.

En cuanto al aspecto de hecho histórico, las evalfunciones de tipo esencialmente permiten la ejecución de código arbitrario que se ha explotado previamente en el popular CMS web, Joomla! . Con Joomla! con más de 2.5 millones de sitios en todo el mundo , eso es un daño potencial no solo para los visitantes de esos sitios, sino también para la infraestructura en la que se aloja y también la reputación de los sitios / compañías que han sido explotados.

El Joomla! El ejemplo puede ser simple, pero es uno que ha sido grabado.

gabe3886
fuente
0

Hay algunas buenas razones para desalentar el uso de eval(aunque algunas son específicas de ciertos idiomas).

  • El entorno (léxico y dinámico) utilizado por evales con frecuencia sorprendente (es decir, cree que eval(something here)debería hacer una cosa, pero hace otra, posiblemente desencadenando excepciones)
  • Con frecuencia hay una mejor manera de lograr lo mismo (la concatenación de cierres léxicos construidos es a veces una mejor solución, pero eso puede ser específico de Common Lisp)
  • Es demasiado fácil terminar con la evaluación de datos inseguros (aunque esto puede evitarse en su mayoría).

Personalmente, no iría tan lejos como para decir que es malo, pero siempre cuestionaré el uso evalen una revisión de código, con palabras como "¿ha considerado algún código aquí ?" (si tengo tiempo para hacer al menos un reemplazo provisional) o "¿estás seguro de que una evaluación es realmente la mejor solución aquí?" (si no lo hago)

Vatine
fuente
esto ni siquiera intenta abordar la pregunta formulada, "¿Hay algún hecho histórico para que este miedo se convierta en parte de la cultura popular". Vea cómo responder
mosquito
0

En Minsky's Society of Mind , Capítulo 6.4, dice

Hay una manera de que una mente se vea a sí misma y siga el rastro de lo que está sucediendo. Divida el cerebro en dos partes, A y B. Conecte las entradas y salidas del cerebro A al mundo real, para que pueda sentir lo que sucede allí. Pero no conecte el cerebro B con el mundo exterior; en lugar de eso, conéctelo para que el cerebro A sea el mundo del cerebro B.

Cuando un programa (B) escribe otro programa (A), funciona como un metaprograma. El tema de B es el programa A.

Hay un programa de C. Ese es el que en tu cabeza escribe el programa B.

El peligro es que puede haber alguien (C ') con malas intenciones, que puede interferir en este proceso, por lo que obtienes cosas como la inyección de SQL.

El desafío es hacer que el software sea más inteligente sin hacerlo también más peligroso.

Mike Dunlavey
fuente
Dos votos a favor y dos votos a favor. Parece que tal vez esto golpea un nervio.
Mike Dunlavey
0

Tiene muchas buenas respuestas aquí y la razón principal es claramente que la ejecución de código arbitrario es mala mmmkay, pero agregaré otro factor que otros solo han tocado al borde de:

Es realmente difícil solucionar el código que se está evaluando a partir de una cadena de texto. Sus herramientas de depuración normales son prácticamente directas y queda reducido al rastreo o eco de la vieja escuela. Obviamente, eso no importa tanto si tiene un fragmento en una línea que desea, evalpero como programador experimentado probablemente pueda encontrar una mejor solución para eso, mientras que la generación de código a mayor escala puede estar en algún lugar que una función de evaluación se convierte en un aliado potencialmente útil.

glenatron
fuente