Как я могу безопасно использовать регулярные выражения из пользовательского ввода?

My (Perl-based) приложение должно позволить пользователям вводить регулярные выражения, чтобы соответствовать различным строкам за кулисами. Мой план до сих пор заключался в том, чтобы взять строку и обернуть ее чем-то вроде

$regex = eval { qr/$text/ };
if (my $error = [email protected]) { 
   # mangle $error to extract user-facing message

($text был лишен новых строк раньше времени, поскольку на самом деле это несколько регулярных выражений в многострочном текстовом поле, которое я split).

Есть ли какие-либо потенциальные угрозы безопасности при этом - какой-то странный вклад, который может привести к произвольному выполнению кода? (Помимо переполнения буфера переполнения в механизмах регулярных выражений, таких как CVE-2007-5116). Если да, можно ли их смягчить?

Есть ли лучший способ сделать это? Любые модули Perl, которые помогают абстрагировать операции включения пользовательского ввода в регулярные выражения (например, извлечения сообщений об ошибках... или предоставления модификаторов, таких как /i, которые мне здесь не нужны, но было бы хорошо)? Я искал CPAN и не нашел много того, что было многообещающе, но развлекал возможность, что я что-то пропустил.

Ответ 1

С конструкцией (?{ code }) пользовательский ввод может использоваться для выполнения произвольного кода. См. Пример в perlre#code и где он говорит

local $cnt = $cnt + 1,

замените его выражением

system("rm -rf /home/fennec"); print "Ha ha.\n";

(На самом деле, не делайте этого.)

Ответ 2

Использование ненадежного ввода как регулярного выражения создает уязвимость отказа в обслуживании, как описано в perlsec:

Регулярные выражения - Механизм регулярных выражений Perl называется так называемым NFA (недетерминированный конечный автомат), который среди прочего            означает, что он может довольно легко потреблять большие количества времени и пространства, если регулярное выражение может совпадать несколькими способами.            Тщательное создание регулярных выражений может помочь, но довольно часто там действительно мало что можно сделать (книга "Mastering Regular"            Выражения "необходимо прочитать, см. Perlfaq2). Запуск из пространства проявляется у Perl, заканчивающегося из памяти.

Ответ 3

лучший способ - не позволить пользователям иметь слишком много привилегий. Предоставьте интерфейс, достаточный для того, чтобы пользователи могли делать то, что им нужно. (например, банкомат с только кнопками для различных опций, без ввода клавиатуры). Конечно, если вам нужен пользователь для ввода ввода, затем укажите текстовое поле, а затем на задней панели, используйте Perl для обработки запроса (например, для дезинфекции и т.д.). Мотивом, позволяющим пользователям вводить регулярное выражение, является поиск правильных шаблонов строк? Тогда в этом случае самым простым и безопасным способом является указание им вводить только строку. Затем на заднем конце вы используете регулярное выражение Perl для его поиска. Есть ли какая-либо другая веская причина для регулярного ввода пользовательского ввода?

Ответ 4

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

Я не пробовал, но есть PCRE для perl. Вы также можете ограничить или удалить поддержку кода, используя эту информацию о создании настраиваемых механизмов регулярного выражения.

Ответ 5

Об этом обсуждается в Монастырь.

TL;DR: используйте re:: engine:: RE2 (-strict = > 1);

Убедитесь, что в add (-strict = > 1) используется оператор use или re:: engine:: RE2 вернется к perl re.

Ниже приведена quote от junyer, владельца проекта на github.

RE2 был разработан и реализован с явной целью - обеспечить возможность обработки регулярных выражений от ненадежных пользователей без риска. Одна из его основных гарантий заключается в том, что время совпадения является линейным по длине входной строки. Это также было написано с учетом производственных соображений: синтаксический анализатор, компилятор и механизмы исполнения ограничивают использование их памяти, работая в настраиваемом бюджете - изящно изящно при исчерпании - и избегают, избегая рекурсии.

Старая информация:
Подводя итог важным моментам. Он безопасен от произвольного выполнения кода по умолчанию, но добавляет "no re 'eval"; предотвратить PERL5OPT или что-нибудь еще? от установки его на вас. Я не уверен, если это предотвратит все.

Используйте подпроцесс (fork) с BSD:: Resource (даже в Linux), чтобы удалить память и убить ребенка через некоторое время.