programing tip

PHP에서 평가 악은 언제입니까?

itbloger 2020. 9. 23. 07:24
반응형

PHP에서 평가 악은 언제입니까?


내가 PHP로 개발해 온 모든 해 동안, 나는 항상 사용하는 eval()것이 악 하다고 들었습니다 .

다음 코드를 고려할 때 두 번째 (더 우아한) 옵션을 사용하는 것이 합리적이지 않습니까? 그렇지 않다면 왜?

// $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).';');

eval () 순수한 악을 호출 할 때는주의해야합니다. 동적 평가는 강력한 도구이며 때로는 생명의 은인이 될 수 있습니다. eval ()을 사용하면 PHP의 단점을 해결할 수 있습니다 (아래 참조).

eval ()의 주요 문제점은 다음과 같습니다.

  • 잠재적으로 안전하지 않은 입력. 신뢰할 수없는 매개 변수를 전달하는 것은 실패하는 방법입니다. 매개 변수 (또는 매개 변수의 일부)가 완전히 신뢰할 수 있는지 확인하는 것은 쉬운 일이 아닙니다.
  • 속임수. eval ()을 사용하면 코드가 영리 해져 따라 가기가 더 어려워집니다. Brian Kernighan을 인용하려면 " 디버깅은 처음에 코드를 작성하는 것보다 두 배 더 어렵습니다. 따라서 코드를 가능한 한 똑똑하게 작성하면 정의상 디버깅 할만큼 똑똑하지 않은 것입니다. "

eval ()의 실제 사용과 관련된 주요 문제는 다음 중 하나입니다.

  • 충분히 고려하지 않고 사용하는 경험이없는 개발자.

경험상 나는 이것을 따르는 경향이 있습니다.

  1. 때로는 eval ()이 유일한 / 올바른 솔루션입니다.
  2. 대부분의 경우 다른 것을 시도해야합니다.
  3. 확실하지 않은 경우 2로 이동합니다.
  4. 그렇지 않으면 매우 조심하십시오.

평가 된 문자열에 userinput이 포함될 가능성이 아주 적을 때 eval은 악의적입니다. 사용자의 콘텐츠없이 평가를 할 때 안전해야합니다.

그럼에도 불구하고 eval을 사용하기 전에 최소한 두 번 생각해야합니다. 믿을 수 없을 정도로 간단 해 보이지만 오류 처리 (VBAssassins 주석 참조), 디버깅 가능성 등을 염두에두고 더 이상 간단하지 않습니다.

따라서 경험 상으로는 잊어 버리세요. eval이 대답이면 잘못된 질문을하는 것입니다! ;-)


eval ()은 항상 똑같이 악합니다.

"eval ()은 언제 악하지 않습니까?" eval () 사용에 대한 단점이 일부 상황에서 마술처럼 사라진다는 것을 암시하는 것처럼 보이기 때문에 내 의견으로는 잘못된 질문입니다.

eval ()을 사용하는 것은 일반적으로 코드의 가독성, 런타임 전에 코드 경로를 예측할 수있는 기능 (및 그에 대한 가능한 보안 영향), 따라서 코드를 디버깅하는 기능을 저하시키기 때문에 나쁜 생각입니다. eval ()을 사용하면 평가 된 코드와이를 둘러싼 코드가 PHP 5.5 이상에 통합 된 Zend Opcache와 같은 opcode 캐시 또는 HHVM에있는 것과 같은 JIT 컴파일러에 의해 최적화되는 것을 방지 할 수 있습니다.

게다가 eval ()을 반드시 사용해야하는 상황은 없습니다. PHP는 그것 없이는 완전한 기능을 갖춘 프로그래밍 언어입니다.

실제로 이것을 악으로 보는지 아닌지 또는 경우에 따라 eval ()을 사용하여 개인적으로 정당화 할 수 있는지 여부는 귀하에게 달려 있습니다. 어떤 사람들에게는 악이 너무 커서 그것을 정당화 할 수 없으며 다른 사람들에게는 eval ()이 편리한 지름길입니다.

그러나 eval ()을 악하다고 생각하면 항상 악합니다. 상황에 따라 마술처럼 악을 잃지 않습니다.


이 경우 사용자가 테이블에 임의의 열을 생성 할 수없는 한 eval은 충분히 안전 할 수 있습니다.

그래도 더 이상 우아하지는 않습니다. 이것은 기본적으로 텍스트 구문 분석 문제이며 처리하기 위해 PHP의 구문 분석기를 남용하는 것은 약간 엉망인 것처럼 보입니다. 언어 기능을 남용하려면 JSON 파서를 남용하지 않는 이유는 무엇입니까? 적어도 JSON 파서에서는 코드 삽입의 가능성이 전혀 없습니다.

$json = str_replace(array(
    'enum', '(', ')', "'"), array)
    '',     '[', ']', "'"), $type);
$result = json_decode($json);

정규식이 아마도 가장 확실한 방법 일 것입니다. 단일 정규식을 사용하여이 문자열에서 모든 값을 추출 할 수 있습니다.

$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];

eval 내에서 외부 데이터 (예 : 사용자 입력)를 사용하는 경우.

위의 예에서 이것은 문제가 아닙니다.


eval() 느리지 만 나는 그것을 악이라고 부르지 않을 것입니다.

It's the bad use we make of it that can lead to code injection and be evil.

A simple example:

$_GET = 'echo 5 + 5 * 2;';
eval($_GET); // 15

A harmlful example:

$_GET = 'system("reboot");';
eval($_GET); // oops

I would advise you to not use eval() but if you do, make sure you validate / whitelist all input.


