Подтвердить что ты не робот

Безопасно ли читать регулярные выражения из файла?

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

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

Спасибо, Z.


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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Это

eval { 
    qr/$re/;
};
if ( [email protected]  ) { 
    # do something
}

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

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

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

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

Ответ 3

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

(?{ code })

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

Ответ 4

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

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

Ответ 5

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