En todos los años que he estado desarrollando en php, siempre he escuchado que usar eval()
es malo.
Teniendo en cuenta el siguiente código, ¿no tendría sentido utilizar la segunda (y más elegante) opción? Si no es así, ¿por qué?
// $type is the result of an SQL statement
// e.g. SHOW COLUMNS FROM a_table LIKE 'a_column';
// hence you can be pretty sure about the consistency
// of your string
$type = "enum('a','b','c')";
// possibility one
$type_1 = preg_replace('#^enum\s*\(\s*\'|\'\s*\)\s*$#', '', $type);
$result = preg_split('#\'\s*,\s*\'#', $type_1);
// possibility two
eval('$result = '.preg_replace('#^enum#','array', $type).';');
$result = array(); preg_replace_callback('#^enum\s*\(\s*\'|\'\s*\)\s*$#', function($m) use($result) { $result[] = $m[1]; }, $type);
Respuestas:
Sería cauteloso al llamar a eval () pura maldad. La evaluación dinámica es una herramienta poderosa y, a veces, puede salvar la vida. Con eval () se pueden solucionar las deficiencias de PHP (ver más abajo).
Los principales problemas con eval () son:
El principal problema con el uso real de eval () es solo uno:
Como regla general, tiendo a seguir esto:
fuente
eval es malo cuando existe la más mínima posibilidad de que la entrada del usuario esté incluida en la cadena evaluada. Cuando realiza una evaluación sin contenido que proviene de un usuario, debe estar seguro.
Sin embargo, debería pensar al menos dos veces antes de usar eval, parece engañosamente simple, pero teniendo en cuenta el manejo de errores (ver el comentario de VBAssassins), la capacidad de depuración, etc., ya no es tan simple.
Entonces, como regla general: Olvídate de eso. ¡Cuando eval es la respuesta, probablemente estás haciendo la pregunta incorrecta! ;-)
fuente
eval()
es imposible, este es un mejor enfoque. Mucha gente dice queeval()
es inevitable en algunos casos, pero no mencionan ningún ejemplo específico que podamos argumentar, de esta manera este debate no tiene sentido. Así que por favor, gente que dice queeval()
es inevitable, ¡pruébenlo primero!eval () es igualmente malvado en todo momento.
"¿Cuándo eval () no es malo?" es la pregunta incorrecta en mi opinión, porque parece implicar que los inconvenientes de usar eval () desaparecen mágicamente en algunos contextos.
El uso de eval () es generalmente una mala idea porque disminuye la legibilidad del código, la capacidad de predecir la ruta del código (y las posibles implicaciones de seguridad de eso) antes del tiempo de ejecución y, por lo tanto, la capacidad de depurar el código. El uso de eval () también puede evitar que el código evaluado y el código que lo rodea sea optimizado por una caché de código de operación como Zend Opcache integrado en PHP 5.5 y superior, o por un compilador JIT como el de HHVM.
Además, no existe ninguna situación para la que sea absolutamente necesario utilizar eval (); PHP es un lenguaje de programación totalmente capaz sin él.
Si realmente los ve o no como males o si puede justificar personalmente el uso de eval () en algunos casos, depende de usted. Para algunos, los males son demasiado grandes como para justificarlos, y para otros, eval () es un atajo útil.
Sin embargo, si ve eval () como malvado, es malvado en todo momento. No pierde mágicamente su maldad según el contexto.
fuente
En este caso, eval es probablemente lo suficientemente seguro, siempre que nunca sea posible que un usuario cree columnas arbitrarias en una tabla.
Sin embargo, en realidad no es más elegante. Esto es básicamente un problema de análisis de texto, y abusar del analizador de PHP para manejarlo parece un poco complicado. Si desea abusar de las funciones del idioma, ¿por qué no abusar del analizador JSON? Al menos con el analizador JSON, no hay ninguna posibilidad de inyección de código.
$json = str_replace(array( 'enum', '(', ')', "'"), array) '', '[', ']', "'"), $type); $result = json_decode($json);
Una expresión regular es probablemente la forma más obvia. Puede usar una sola expresión regular para extraer todos los valores de esta cadena:
$extract_regex = '/ (?<=,|enum\() # Match strings that follow either a comma, or the string "enum("... \' # ...then the opening quote mark... (.*?) # ...and capture anything... \' # ...up to the closing quote mark... /x'; preg_match_all($extract_regex, $type, $matches); $result = $matches[1];
fuente
eval()
es lento, pero yo no lo llamaría malvado.Es el mal uso que hacemos de él lo que puede llevar a la inyección de código y ser malvado.
Un simple ejemplo:
$_GET = 'echo 5 + 5 * 2;'; eval($_GET); // 15
Un ejemplo dañino:
$_GET = 'system("reboot");'; eval($_GET); // oops
Le aconsejaría que no lo use,
eval()
pero si lo hace, asegúrese de validar / incluir en la lista blanca todas las entradas.fuente
Cuando utiliza datos externos (como la entrada del usuario) dentro de eval.
En su ejemplo anterior, esto no es un problema.
fuente
voy a robar descaradamente el contenido aquí:
blog.joshuaeichorn.com: usando-eval-en-php
fuente
eval()
es siempre malvado.fuente
eval()
, supongo que he hecho la pregunta mal; rara vez es la respuesta "correcta", pero afirmar que siempre es malvado es simplemente incorrecto.También prestaría algo de consideración a las personas que mantienen su código.
eval () no es fácil de mirar y saber lo que se supone que debe suceder, tu ejemplo no es tan malo, pero en otros lugares puede ser una verdadera pesadilla.
fuente
Personalmente, creo que el código sigue siendo bastante malo porque no estás comentando lo que está haciendo. Tampoco está probando la validez de sus entradas, lo que lo hace muy frágil.
También creo que, dado que el 95% (o más) de los usos de eval son activamente peligrosos, el pequeño ahorro de tiempo potencial que podría proporcionar en otros casos no vale la pena permitirse la mala práctica de usarlo. Además, luego tendrás que explicar a tus secuaces por qué tu uso de eval es bueno y el de ellos malo.
Y, por supuesto, su PHP termina pareciéndose a Perl;)
Hay dos problemas clave con eval (), (como un escenario de "ataque de inyección"):
1) Puede causar daño 2) Simplemente puede fallar
y uno que es más social que técnico:
3) Tentará a las personas a usarlo de manera inapropiada como atajo en otros lugares
En el primer caso, corre el riesgo (obviamente, no cuando está evaluando una cadena conocida) de la ejecución de código arbitrario. Sin embargo, es posible que sus entradas no sean tan conocidas o tan fijas como cree.
Es más probable (en este caso) que se bloquee y su cadena termine con un mensaje de error innecesariamente oscuro. En mi humilde opinión, todo el código debería fallar lo más claramente posible, en caso contrario, debería generar una excepción (como la forma de error más manejable).
Sugeriría que, en este ejemplo, esté codificando por coincidencia en lugar de codificar el comportamiento. Sí, la declaración de enumeración de SQL (y ¿está seguro de la enumeración de ese campo? - ¿llamó al campo correcto de la tabla correcta de la versión correcta de la base de datos? ¿En realidad respondió?) Parece tener la sintaxis de declaración de matriz en PHP, pero sugiero que lo que realmente quiere hacer no es encontrar el camino más corto desde la entrada hasta la salida, sino abordar la tarea especificada:
Que es aproximadamente lo que hace su opción uno, pero envolvería algunos if y comentarios para mayor claridad y seguridad (por ejemplo, si la primera coincidencia no coincide, arroje una excepción o establezca un resultado nulo).
Todavía hay algunos problemas posibles con las comillas o comillas de escape, y probablemente debería descomprimir los datos y luego eliminarlos, pero al menos trata los datos como datos, en lugar de como código.
Con preg_version, es probable que su peor resultado sea $ result = null, con la versión eval se desconoce el peor, pero al menos un bloqueo.
fuente
eval evalúa una cadena como código, el problema es que si la cadena está "contaminada" de alguna manera, podría exponer enormes amenazas de seguridad. Normalmente, el problema es en un caso en el que la entrada del usuario se evalúa en la cadena; en muchos casos, el usuario podría ingresar código (php o ssi, por ejemplo) que luego se ejecuta dentro de eval, se ejecutaría con los mismos permisos que su script php y podría ser utilizado para obtener información / acceso a su servidor. Puede ser bastante complicado asegurarse de que la entrada del usuario se elimine correctamente antes de entregársela a eval. Hay otros problemas ... algunos de los cuales son discutibles
fuente
PHP aconseja que escriba su código de tal manera que se pueda ejecutar a través de call_user_func en lugar de realizar evaluaciones explícitas.
fuente
Otra razón
eval
es que no se puede almacenar en caché mediante cachés de código de bytes de PHP como eAccelertor o ACP.fuente
Es una mala programación lo que hace que eval () sea malo, no la función. Lo uso a veces, ya que no puedo evitarlo en la programación dinámica en varios sitios. No puedo hacer que PHP sea analizado en un sitio, ya que no recibiré las cosas que quiero. ¡Solo recibiría un resultado! Estoy feliz de que exista una función como eval (), ya que hace mi vida mucho más fácil. ¿Entrada del usuario? Los hackers sólo enganchan a los programadores malos. No me preocupo por eso.
fuente
Predigo que pronto tendrás serios problemas ...
Honestamente, no hay absolutamente ningún buen uso para una función exorbitante como eval, en un lenguaje interpretado como PHP. Nunca he visto a eval realizar funciones de programa que no se podrían haber ejecutado usando otras formas más seguras ...
Eval es la raíz de todos los males, estoy totalmente de acuerdo, para todas las personas que piensan que probar la entrada del usuario ayudará. Piénselo dos veces, la entrada del usuario puede tener muchas formas diferentes y, mientras hablamos, los piratas informáticos están explotando esa función que no le importaba lo suficiente. En mi opinión, simplemente evite eval por completo.
He visto ejemplos elaborados para abusar de la función eval que sobrepasó mi propia creatividad. Desde una posición de seguridad, evítelo a toda costa, e incluso iría tan lejos como para exigir que sea al menos una opción en la configuración de PHP, en lugar de un 'dado'.
fuente
eval
. Y por lo tanto, para cualquier característica, X: X es la raíz de todo eval ... er ... evil, así que mejor renuncie a la programación por completo (tirando así de la alfombra debajo de esos tontos hackers, aún burlándolos eventualmente).Aquí hay una solución para ejecutar código PHP extraído de una base de datos sin usar eval. Permite todas las funciones y excepciones del alcance:
$rowId=1; //database row id $code="echo 'hello'; echo '\nThis is a test\n'; echo date(\"Y-m-d\");"; //php code pulled from database $func="func{$rowId}"; file_put_contents('/tmp/tempFunction.php',"<?php\nfunction $func() {\n global \$rowId;\n$code\n}\n".chr(63).">"); include '/tmp/tempFunction.php'; call_user_func($func); unlink ('/tmp/tempFunction.php');
Básicamente, crea una función única con el código incluido en un archivo de texto, incluye el archivo, llama a la función y luego elimina el archivo cuando termina con él. Estoy usando esto para realizar ingestiones / sincronizaciones diarias de bases de datos donde cada paso requiere un código único para procesar. Esto ha resuelto todos los problemas a los que me enfrentaba.
fuente
Solía usar eval () mucho, pero encontré que en la mayoría de los casos no es necesario usar eval para hacer trucos. Bueno, tienes call_user_func () y call_user_func_array () en PHP. Es lo suficientemente bueno para llamar estática y dinámicamente a cualquier método.
Para realizar una llamada estática, construya su devolución de llamada como una matriz ('class_name', 'method_name'), o incluso como una cadena simple como 'class_name :: method_name'. Para realizar una llamada dinámica, use la devolución de llamada de estilo array ($ object, 'method').
El único uso sensato de eval () es escribir un compilador personalizado. Hice uno, pero eval sigue siendo malo, porque es muy difícil de depurar. Lo peor es que el error fatal en el código evaluado bloquea el código que lo llamó. Usé la extensión Parsekit PECL para verificar la sintaxis al menos, pero aún así no me alegro: intente hacer referencia a clases desconocidas y fallas de aplicaciones completas.
fuente
Aparte de las preocupaciones de seguridad, eval () no se puede compilar, optimizar o almacenar en caché el código de operación, por lo que siempre será más lento, mucho más lento , que el código php normal. Por lo tanto, no es eficaz usar eval, aunque eso no lo convierte en malo. (
goto
es malvado,eval
es solo una mala práctica / código maloliente / feo)fuente
eval
obtiene una calificación de maldad más baja quegoto
? ¿Es el día opuesto?goto
en 5.3.goto
fobianos: están las herramientas, y están los artesanos, que las usan (o no). Es que nunca las herramientas que hacen un aspecto profesional como un idiota, cuando cometer errores, sino más bien la imposibilidad de utilizar las herramientas adecuadas (correctamente). Pero siempre son las herramientas las que tienen la culpa ...La mayoría de la gente señalará el hecho de que puede ser peligroso cuando se trata de la entrada del usuario (que es posible de manejar).
Para mí, la peor parte es que reduce la capacidad de mantenimiento de su código:
fuente