Как позволить пользователю безопасно вводить функцию JavaScript? - PullRequest
2 голосов
/ 22 марта 2011

Я занимаюсь созданием генератора таблиц правды. Используя функцию, предоставленную пользователем (например, a && b || c), я пытаюсь заставить JavaScript отображать все комбинации a, b и c с результатом функции.

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

eval() не является безопасным; ни один из них не является new Function(), так как оба могут заставить пользователя по своему усмотрению поместить все в функцию. Обычно JSON.parse() является отличной альтернативой eval(), однако функции не существуют в JSON.

Поэтому мне было интересно, как я могу разобрать пользовательскую строку логического оператора, такую ​​как a && b || c, в функцию, в то время как любые строки вредоносного кода игнорируются. Внутри функции должны быть разрешены только логические операторы (&&, ||, !).

Ответы [ 4 ]

1 голос
/ 22 марта 2011

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

1 голос
/ 22 марта 2011

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

Так, скажем, разбейте строку "a &! B" на последовательность токенов "a" "&" "!" «b», затем пройдитесь и (в конце концов) создайте что-то вроде: booland (boolvar («a»), boolnot (boolvar («b»)))), и у вас будет подходящая структура данных для запуска вашей (пользовательской, мы надеемся, инъекции Бесплатно) оценщик закончен.

1 голос
/ 22 марта 2011

Даже если вы проверите логические выражения, я мог бы сделать это:

(a && b && (function() { ruinYourShit(); return true; })())

Это показывает, что ваша проблема не решаема в общем случае.

Чтобы это работало в вашей ситуации, вы должны наложить жесткие ограничения на именование переменных, например, требовать, чтобы все переменные представляли собой одну букву алфавита, а затем использовать регулярное выражение, чтобы отбросить его, если что-то еще будет найдено. Кроме того, чтобы «соответствовать» булевому выражению, вам фактически нужно разработать грамматику для этого выражения. Вы пытаетесь проанализировать нерегулярный язык (javascript), и поэтому вы не можете написать регулярное выражение, которое могло бы соответствовать любому возможному логическому выражению произвольной сложности. По сути, проблема, которую вы пытаетесь решить, очень, очень сложная.

Если вы не ожидаете, что мир рухнет, если кто-то испортит ваше дерьмо, вы можете разработать достаточно хорошее решение , просто проверив ключевое слово function и запретив любые блоки логического кода содержится в { и }.

0 голосов
/ 22 марта 2011

Я получил регулярное выражение:

if(!/^[a-zA-Z\|\&\!\(\)\ ]+$/.test(str)) {
   throw "The function is not a combination of Boolean operators.";
   return;
}
...