Когда оценка является злой в php?

В CodeIgniter 3 появились новые методы group_start () и group_end () , которые служат именно для этой цели.

return $this->db
     ->where('LastName', 'Svendson');
     ->where('Age', 12);
     ->group_start()
         ->where('FirstName','Tove')
         ->or_where('FirstName','Ola')
         ->or_where('Gender','M')
         ->or_where('Country','India')
     ->group_end()
     ->get('Persons')
     ->result();

82
задан Nathaniel Ford 27 February 2014 в 23:02
поделиться

13 ответов

Я бы осторожно назвал eval () чистым злом. Динамическая оценка - мощный инструмент, который иногда может спасти жизнь. С помощью eval () можно обойти недостатки PHP (см. Ниже).

Основными проблемами с eval () являются:

  • Потенциально небезопасный ввод. Передача ненадежного параметра - это способ потерпеть неудачу. Часто бывает нетривиальной задачей убедиться, что параметру (или его части) полностью доверяют.
  • Хитрость. Использование eval () делает код умным, поэтому его труднее отслеживать. Цитируя Брайана Кернигана: « Отладка вдвое сложнее, чем написание кода в первую очередь. Поэтому, если вы напишете код настолько умно, насколько это возможно, вы по определению недостаточно умны, чтобы отлаживать его »

Основная проблема с фактическим использованием eval () только одна:

  • Неопытные разработчики, которые используют его без должного внимания.

Как правило, я придерживаюсь следующего:

  1. Иногда eval () - единственное / правильное решение.
  2. В большинстве случаев следует попробовать что-то еще.
  3. Если не уверены, goto 2.
  4. Иначе, будьте очень-очень осторожны.
129
ответ дан 24 November 2019 в 09:02
поделиться

PHP рекомендует писать код таким образом, чтобы он мог выполняться через call_user_func вместо явных вычислений.

3
ответ дан 24 November 2019 в 09:02
поделиться

eval оценивает строку как код, проблема в том, что если строка каким-либо образом "испорчена", это может привести к огромным угрозам безопасности. Обычно проблема возникает в случае, когда ввод пользователя оценивается в строке, во многих случаях пользователь может ввести код (например, php или ssi), который затем запускается в eval, он будет работать с теми же разрешениями, что и ваш сценарий php, и может использоваться для получения информации / доступа к вашему серверу. Может быть довольно сложно убедиться, что пользовательский ввод правильно очищен, прежде чем передать его eval. Есть и другие проблемы ... некоторые из которых спорны

3
ответ дан 24 November 2019 в 09:02
поделиться

Лично я считаю, что этот код все еще довольно злой, потому что вы не комментируете то, что он делает. Он также не проверяет свои входные данные на достоверность, что делает его очень хрупким.

Я также считаю, что, поскольку 95% (или более) случаев использования eval являются активно опасными, небольшая потенциальная экономия времени, которую он может обеспечить в других случаях, не Не стоит отказываться от плохой практики его использования. Кроме того, позже вам придется объяснять своим миньонам, почему вы используете eval, а их - плохо.

И, конечно же, ваш PHP в конечном итоге выглядит как Perl;)

Есть две ключевые проблемы с eval (), (как сценарий "атаки путем внедрения"):

1) Это может причинить вред 2) Он может просто дать сбой

и тот, который носит скорее социальный, чем технический характер:

3) Он соблазнит людей использовать его ненадлежащим образом в качестве ярлыка в другом месте

В первом случае вы рискуете (очевидно, не когда вы оцениваете известную строку) выполнения произвольного кода. Однако ваши входные данные могут быть не такими известными или фиксированными, как вы думаете.

Скорее всего (в этом случае) вы просто упадете, и ваша строка завершится неоправданно непонятным сообщением об ошибке. ИМХО, весь код должен выходить из строя настолько аккуратно, насколько это возможно, в противном случае он должен вызывать исключение (как наиболее управляемую форму ошибки).

Я бы предположил, что в этом примере вы кодируете случайно, а не кодируете к поведению. Да, оператор перечисления SQL (и вы уверены, что это поле?) s enum? - Вы вызывали правое поле правой таблицы нужной версии базы данных? Действительно ли он ответил?) Выглядит как синтаксис объявления массива в PHP, но я бы посоветовал вам действительно не найти кратчайшего пути от ввода к выводу, а скорее заняться указанной задачей:

  • Определите это у вас есть перечисление
  • Извлечь внутренний список
  • Распаковать значения списка

Это примерно то же самое, что и ваш первый вариант, но я бы обернул некоторые if и комментарии вокруг него для ясности и безопасности (например, если первое совпадение не совпадает, генерирует исключение или устанавливает нулевой результат).

Есть еще некоторые возможные проблемы с экранированными запятыми или кавычками, и вам, вероятно, следует распаковать данные, а затем исключить их из кавычек, но это, по крайней мере, обрабатывает данные как данные, а не как код.

