Можно ли использовать Perl Marpa Parser для публичного сетевого сервера?

Документация анализатора Perl Marpa содержит следующий раздел о испорченных данных:

Marpa:: R2 существует, чтобы его входные данные могли гибко и эффективно изменять выполнение. Марпа не должен использоваться с ненадежным вводом. В Perl 's taint mode является фатальной ошибкой использовать SLIF-интерфейс Marpa с испорченной грамматикой, испорченной входной строкой или испорченными значениями токенов.

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

Это действительно так? Разве невозможно реализовать какой-либо публичный сетевой сервис с Marpa?

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

Кто-нибудь может объяснить это противоречие?

2 ответа

Решение

Marpa на самом деле безопаснее, чем другие парсеры, потому что язык, который он анализирует, точно соответствует языку, указанному в BNF. С помощью регулярных выражений, PEG и т. Д. Очень трудно определить, какой язык фактически анализируется. На практике программисты обычно работают над несколькими тестовыми примерами, а затем сдаются.

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

Так почему же пугает язык про режим порчи? Marpa, в самом общем случае, можно рассматривать как язык программирования, и у него точно такие же проблемы безопасности. Разрешение пользователю выполнять произвольный код по определению небезопасно, и это именно то, что C, Perl, Marpa и т. Д. Делают намеренно. Вы не можете дать ненадежному пользователю общий языковой интерфейс. Это было бы понятно для C, Python и т. Д., Но я подумал, что кто-то может пропустить это в случае с Marpa. Отсюда и страшный язык.

Марпа ИМХО более безопасен, чем конкурирующие технологии. Однако в наиболее общем случае это недостаточно безопасно.

taint mode это необязательный параметр Perl, который говорит - обрабатывать ввод пользователя как ненадежный. Он останавливает использование любых "испорченных" переменных - таких, которые читаются непосредственно из STDIN или же ENV в определенных функциях, потому что это опасно.

Типичным примером являются эксплойты внедрения кода: Подвиги мамы

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

развязка - это просто - все, что вам нужно сделать, это применить фильтр регулярных выражений к исходным данным, чтобы исключить любые "опасные" метасимволы. (Следует отметить - perl на самом деле не знает, что является "опасным", а что нет - подразумевается, что вы не идиот и просто "подбираете" все)

Это будет ошибка:

#!/usr/bin/env perl -T
use strict;
use warnings;

my $tainted = $ENV{'USERNAME'};
system ( "echo $tainted" );

Потому что я передаю ненадежную переменную в "систему", и она может иметь встроенный код.

Небезопасная зависимость в системе при работе с ключом -T в

(Это может также жаловаться на небезопасный путь)

Так что, чтобы развязать, мне нужно продезинфицировать. Разумная дезинфекция будет такой: имя пользователя должно быть только буквенно-цифровым:

#!/usr/bin/env perl -T
use strict;
use warnings;

$ENV{'PATH'} = '/bin'; # an untainted value 

my $tainted = $ENV{'USERNAME'};
my ( $untainted ) = $tainted =~ m/(\w+)/g;
system ( "echo $untainted"); # no error now

И поскольку я использовал регулярное выражение - Perl предполагает, что я не сделал что-то с головой (.*)) и, таким образом, считает данные незапятнанными.

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

В вашем конкретном случае:

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

  • Фильтрация HTML для проверки длины и набора символов, вероятно, имеет смысл. Например - проверка "ascii-совместимой кодировки символов".

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

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

Другие вопросы по тегам