На каких языках использовать дыру в безопасности с помощью пользовательских регулярных выражений? - PullRequest
12 голосов
/ 27 ноября 2010

Редактировать: tchrist сообщил мне, что мои первоначальные обвинения в небезопасности Perl являются необоснованными.Однако вопрос все еще стоит.

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

Ответы [ 8 ]

17 голосов
/ 27 ноября 2010

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

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

Для получения дополнительной информации читайте эту страницу: http://www.regular -expressions.info / catastrophic.html

6 голосов
/ 27 ноября 2010

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

use re "eval";

, если вы ожидаете, что интерполяция и экранирование кода происходят в одном и том же шаблоне.

Часы:

% perl -le '$x = "(?{ die 'naughty' })"; "aaa" =~ /$x/'
Eval-group not allowed at runtime, use re 'eval' in regex m/(?{ die naughty })/ at -e line 1.
Exit 255

% perl -Mre=eval -le '$x = "(?{ die 'naughty' })"; "aaa" =~ /$x/'
naughty at (re_eval 1) line 1.
Exit 255
2 голосов
/ 27 ноября 2010

1) Уязвимости обнаруживаются в библиотеках регулярных выражений, таких как переполнение буфера , которое затрагивает Webkit и позволяет любому злоумышленнику получить удаленное выполнение кода, получив доступ к библиотеке регулярных выражений из JavaScript.

2) Это условие DoS в C #.

3) Предоставленные пользователем регулярные выражения могут быть для php из-за модификаторов.Добавление модификатора / e устраняет совпадение.В этом случае система будет eval () 'ed.

preg_replace("/.*/e","system('echo /etc/passwd')");

Или в виде уязвимости:

preg_replace($_GET['regex'],$_GET['check']);

2 голосов
/ 27 ноября 2010

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

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

1 голос
/ 08 апреля 2019

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

В случае с Regex это может быть ReDos: Regex Denial of Service.По сути, регулярное выражение, которое потребляет чрезмерное количество процессора и памяти для обработки.

Например: если вы попытаетесь оценить это регулярное выражение

^(([a-z])+.)+[A-Z]([a-z])+$

на этом входе:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!

вы заметите, что оно может зависнуть - это называется катастрофическим возвратом,Убедитесь сами здесь: https://regex101.com/r/Qhn3Vb/1

Подробнее о Regex DoS: https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS


Итог: никогда не думайте, что ввод пользователя безопасен!

1 голос
/ 27 ноября 2010

Я подозреваю, что ruby ​​позволит /#{system("rm -rf really_important_directory")}/ - это то, о чем вы беспокоитесь?

1 голос
/ 27 ноября 2010

Регулярные выражения являются языком программирования. Я не думаю, что они достаточно полны по Тьюрингу, но они достаточно близки, чтобы позволить вашим пользователям вводить их на ваш веб-сайт, что позволяет другим людям запускать код на вашем сервере. КЭД, да, это дыра в безопасности.

Возможно, вам удастся уйти с разрешением подмножества любого языка регулярных выражений, который вы хотите использовать, внесения в белый список определенного набора конструкций, чтобы сделать его дырой не слишком большой, чтобы потеть ... другие уже упомянул возможные гибели гнездования и *. Насколько вы готовы позволить людям загружать ваш сервер, зависит только от вас. Лично мне было бы удобно позволить им иметь один SQL-оператор «CONTAINS» и, возможно, «BETWEEN ()». :)

0 голосов
/ 27 ноября 2010

AFAIK, вы можете сделать это безопасно в C #: вы можете передать строку регулярного выражения в конструктор Regex, и если он не сможет разобрать, он выдаст.Я не уверен в других.

...