С preg_version ваш худший результат, вероятно, будет $ result = null, с версией eval худший неизвестен, но по крайней мере сбой.

5
ответ дан 24 November 2019 в 09:02
поделиться

Я бы также уделил внимание людям, поддерживающим ваш код.

eval () - это не простой способ просто посмотреть и узнать, что должно произойти, ваш пример не так уж плох, но в других местах он может стать настоящим кошмаром.

4
ответ дан 24 November 2019 в 09:02
поделиться

Я явно украду содержимое здесь:

  1. Eval по своей природе всегда будет проблемой безопасности.

  2. Помимо проблем безопасности, eval также имеет проблему невероятно медленной работы . В моем тестировании на PHP 4.3.10 он в 10 раз медленнее обычного кода и в 28 раз медленнее на PHP 5.1 beta1.

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

7
ответ дан 24 November 2019 в 09:02
поделиться

eval () всегда одинаково злой.

«Когда eval () не злой?» на мой взгляд, это неправильный вопрос, потому что он, кажется, подразумевает, что недостатки использования eval () волшебным образом исчезают в некоторых контекстах.

Использование eval (), как правило, плохая идея, потому что это снижает читабельность кода, возможность предсказать путь кода (и возможные последствия этого для безопасности) до выполнения и, следовательно, возможность отлаживать код. Использование eval () также может предотвратить оптимизацию оцениваемого кода и кода, окружающего его, с помощью кэша кодов операций, такого как Zend Opcache, интегрированного в PHP 5.5 и выше, или JIT-компилятором, например, в HHVM.

Кроме того, , нет ситуации, в которой абсолютно необходимо использовать eval () - PHP является полноценным языком программирования без него.

Считаете ли вы это на самом деле злом или можете ли вы лично оправдать использование eval () в некоторых случаях, зависит от вас. Для некоторых зло слишком велико, чтобы его оправдать, а для других eval () - удобный ярлык.

Однако, если вы видите eval () как зло, это зло всегда. Он не теряет магической злобы в зависимости от контекста.

18
ответ дан 24 November 2019 в 09:02
поделиться

В этом случае 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];
14
ответ дан 24 November 2019 в 09:02
поделиться

Когда вы используете внешние данные (например, пользовательский ввод) внутри eval.

В вашем примере выше это не проблема.

11
ответ дан 24 November 2019 в 09:02
поделиться

eval является злом, когда существует лишь малейшая вероятность того, что ввод пользователя включен в вычисляемую строку. Когда вы выполняете eval без контента, полученного от пользователя, вы должны быть в безопасности.

Тем не менее, вы должны подумать как минимум дважды, прежде чем использовать eval, это выглядит обманчиво простым, но с обработкой ошибок (см. Комментарий VBAssassins), возможностью отладки и т. Д. В помните, это уже не так просто.

Итак, как правило: Забудь об этом. Когда eval - это ответ, вы, вероятно, задаете неправильный вопрос! ; -)

40
ответ дан 24 November 2019 в 09:02
поделиться
begin
  require "some_gem"
rescue LoadError
  puts "message"
end
-121--2889084-

msysgit это, как все говорили, замечательно.

Вы также должны ознакомиться с Git Extensions для интеграции с визуальной студией, без которой я не могу жить.

-121--2207925-

Я часто использовал eval (), но я нашел большинство случаев, когда вам не нужно использовать eval, чтобы делать трюки. Ну, у вас есть call_user_func () и call_user_func_array () в PHP. Достаточно хорошо статически и динамически вызывать любой метод.

Для выполнения статического вызова создайте обратный вызов как массив («class _ name», «method _ name») или даже как простую последовательность, например «class _ name:: method _ name». Для выполнения динамического вызова используйте обратный вызов стиля array ($ object, 'method').

Единственное разумное использование eval () - это запись пользовательского компилятора. Я сделал один, но эвал по-прежнему зло, потому что это чертовски трудно отладить. Хуже всего то, что фатальная ошибка в оцененном коде сбивает код, который его назвал. Я использовал расширение Parsekit PECL, чтобы проверить синтаксис хотя бы, но все же нет радости - попробуйте сослаться на неизвестные сбои класса и всего приложения.

1
ответ дан 24 November 2019 в 09:02
поделиться

Eval () медленно, но я бы не назвал это злом.

Это плохое использование, которое мы сделаем из этого, которое может привести к инъекции кода и будь злым.

Простой пример:

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

Hardful пример:

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

Я бы посоветовал вам не использовать Eval () , но если вы сделаете, убедитесь, что вы проверяете / Whitelist все входные.

11
ответ дан 24 November 2019 в 09:02
поделиться

Еще одна причина EVAL - это зло, что он не может кэшировать кэшированные кэшированные кэширования, такие как EACCELERTOR или ACP.

2
ответ дан 24 November 2019 в 09:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: