Должен ли я использовать eval () или call_user_func ()? - PullRequest
5 голосов
/ 19 марта 2009

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

Например, если я выбрал код «myfunc (1,2,3); anotherFunc (3,2,1);»
Я могу выполнить eval () непосредственно для запуска кода.

Но для call_user_func () мне пришлось бы проанализировать строку, чтобы ее можно было запустить. Так какую же функцию лучше использовать в этом случае?

Ответы [ 6 ]

4 голосов
/ 20 марта 2009

Хранение PHP в базе данных само по себе является неприятным запахом дизайна; даже если в этом случае вы почти уверены, что он никогда не будет содержать небезопасный код, всегда полезно минимизировать количество предположений или защитных мер, которые вы должны сделать. Если вы храните код PHP в базе данных, то атака, при которой злоумышленник получает доступ к вашей базе данных, быстро становится намного более серьезной, превращаясь в атаку, в которой злоумышленник может выполнить произвольный код! Я знаю, что подобная компрометация вашей базы данных крайне маловероятна, но, тем не менее, это хорошая практика безопасности, которая не позволяет даже маловероятной ситуации скомпрометировать вашу систему больше, чем нужно.

Многие люди соглашаются , что eval () следует всегда без исключения избегать в коде PHP. Всегда есть альтернатива.

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

Я бы, однако, рекомендовал

  1. Вы пытаетесь проверить код перед тем, как его выполнять (eval ()), проявляя осторожность в том, что разрешаете. Предположим, что злоумышленник каким-то образом проник в вашу базу данных, даже подумав, что это маловероятно.
  2. По крайней мере, вы серьезно задумываетесь о переписывании приложения, чтобы код PHP не сохранялся в базе данных. Если вы храните сложные структуры данных, подумайте о чем-то вроде JSON или даже XML. Для них существуют безопасные парсеры.

Извините, если этот ответ кажется немного реакционным; Мне просто кажется, что такие вещи очень важны.

2 голосов
/ 19 марта 2009

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

Вы говорите «Нет вероятности, что небезопасный код будет введен» , поэтому большой вопрос: есть ли вероятность того, что неработающий код окажется в базе данных?

Если нет, то eval () - это решение, но при наличии правильного синтаксического анализа и регистрации ошибок / etc может быть более безопасная ставка. (Я полагаю, что использование call_user_func_array () быстрее в теории, поэтому любые издержки синтаксического анализа могут стать незначительными)

1 голос
/ 19 марта 2009

Возможно, вы захотите взглянуть на расширение runkit , которое может запускать php в песочнице, не влияя на выполняемый код.

Если предполагается, что код влияет на ваш работающий код, перейдите к eval ().

1 голос
/ 19 марта 2009

Используйте eval (). Все остальное не стоит усилий - они не будут иметь никаких положительных побочных эффектов.

1 голос
/ 19 марта 2009

Я бы подумал, что синтаксический анализ привел бы к дополнительным издержкам, но единственный способ убедиться в этом - запустить его тестирование. Попробуйте оба способа с различными функциями и посмотрите, каковы ваши результаты. Используйте код, который представляет то, что вы ожидаете сохранить.

Удачи!

0 голосов
/ 20 марта 2009

Вы должны также обернуть код, который собираетесь запустить, в блок try / catch на случай, если возникнет ошибка (даже если вы сказали, что этого не произойдет, такая возможность есть, и это лучшая практика)

...