Pull to refresh

Интересная ошибка Perl-разработчика

Reading time 2 min
Views 1.2K
Представим, что у вас есть код:
  1. chomp(my $input = <STDIN>);
  2. my $kinda_secret = get_data($input);
  3. if(defined $kinda_secret) {
  4.  print 'Your secret is: ', $kinda_secret
  5. }
  6. else {
  7.  print 'No soup for you'
  8. }
  9.  
  10. sub get_data {
  11.  my $input = shift;
  12.  open my $fh, '<', 'data.file' or return;
  13.  my $retval;
  14.  while(<$fh>) {
  15.   if(/^$input:(.+?)$/) {
  16.    $retval = $1;
  17.    last
  18.   }
  19.  }
  20.  close $fh;
  21.  
  22.  $retval
  23. }
* This source code was highlighted with Source Code Highlighter
.

Ничего экзотичного. Вариации такого кода могут встретиться где угодно. Смысл кода, надеюсь, ясен (я не имею в виду его практическую ценность).

Вы уже увидели ошибку? Если да, то дальше можно не читать.

А я, признаться, не сразу понял в чем дело( Вот наглядный пример:

ksurent@desktop:~> cat data.file 
password1:hello1
password2:hello2
ksurent@desktop:~> perl -l t.pl
password1
Your secret is: hello1
ksurent@desktop:~> perl -l t.pl
password
No soup for you
ksurent@desktop:~> perl -l t.pl
.+
Your secret is: hello1
ksurent@desktop:~> 


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

Безопасный выход конечно же есть: метасимволы \Q и \E. \Q отключает интерпретирование метасиволов вплоть до \E (или до конца регулярного выражения, если \E опущен).
Возьмите за правило обрамлять переменные с непроверенными данными в \Q\E при подставновке в регулярки.

Небольшое дополнение


Практической ценности не несет в силу очень экзотических условий для выполнения. Просто интересно.
Представим, что по какой-то причине в скрипте оказалось строчка
use re 'eval';
. Ну мало ли, например, используются где-то сложные динамические регулярки. Это приведет аж к внедрению кода:
ksurent@desktop:~> perl -l t.pl
(??{system'id'})
uid=1000(ksurent) gid=100(users) группы=16(dialout),33(video),100(users)
uid=1000(ksurent) gid=100(users) группы=16(dialout),33(video),100(users)
No soup for you
ksurent@desktop:~>

Вот такие дела. Благо разработчики интерпретатора предвидели это: по умолчанию такие вещи не прокатывают. Но! Даже если
use re 'eval';
в скрипте нет, то можно получить небольшой кусок кода, что тоже не сыграет разработчику на руку.

ksurent@desktop:~> perl -l t.pl
(??{system'id'})
Eval-group not allowed at runtime, use re 'eval' in regex m/^(??{system'id'}):(.+?)$/ at t.pl line 15, <$fh> line 1.
ksurent@desktop:~>
Tags:
Hubs:
+19
Comments 12
Comments Comments 12

Articles