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

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

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

Я буду использовать библиотеку Regex в .NET(С#).

Ответ 1

Проблемы, связанные с отказом в обслуживании

Наиболее распространенная проблема с регулярными выражениями - атака типа "отказ в обслуживании" через патологические шаблоны, которые экспоненциальны или даже суперэкспоненциальны! - и поэтому, похоже, навсегда нужно решить. Они могут отображаться только на определенных входных данных, но обычно можно создать один, в котором это не имеет значения.

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

Russ Coxs превосходная статья 2007 года на Регуляция регулярных выражений может быть простой и быстрой (но медленный в Java, Perl, PHP, Python, Ruby,...) рассказывает о том, как большинство современных NFA, которые, как представляется, происходят из кода Генри Спенсера, страдают серьезной деградацией производительности, но там, где Томпсон -style NFA не имеет таких проблем.

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

С DFA вы тратите больше времени на его создание (и выделяете больше состояний), тогда как с NFA вы тратите больше времени на его выполнение, так как это может быть несколько состояний одновременно, и откат может съесть ваш обед - и ваш процессор.

Решения для отказа в обслуживании

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

Существуют различные способы их реализации, начиная с простого alarm(N) на уровне C, до какого-либо try {} блокирует исключения исключений типа тревоги, вплоть до создания нового потока, специально созданного с ограничением по времени, встроенным в него.

Выноски кода

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

Например, в Perl нельзя иметь выноски кода в регулярных выражениях, созданных из строковой интерполяции (как это было бы, как они были скомпилированы во время выполнения), если только специальная лексически-ограниченная прагма use re "eval"; не активна в текущей области.

Таким образом, никто не может прокрасться в выноску кода для запуска системных программ, например, rm -rf *. Поскольку выноски кода настолько чувствительны к безопасности, Perl отключает их по умолчанию во всех интерполированных строках, и вам нужно уйти с пути, чтобы повторно активировать их.

Пользовательский \P {roperties}

Остается еще одна проблема с безопасностью, связанная со свойствами стиля Unicode - например, \pM, \p{Pd}, \p{Pattern_Syntax} или \p{Script=Greek} - которые могут существовать в некоторых компиляторах, которые поддерживают эту нотацию.

Проблема в том, что в некоторых из них набор возможных свойств расширяется пользователем. Это означает, что вы можете иметь настраиваемые свойства, которые являются фактическими выносками кода для названных функций в определенном пространстве имен, например \p{GoodChars} или \p{Class::Good_Characters}. Как ваш язык справляется с тем, на что стоит обратить внимание.

Песочница

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

Ответ 2

Добавление в tchrist отличного ответа: тот же Russ Cox, который написал страницу "Regular Expression", также выпустил код! re2 - это библиотека С++, которая гарантирует время выполнения O (length_of_regex) и настраиваемый лимит использования памяти. Он используется в Google, так что вы можете ввести регулярное выражение в поиск кода Google - это означает, что он был проверен на битву.

Ответ 4

Вы хотите прочитать эту статью:

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

Ответ 5

Вы должны не только беспокоиться о совпадении, но и о том, как вы выполняете сопоставление. Например, если ваш вход проходит через какую-либо фазу eval или подстановку команд на пути к движку регулярных выражений, может быть код, который выполняется внутри шаблона. Или, если ваш синтаксис регулярных выражений позволяет встроенным командам, вы также должны быть осторожны с этим. Поскольку вы не указали язык в своем вопросе, трудно сказать точно, каковы все последствия для безопасности.

Ответ 6

Хорошим способом протестировать ваш RegEx для проблем безопасности (по крайней мере для Windows) является SDL RegEx fuzzing tool, выпущенный недавно Microsoft. Это может помочь избежать патологически плохой конструкции RegEx.