Защита ввода пользователем регулярных выражений от атак

9

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

icirellik
источник
Вам не хватает деталей. Платформа, использование и т. Д.
whatsisname
8
Вместо того, чтобы пытаться избежать того, чтобы пользователь отправлял неправильное регулярное выражение, возможно, решение, при котором после определенного периода времени вы отменяете выполнение?
Самуил

Ответы:

8

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

Регулярные выражения концепции компьютерных наук всегда могут быть сопоставлены в линейном времени после их компиляции в конечный автомат. Таким образом, механизм регулярных выражений на основе конечного автомата не может быть использован для ReDoS. Однако необходимые патологические машины могут стать довольно большими в патологических примерах. Но ограничение доступной памяти обычно проще, чем ограничение доступного времени вычислений.

Двигатель RE2 был разработан специально для борьбы с ненадежными регулярными выражениями и предназначен для выполнения линейного времени.

Другой альтернативой является сборка регулярных выражений самостоятельно из упрощенной записи. Например, вы можете разрешить пользователям использовать шаблоны глобуса (например *.txt). Затем вы можете проанализировать это таким образом, чтобы предотвратить возврат, например, запретив вложение и используя только жадные квантификаторы. Для многих случаев использования вполне достаточно упрощенной системы обозначений.

Амон
источник
11

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

Можно, конечно, найти решение , которое является правильным и в комплекте. Например, вы можете работать с ограниченным белым списком функций, которые безопасно использовать (например, классы символов да, повторение нет ...). Это позволит вам пропустить множество некритических регулярных выражений, отвергнуть все критические и (ошибочно) отклонить те, которые в порядке, но слишком сложные, чтобы автоматически оказаться безопасными.

Килиан Фот
источник
3
У вас есть цитата для вашего первого заявления? Мне было бы интересно увидеть такое доказательство. Регулярные выражения не являются полными по Тьюрингу, поэтому проблема остановки может не применяться.
Себастьян Редл
3
@SebastianRedl Это правда, что, строго говоря, регулярные выражения не являются полными по Тьюрингу, но все популярные библиотеки регулярных выражений имеют расширения, которые делают их более не регулярными. Ограничение ваших пользователей буквально регулярными выражениями может быть хорошим решением в этой ситуации.
Килиан Фот
2
@KilianFoth: IIRC, даже истинные регулярные выражения (в смысле слова CompSci) могут потребовать экспоненциального количества возвратов. Но поскольку они не полны по Тьюрингу, для любого заданного регулярного выражения теоретически возможно установить эту верхнюю границу. Однако это оставляет открытыми две проблемы: автоматическое определение верхней границы является нетривиальной задачей, и результат может дать неоправданно высокие результаты (например, верхняя граница намного выше, чем ожидаемое время).
MSalters
@msalters любое истинное регулярное выражение механически преобразуется в детерминированный конечный автомат, т. е. всегда можно найти выражение без обратного отслеживания. Конечно, ваш FSA может стать неоправданно большим, но это говорит о том, что ограничение количества состояний в сгенерированном FSA является достаточным решением для предотвращения рассматриваемой атаки.
Жюль
1

Как автор re reser для проекта lazarus, я бы сказал, что нет никаких способов понять для какого-либо данного регулярного выражения, какие ресурсы он будет использовать для данного текста.

Не тратя те же самые ресурсы, которые я имею в виду (по крайней мере, в значении big-O).

Поэтому лучший подход - запускать re parser в отдельном потоке и уничтожать его по истечении времени ожидания.

ANDgineer
источник
0

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

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

как зовут
источник