Безопасно ли читать регулярные выражения из файла? - PullRequest
12 голосов
/ 28 октября 2008

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

Кроме того, есть ли способ проверить, является ли указанное регулярное выражение действительным, прежде чем его реально использовать? Я хотел бы выдавать предупреждения, если было введено что-то вроде /foo (bar/.

Спасибо, З.


EDIT:
Спасибо за очень интересные ответы. С тех пор я обнаружил, что следующие опасные конструкции будут оцениваться в регулярных выражениях только при использовании прагмы use re 'eval':
(?{code})
(??{code})
${code}
@{code}

По умолчанию no re 'eval'; поэтому, если я что-то упускаю, то можно безопасно читать регулярные выражения из файла, единственной проверкой является eval / catch, отправленный Axeman. По крайней мере, я не смог спрятать в них ничего злого в своих тестах.

Еще раз спасибо. Z.

Ответы [ 5 ]

13 голосов
/ 28 октября 2008

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

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

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

11 голосов
/ 28 октября 2008

Это

eval { 
    qr/$re/;
};
if ( $@  ) { 
    # do something
}

компилирует выражение и позволяет вам восстановиться после ошибки.

Вы можете следить за вредоносным выражением, поскольку вы будете только сопоставлять, ища следующие шаблоны, которые позволят выполнить произвольный код:

(?: \( \?{1,2} \{  # '(' followed by '?' or '??', and then '{'
|   \@ \{ \s* \[   # a dereference of a literal array, which may be arbitrary code.
)

Убедитесь, что вы скомпилировали это с флагом x.

5 голосов
/ 28 октября 2008

Я бы предложил не доверять регулярным выражениям пользователей. Если вы действительно решили это сделать, пожалуйста, запустите perl в режиме taint (-T). В этом случае вам понадобится некоторая форма проверки. Вместо того, чтобы использовать Parse :: RecDescent для написания вашего собственного парсера регулярных выражений, как предлагает другой ответ, вы должны использовать существующий парсер YAPE :: Regex regexp, который, вероятно, быстрее, был написан экспертом и работает как очарование.

Наконец, начиная с perl 5.10.0, вы можете подключать различные механизмы регулярных выражений к perl (лексически!). Вы можете проверить, существует ли менее мощный механизм регулярных выражений, синтаксис которого легче проверить. Если вы хотите пойти по этому пути, прочитайте описание API , Avar's re :: engine :: Plugin , или вообще проверьте любой из модулей плагинов Avar .

5 голосов
/ 28 октября 2008

Вам, вероятно, придется провести некоторый уровень дезинфекции. Например, справочная страница perlre описывает следующую конструкцию:

(?{ code })

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

0 голосов
/ 28 октября 2008

Может ли модуль Safe быть полезным для компиляции / выполнения ненадежных регулярных выражений?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...