2012-06-17 5 views
4

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

Вот что я собрал:

  • Не используйте Eval для строк (это может быть проблемой, так как она является формула мне нужно разобрать)
  • Strip вход приходит от формы (я не совсем уверен, что вещи, которые я должен раздеться)
  • Eval может или не может быть злым, и представляет собой угрозу безопасности (есть альтернативы для разбора уравнения в строке?)

Что вы думаете, что я должен делать?

EDIT: Я пробовал метод eval, и, хотя он работает, санитария, которую я использовал, не поддерживала более двух операндов. Поскольку мне действительно не хочется писать собственное (возможно, небезопасное) решение для санитарии, я просто собираюсь найти и использовать предварительно написанный математический класс. Спасибо всем за предложения!

+3

Какая формула? Формула PHP? Можете ли вы привести примеры возможных формул? –

+1

Для математических выражений вы могли бы запустить ввод с регулярным выражением, например '^ [0-9 - +/\ *% \^\ (\)] + $'. Это позволит использовать математические выражения типа «1 - (2 * 3 + 1/(2^(11% 4))), но не будет допускать' $ ', символы, символы подчеркивания,' :: ',' ​​-> 'и т. д., что предотвращает использование переменных, функций и классов. –

+0

Примером ожидаемой формулы будет «% U% +% B% -% P%», где все внутри знака процента - это число, загруженное сервером. –

ответ

3

Если вы должны использовать eval, на странице eval docs на нем есть код, который позволит вам фильтровать математические формулы. Однако, как и другие, и страница документов PHP, сказали, что не рекомендуется использовать eval, если нет другой альтернативы.

<?php 

$test = '2+3*pi'; 

// Remove whitespaces 
$test = preg_replace('/\s+/', '', $test); 

$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number 
$functions = '(?:sinh?|cosh?|tanh?|abs|acosh?|asinh?|atanh?|exp|log10|deg2rad|rad2deg|sqrt|ceil|floor|round)'; // Allowed PHP functions 
$operators = '[+\/*\^%-]'; // Allowed math operators 
$regexp = '/^(('.$number.'|'.$functions.'\s*\((?1)+\)|\((?1)+\))(?:'.$operators.'(?2))?)+$/'; // Final regexp, heavily using recursive patterns 

if (preg_match($regexp, $q)) 
{ 
    $test = preg_replace('!pi|π!', 'pi()', $test); // Replace pi with pi function 
    eval('$result = '.$test.';'); 
} 
else 
{ 
    $result = false; 
} 

?> 
+0

Формула будет выглядеть примерно так: «% U% +% B% -% P%», а сервер будет загружать числа вместо%%%. Метод, описанный выше (без некоторых бит, которые не нужны) будет работать хорошо. –

+0

Спасибо за ваше предложение! Я собираюсь использовать его сейчас. –

4

Использование EVAL на входе пользователя - отличный способ получить доступ к вашему серверу. Не.

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

+0

Спасибо за ваше предложение! –

0

eval всегда опасно. Как только вы начнете черный список (фильтрацию), люди найдут способы обойти допущения, которые вы делаете в своей логике фильтра. Белые списки действительных выражений - это более безопасный способ.

Но самый эффективный способ защиты от кого-либо, злоупотребляющего функциональностью, - это, вероятно, написать правильный парсер для математических выражений. Если формулы, которые вы хотели бы поддержать, не слишком сложны, это даже не та часть сделки, если вы используете простой метод парсера с реверсивным спусками сверху вниз. У этого answer есть несколько ссылок, чтобы вы начали. Также есть this article, который разрабатывает рекурсивный синтаксический анализатор для простого калькулятора (к сожалению, он находится на Java, хотя).