i'll blatantly steal the content here:

  1. Eval by its nature is always going to be a security concern.

  2. Besides security concerns eval also has the problem of being incredibly slow. In my testing on PHP 4.3.10 its 10 times slower then normal code and 28 times slower on PHP 5.1 beta1.

blog.joshuaeichorn.com: using-eval-in-php


Personally, I think that code's still pretty evil because you're not commenting what it's doing. It's also not testing its inputs for validity, making it very fragile.

I also feel that, since 95% (or more) of uses of eval are actively dangerous, the small potential time saving that it might provide in other cases isn't worth indulging in the bad practice of using it. Plus, you'll later have to explain to your minions why your use of eval is good, and theirs bad.

And, of course, your PHP ends up looking like Perl ;)

There are two key problems with eval(), (as an "injection attack" scenario):

1) It may cause harm 2) It may simply crash

and one that's more-social-than-technical:

3) It'll tempt people to use it inappropriately as a shortcut elsewhere

In the first case, you run the risk (obviously, not when you're eval'ing a known string) of arbitrary code execution. Your inputs may not be as known or as fixed as you think, though.

More likely (in this case) you'll just crash, and your string will terminate with a gratuitously obscure error message. IMHO, all code should fail as neatly as possible, failing which it should throw an exception (as the most handleable form of error).

I'd suggest that, in this example, you're coding by coincidence rather than coding to behaviour. Yes, the SQL enum statement (and are you sure that field's enum? - did you call the right field of the right table of the right version of the database? Did it actually answer?) happens to look like array declaration syntax in PHP, but I'd suggest what you really want to do is not find the shortest path from input to output, but rather tackle the specified task:

  • Identify that you have an enum
  • Extract the inner list
  • Unpack the list values

Which is roughly what your option one does, but I'd wrap some if's and comments around it for clarity and safety (eg, if the first match doesn't match, throw exception or set null result).

There are still some possible issues with escaped commas or quotes, and you should probably unpack the data then de-quote it, but it does at least treat data as data, rather than as code.

With the preg_version your worst outcome is likely to be $result=null, with the eval version the worst is unknown, but at least a crash.


I'd also pay some consideration to people maintaining your code.

eval() isn't the easiet to just look at and know what is supposed to happen, your example isn't so bad, but in other places it can be a right nightmare.


eval() is always evil.

  • for security reasons
  • for performance reasons
  • for readability / reusability reasons
  • for IDE / tool reasons
  • for debugging reasons
  • there is always a better way

eval evaluates a string as code, the problem with that is if the string is in any way "tainted" it could expose huge security threats. Normally the problem is in a case where user input is evaluated in the string in many cases the user could input code (php or ssi for example) that is then run within eval, it would run with the same permissions as your php script and could be used to gain information/access to your server. It can be quite tricky to make sure user input is properly cleaned out before handing it to eval. There are other problems... some of which are debatable


PHP advises that you write your code in such a way that it can be executing via call_user_func instead of doing explicit evals.


Another reason eval is evil is, that it could not cached by PHP bytecode caches like eAccelertor or ACP.


It's bad programming that makes eval() evil, not the function. I use it sometimes, as I can not get around it in dynamic programming on multiple sites. I can not have PHP being parsed at one site, as I will not receive the things I want. I would just receive a result! I'm happy a function as eval() exists, as it makes my life much more easy. User-input? Only bad programmers get hooked up by hackers. I don't worry about that.


It's bad programming that makes eval() evil, not the function. I use it sometimes, as I can not get around it in dynamic programming on multiple sites. I can not have PHP being parsed at one site, as I will not receive the things I want. I would just receive a result! I'm happy a function as eval() exists, as it makes my life much more easy. User-input? Only bad programmers get hooked up by hackers. I don't worry about that.

I predict you will have serious problems soon...

In all honesty, there is absolutely no good use for an exorbitant function such as eval, in an interpreted language such as PHP. I have never seen eval perform program functions which could not have been executed using other, safer ways...

Eval is the root of all evil, I wholeheartedly agree, to all people that think that testing user input will help. Think twice, user input can come in many different forms, and as we speak hackers are exploiting that function you didn't care enough about. In my opinion, just avoid eval altogether.

I have seen crafted examples to abuse the eval function that surpassed my own creativity. From a security stance, avoid at all cost, and I would even go as far as to demand it to be at the very least an option in the PHP configuration, rather than a 'given'.


I used to use eval() a lot, but I found most of the cases you don't have to use eval to do tricks. Well, you have call_user_func() and call_user_func_array() in PHP. It's good enough to statically and dynamically call any method.

To perform a static call construct your callback as array('class_name', 'method_name'), or even as simple string like 'class_name::method_name'. To perform a dynamic call use array($object, 'method') style callback.

The only sensible use for eval() is to write a custom compiler. I made one, but eval is still evil, because it's so damn hard to debug. The worst thing is the fatal error in evaled code crashes the code which called it. I used Parsekit PECL extension to check the syntax at least, but still no joy - try to refer to unknown class and whole app crashes.


Here is a solution to running PHP code pulled from a database without using eval. Allows for all in scope functions and exceptions:

$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');

Basically it creates a unique function with the included code in a text file, includes the file, calls the function, then removes the file when done with it. I am using this to perform daily database ingestions/syncronizations where every step requires unique code to handle to process. This has solved all the issues I was facing.


Other than security concerns, eval() cannot be compiled, optimized or opcode cached, thus it will allways be slower -- way slower -- than normal php code. It is thus non-performant to use eval, allthough that doesn't make it evil. (goto is evil, eval is only bad practise/smelly code/ugly)

참고URL : https://stackoverflow.com/questions/951373/when-is-eval-evil-in-php

반응형