Можно ли использовать 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-совместимой кодировки символов".
По сути, хотя я думаю, что вы переосмысливаете, что такое проверка на заражение - это не исчерпывающий метод проверки - это система безопасности. Все, что нужно сделать, - это убедиться, что вы провели некоторую базовую очистку перед передачей пользовательского ввода небезопасному механизму. Это остановит нелепые ошибки, подобные тому, который я обрисовал в общих чертах, - большинство из них можно поймать простым регулярным выражением.
Если вы знаете о проблеме и не беспокоитесь о злонамеренном вводе данных пользователем, я не думаю, что вам нужно слишком беспокоиться. Белый список символов будет достаточно, а затем проанализировать.