Au cours de toutes les années que j'ai développées en php, j'ai toujours entendu dire que l'utilisation eval()
était maléfique.
Compte tenu du code suivant, ne serait-il pas logique d'utiliser la deuxième option (et plus élégante)? Si non, pourquoi?
// $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);
Réponses:
Je serais prudent en appelant eval () pur evil. L'évaluation dynamique est un outil puissant et peut parfois sauver la vie. Avec eval (), on peut contourner les lacunes de PHP (voir ci-dessous).
Les principaux problèmes avec eval () sont:
Le principal problème avec l'utilisation réelle de eval () est un seul:
En règle générale, j'ai tendance à suivre ceci:
la source
eval est mauvais quand il n'y a que la moindre possibilité que userinput soit inclus dans la chaîne évaluée. Lorsque vous évaluez sans contenu provenant d'un utilisateur, vous devez être en sécurité.
Néanmoins, vous devriez réfléchir au moins deux fois avant d'utiliser eval, cela a l'air d'une simplicité trompeuse, mais avec la gestion des erreurs (voir le commentaire de VBAssassins), la débuggabilité, etc. à l'esprit, ce n'est plus si simple.
Donc, en règle générale: oubliez ça. Lorsque eval est la réponse, vous posez probablement la mauvaise question! ;-)
la source
eval()
est impossible d' éviter l'utilisation de , c'est une meilleure approche. Beaucoup de gens disent queeval()
c'est inévitable dans certains cas, mais ils ne mentionnent aucun exemple spécifique que nous pourrions argumenter - de cette façon, ce débat n'a pas de sens. Alors s'il vous plaît, les gens qui disent queeval()
c'est inévitable, prouvez-le d'abord!eval () est également mauvais à tout moment.
"Quand eval () n'est-il pas mauvais?" est la mauvaise question à poser à mon avis, car elle semble impliquer que les inconvénients de l'utilisation de eval () disparaissent comme par magie dans certains contextes.
Utiliser eval () est généralement une mauvaise idée car cela diminue la lisibilité du code, la possibilité pour vous de prédire le chemin du code (et les implications de sécurité possibles de cela) avant l'exécution, et donc la capacité de déboguer le code. Utiliser eval () peut également empêcher le code évalué et le code qui l'entoure d'être optimisé par un cache d'opcode tel que le Zend Opcache intégré à PHP 5.5 et supérieur, ou par un compilateur JIT tel que celui de HHVM.
De plus, il n'y a aucune situation pour laquelle il est absolument nécessaire d'utiliser eval () - PHP est un langage de programmation pleinement capable sans lui.
Que vous les voyiez ou non comme des maux ou que vous puissiez justifier personnellement l'utilisation de eval () dans certains cas, cela dépend de vous. Pour certains, les maux sont trop grands pour jamais le justifier, et pour d'autres, eval () est un raccourci pratique.
Cependant, si vous voyez eval () comme un mal, c'est le mal à tout moment. Il ne perd pas comme par magie sa perversité selon le contexte.
la source
Dans ce cas, eval est probablement suffisamment sûr, tant qu'il n'est jamais possible de créer des colonnes arbitraires dans une table par un utilisateur.
Ce n'est pas vraiment plus élégant cependant. Il s'agit essentiellement d'un problème d'analyse de texte, et abuser de l'analyseur PHP pour le gérer semble un peu piraté. Si vous voulez abuser des fonctionnalités du langage, pourquoi ne pas abuser de l'analyseur JSON? Au moins avec l'analyseur JSON, il n'y a aucune possibilité d'injection de code.
$json = str_replace(array( 'enum', '(', ')', "'"), array) '', '[', ']', "'"), $type); $result = json_decode($json);
Une expression régulière est probablement le moyen le plus évident. Vous pouvez utiliser une seule expression régulière pour extraire toutes les valeurs de cette chaîne:
$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];
la source
eval()
est lent, mais je n'appellerais pas ça mal.C'est le mauvais usage que nous en faisons qui peut conduire à l' injection de code et être mauvais.
Un exemple simple:
$_GET = 'echo 5 + 5 * 2;'; eval($_GET); // 15
Un exemple néfaste:
$_GET = 'system("reboot");'; eval($_GET); // oops
Je vous conseillerais de ne pas utiliser,
eval()
mais si vous le faites, assurez-vous de valider / mettre en liste blanche toutes les entrées.la source
Lorsque vous utilisez des données étrangères (telles que les entrées utilisateur) dans eval.
Dans votre exemple ci-dessus, ce n'est pas un problème.
la source
Je vais voler de manière flagrante le contenu ici:
blog.joshuaeichorn.com: utilisation-eval-in-php
la source
eval()
est toujours mauvais.la source
eval()
, je suppose juste que j'ai posé la mauvaise question; C'est rarement la «bonne» réponse, mais dire que c'est toujours le mal est tout simplement incorrect.Je prêterais également attention aux personnes qui maintiennent votre code.
eval () n'est pas facile à regarder et à savoir ce qui est censé se passer, votre exemple n'est pas si mauvais, mais dans d'autres endroits, cela peut être un vrai cauchemar.
la source
Personnellement, je pense que ce code est encore assez mauvais parce que vous ne commentez pas ce qu'il fait. Il ne teste pas non plus la validité de ses entrées, ce qui le rend très fragile.
Je pense également que, puisque 95% (ou plus) des utilisations d'Eval sont activement dangereuses, le petit gain de temps potentiel qu'il pourrait fournir dans d'autres cas ne vaut pas la peine de se livrer à la mauvaise pratique de l'utiliser. De plus, vous devrez plus tard expliquer à vos serviteurs pourquoi votre utilisation d'Eval est bonne et la leur mauvaise.
Et, bien sûr, votre PHP finit par ressembler à Perl;)
Il y a deux problèmes clés avec eval (), (comme un scénario "d'attaque par injection"):
1) Cela peut causer des dommages 2) Il peut simplement s'écraser
et un qui est plus social que technique:
3) Cela incitera les gens à l'utiliser de manière inappropriée comme raccourci ailleurs
Dans le premier cas, vous courez le risque (évidemment, pas lorsque vous évaluez une chaîne connue) de l'exécution de code arbitraire. Cependant, vos entrées peuvent ne pas être aussi connues ou aussi fixes que vous le pensez.
Plus probablement (dans ce cas) vous ne ferez que planter, et votre chaîne se terminera par un message d'erreur gratuit et obscur. À mon humble avis, tout le code doit échouer aussi proprement que possible, faute de quoi il doit lancer une exception (comme la forme d'erreur la plus gérable).
Je suggérerais que, dans cet exemple, vous codez par coïncidence plutôt que par comportement. Oui, l'instruction SQL enum (et êtes-vous sûr que l'énumération de ce champ? - avez-vous appelé le bon champ de la bonne table de la bonne version de la base de données? mais je suggérerais que ce que vous voulez vraiment faire n'est pas de trouver le chemin le plus court de l'entrée à la sortie, mais plutôt de vous attaquer à la tâche spécifiée:
Ce qui est à peu près ce que fait votre option, mais j'envelopperais quelques if et des commentaires pour plus de clarté et de sécurité (par exemple, si la première correspondance ne correspond pas, lancez une exception ou définissez un résultat nul).
Il y a encore des problèmes possibles avec des virgules ou des guillemets, et vous devriez probablement décompresser les données puis les retirer, mais cela traite au moins les données comme des données, plutôt que comme du code.
Avec la version preg_version, votre pire résultat sera probablement $ result = null, avec la version eval, le pire est inconnu, mais au moins un crash.
la source
eval évalue une chaîne en tant que code, le problème avec cela est que si la chaîne est en quelque sorte «corrompue», elle peut exposer d'énormes menaces de sécurité. Normalement, le problème est dans un cas où l'entrée de l'utilisateur est évaluée dans la chaîne dans de nombreux cas, l'utilisateur pourrait entrer du code (php ou ssi par exemple) qui est ensuite exécuté dans eval, il s'exécuterait avec les mêmes autorisations que votre script php et pourrait être utilisé pour obtenir des informations / accéder à votre serveur. Il peut être assez difficile de s'assurer que l'entrée utilisateur est correctement nettoyée avant de la transmettre à eval. Il y a d'autres problèmes ... dont certains sont discutables
la source
PHP vous conseille d'écrire votre code de telle manière qu'il puisse être exécuté via call_user_func au lieu de faire des évaluations explicites.
la source
Une autre raison
eval
est le mal, c'est qu'il ne pouvait pas être mis en cache par des caches de bytecode PHP comme eAccelertor ou ACP.la source
C'est une mauvaise programmation qui rend eval () mauvais, pas la fonction. Je l'utilise parfois, car je n'arrive pas à le contourner en programmation dynamique sur plusieurs sites. Je ne peux pas faire analyser PHP sur un site, car je ne recevrai pas les choses que je veux. Je recevrais juste un résultat! Je suis heureux qu'une fonction comme eval () existe, car cela me facilite la vie. Entrée utilisateur? Seuls les mauvais programmeurs sont accrochés par des pirates. Je ne m'inquiète pas pour ça.
la source
Je prédis que vous aurez bientôt de sérieux problèmes ...
En toute honnêteté, il n'y a absolument aucune bonne utilité pour une fonction exorbitante comme eval, dans un langage interprété tel que PHP. Je n'ai jamais vu eval exécuter des fonctions de programme qui n'auraient pas pu être exécutées par d'autres moyens plus sûrs ...
Eval est la racine de tout mal, je suis tout à fait d'accord, pour toutes les personnes qui pensent que tester les entrées des utilisateurs aidera. Réfléchissez à deux fois, les entrées des utilisateurs peuvent prendre de nombreuses formes différentes, et au moment où nous parlons, les pirates exploitent cette fonction dont vous ne vous souciez pas assez. À mon avis, évitez tout simplement eval.
J'ai vu des exemples conçus pour abuser de la fonction d'évaluation qui surpassait ma propre créativité. Du point de vue de la sécurité, évitez à tout prix, et j'irais même jusqu'à exiger qu'il soit à tout le moins une option dans la configuration PHP, plutôt qu'un «donné».
la source
eval
. Et par conséquent, pour toute fonctionnalité X: X est la racine de tous les eval ... euh ... mal, alors mieux vaut abandonner complètement la programmation (tirant ainsi le tapis de ces hackers stupides, les déjouant encore finalement).Voici une solution pour exécuter du code PHP extrait d'une base de données sans utiliser eval. Permet toutes les fonctions et exceptions de la portée:
$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');
Fondamentalement, il crée une fonction unique avec le code inclus dans un fichier texte, inclut le fichier, appelle la fonction, puis supprime le fichier une fois terminé. J'utilise ceci pour effectuer des ingestions / synchronisations quotidiennes de bases de données où chaque étape nécessite un code unique à traiter. Cela a résolu tous les problèmes auxquels je faisais face.
la source
J'utilisais beaucoup eval (), mais j'ai trouvé dans la plupart des cas que vous n'avez pas besoin d'utiliser eval pour faire des tours. Eh bien, vous avez call_user_func () et call_user_func_array () en PHP. Il suffit d'appeler statiquement et dynamiquement n'importe quelle méthode.
Pour effectuer un appel statique, construisez votre rappel sous forme de tableau ('nom_classe', 'nom_méthode'), ou même sous forme de chaîne simple comme 'nom_classe :: nom_méthode'. Pour effectuer un appel dynamique, utilisez le rappel de style array ($ object, 'method').
La seule utilisation judicieuse de eval () est d'écrire un compilateur personnalisé. J'en ai fait un, mais eval est toujours mauvais, car il est tellement difficile à déboguer. Le pire est que l'erreur fatale dans le code évalué bloque le code qui l'a appelé. J'ai utilisé l'extension Parsekit PECL pour vérifier au moins la syntaxe, mais toujours pas de joie - essayez de faire référence à une classe inconnue et à des plantages d'application entiers.
la source
Hormis les problèmes de sécurité, eval () ne peut pas être compilé, optimisé ou mis en cache opcode, donc il sera toujours plus lent - bien plus lent - que le code PHP normal. Il n'est donc pas performant d'utiliser eval, même si cela ne le rend pas mauvais. (
goto
c'est mal,eval
c'est seulement une mauvaise pratique / code malodorant / moche)la source
eval
obtient une cote perverse inférieure àgoto
? Est-ce le jour opposé?goto
en 5.3.goto
-fobiens: il y a les outils, et il y a les artisans, qui les utilisent (ou pas). Ce ne sont jamais les outils qui font passer un professionnel comme un idiot, quand il fait des erreurs, mais plutôt l'incapacité d'utiliser les bons outils (correctement). Mais ce sont toujours les outils à blâmer ...La plupart des gens souligneront le fait que cela peut être dangereux lorsque vous traitez avec les entrées de l'utilisateur (ce qui est possible).
Pour moi, le pire est que cela réduit la maintenabilité de votre code:
la source