perlsec
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ОПИСАНИЕ
- КОНТАКТНАЯ ИНФОРМАЦИЯ ПО ВОПРОСАМ БЕЗОПАСНОСТИ
- МЕХАНИЗМЫ И ВОПРОСЫ БЕЗОПАСНОСТИ
- СМОТРИТЕ ТАКЖЕ
НАЗВАНИЕ
perlsec - Безопасность Perl
ОПИСАНИЕ
Perl разработан для лёгкой разработки защищённых программ, даже при работе с повышенными привилегиями, например, программы setuid или setgid. В отличие от большинства командных оболочек, которые основаны на нескольких проходах по подстановке каждой строки скрипта, Perl использует более традиционную схему вычислений с меньшим количеством скрытых проблем. Кроме того, поскольку язык имеет больше встроенных функций, он меньше полагается на внешние (и, возможно, ненадежные) программы для достижения своих целей.
КОНТАКТНАЯ ИНФОРМАЦИЯ ПО ВОПРОСАМ БЕЗОПАСНОСТИ
Если вы считаете, что обнаружили уязвимость в системе безопасности Perl, пожалуйста, отправьте подробности по электронной почте на адрес perl5-security-report@perl.org. Это создаст новый билет в системе Request Tracker в специальной очереди, которая поначалу не доступна публично. Почта также будет скопирована на закрытый список рассылки, который не архивируется, и включает всех основных разработчиков, которые смогут помочь оценить влияние проблем, найти решение и согласовать выпуск исправлений для устранения проблем на всех платформах, поддерживающих Perl. Используйте этот адрес только для проблем безопасности в ядре Perl, а не для модулей, независимо распространяемых в CPAN.
При отправке первоначального запроса на адрес электронной почты для сообщений о безопасности не используйте поле Cc для других участников, потому что если они ответят всем, ответ породит еще один новый билет. После получения первоначального ответа с номером билета [perl #NNNNNN] в заголовке, можно использовать Cc в последующих ответах для третьих сторон: все письма на адрес perl5-security-report с номером билета в теме будут добавлены в билет; без него будет создан новый билет.
МЕХАНИЗМЫ И ВОПРОСЫ БЕЗОПАСНОСТИ
Режим taint
Perl автоматически включает набор специальных проверок безопасности, называемых режимом taint, когда обнаруживает, что программа запускается с разными реальными и эффективными идентификаторами пользователя или группы. Флаг setuid в разрешениях Unix имеет значение 04000, а флаг setgid — 02000; может быть установлен один или оба. Вы также можете явно включить режим taint, используя командную строку -T. Этот флаг настоятельно рекомендуется для серверных программ и любых программ, запускаемых от имени другого пользователя, таких как CGI-скрипт. После включения режима taint он остается включённым до конца работы скрипта.
В этом режиме Perl применяет особые меры предосторожности, называемые проверками taint, для предотвращения очевидных и скрытых ловушек. Некоторые из этих проверок достаточно просты, например, проверка того, что каталоги пути не доступны для записи другими пользователями; внимательные программисты всегда использовали такие проверки. Однако другие проверки лучше всего поддерживаются самим языком, и именно эти проверки особенно способствуют тому, что программа Perl с установленным идентификатором более безопасна, чем соответствующая программа на C.
Вы не можете использовать данные, полученные извне вашей программы, для воздействия на что-то вне вашей программы — по крайней мере, не случайно. Все аргументы командной строки, переменные окружения, информация о языке (см. perllocale), результаты определённых системных вызовов (readdir(), readlink(), переменная shmread(), сообщения, возвращённые msgrcv(), пароль, поля gcos и shell, возвращённые функциями getpwxxx()), и все данные ввода из файла помечаются как «заражённые». Заражённые данные нельзя использовать напрямую или косвенно в любой команде, вызывающей дочернюю оболочку, или в любой команде, изменяющей файлы, каталоги или процессы, за исключением следующих случаев:
-
Аргументы
printиsyswriteне проверяются на заражённость. -
Символьные методы
$obj->$method(@args);и символьные ссылки на подпрограммы
&{$foo}(@args); $foo->(@args);не проверяются на заражённость. Это требует повышенной внимательности, если вы не хотите, чтобы внешние данные влияли на ваш поток управления. Если вы не ограничите значения этих символьных переменных, пользователи смогут вызывать функции вне вашего кода Perl, такие как POSIX::system, в результате чего они смогут запускать произвольный внешний код.
-
Ключи словарей никогда не заражены.
По соображениям эффективности Perl придерживается консервативного подхода к определению заражённости данных. Если выражение содержит заражённые данные, любое подвыражение может считаться заражённым, даже если значение подвыражения само по себе не затронуто заражёнными данными.
Поскольку заражённость ассоциируется с каждым скалярным значением, некоторые элементы массива или словаря могут быть заражены, а другие — нет. Ключи словаря никогда не заражены.
Например:
$arg = shift; # $arg is tainted
$hid = $arg . 'bar'; # $hid is also tainted
$line = <>; # Tainted
$line = <STDIN>; # Also tainted
open FOO, "/home/me/bar" or die $!;
$line = <FOO>; # Still tainted
$path = $ENV{'PATH'}; # Tainted, but see below
$data = 'abc'; # Not tainted
system "echo $arg"; # Insecure
system "/bin/echo", $arg; # Considered insecure
# (Perl doesn't know about /bin/echo)
system "echo $hid"; # Insecure
system "echo $data"; # Insecure until PATH set
$path = $ENV{'PATH'}; # $path now tainted
$ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$path = $ENV{'PATH'}; # $path now NOT tainted
system "echo $data"; # Is secure now!
open(FOO, "< $arg"); # OK - read-only file
open(FOO, "> $arg"); # Not OK - trying to write
open(FOO,"echo $arg|"); # Not OK
open(FOO,"-|")
or exec 'echo', $arg; # Also not OK
$shout = `echo $arg`; # Insecure, $shout now tainted
unlink $data, $arg; # Insecure
umask $arg; # Insecure
exec "echo $arg"; # Insecure
exec "echo", $arg; # Insecure
exec "sh", '-c', $arg; # Very insecure!
@files = <*.c>; # insecure (uses readdir() or similar)
@files = glob('*.c'); # insecure (uses readdir() or similar)
# In either case, the results of glob are tainted, since the list of
# filenames comes from outside of the program.
$bad = ($arg, 23); # $bad will be tainted
$arg, `true`; # Insecure (although it isn't really) Если вы попытаетесь сделать что-то небезопасное, вы получите сообщение об ошибке, например, "Небезопасная зависимость" или "Небезопасный $ENV{PATH}".
Исключением из принципа «одно заражённое значение заражает всё выражение» является условный оператор с тремя операндами ?:. Поскольку код с условным оператором с тремя операндами
$result = $tainted_value ? "Untainted" : "Also untainted"; фактически эквивалентен
if ( $tainted_value ) {
$result = "Untainted";
} else {
$result = "Also untainted";
} не имеет смысла, чтобы $result было заражено.
Отмывание и обнаружение заражённых данных
Чтобы проверить, содержит ли переменная заражённые данные, и использование которых, таким образом, вызовет сообщение «Небезопасная зависимость», вы можете использовать функцию tainted() модуля Scalar::Util, доступного в вашем ближайшем зеркале CPAN и включённого в Perl начиная с версии 5.8.0. Или вы можете использовать функцию is_tainted().
sub is_tainted {
local $@; # Don't pollute caller's value.
return ! eval { eval("#" . substr(join("", @_), 0, 0)); 1 };
} Эта функция использует тот факт, что наличие заражённых данных где-либо в выражении делает всё выражение заражённым. Неэффективно, чтобы каждый оператор проверял каждый аргумент на заражённость. Вместо этого используется немного более эффективный и консервативный подход, что если какое-либо заражённое значение было обработано в пределах того же выражения, всё выражение считается заражённым.
Но проверка на заражённость даёт только ограниченные возможности. Иногда вам нужно просто очистить заражённость ваших данных. Значения могут стать незаражёнными, используя их в качестве ключей в словаре; в противном случае единственный способ обойти механизм заражения — сослаться на подстроки из совпадения с регулярным выражением. Perl предполагает, что если вы ссылаетесь на подстроку, используя $1, $2 и т.д. в незаражающем шаблоне, вы знали, что делаете, когда писали этот шаблон. Это означает, что нужно немного подумать — не просто слепо очищать всё, или вы нарушите весь механизм. Лучше убедиться, что переменная содержит только хорошие символы (для определённых значений "хорошие"), а не проверять, есть ли в ней плохие символы. Это потому, что очень легко пропустить плохие символы, о которых вы никогда не думали.
Вот тест, чтобы убедиться, что данные содержат только символы "слова" (буквы, цифры и подчёркивания), дефис, знак @ или точку.
if ($data =~ /^([-\@\w.]+)$/) {
$data = $1; # $data now untainted
} else {
die "Bad data in '$data'"; # log this somewhere
} Это достаточно безопасно, потому что /\w+/ обычно не совпадает с метасимволами оболочки, и точка, дефис или @ не будут иметь особого значения для оболочки. Теоретически использование /.+/ было бы небезопасным, потому что оно пропускает всё, но Perl этого не проверяет. Урок состоит в том, что при очистке от заражения нужно быть чрезвычайно осторожными с шаблонами. Отмывание данных с помощью регулярных выражений — единственный механизм для очистки заражённых данных, если вы не используете стратегию создания дочернего процесса с меньшими привилегиями, описанную ниже.
В примере не очищается $data, если use locale активен, потому что символы, совпадающие с \w, определяются языком. Perl считает, что определения языка ненадежны, потому что они содержат данные извне программы. Если вы пишете программу, учитывающую язык, и хотите очистить данные с помощью регулярного выражения, содержащего \w, поместите no locale перед выражением в том же блоке. См. "БЕЗОПАСНОСТЬ" в perllocale для получения дополнительной информации и примеров.
Переключатели в строке "#!"
Когда вы делаете скрипт исполняемым, чтобы его можно было использовать как команду, система передаёт переключатели Perl из строки #! скрипта. Perl проверяет, что все переключатели командной строки, заданные для скрипта setuid (или setgid), соответствуют переключателям, заданным в строке #! Некоторые Unix-подобные системы накладывают ограничение на количество переключателей в строке #!, поэтому вам может потребоваться использовать что-то вроде -wU вместо -w -U в таких системах. (Эта проблема должна возникать только в Unix-подобных системах, поддерживающих #! и скрипты setuid или setgid.)
Режим taint и @INC
Когда активен режим taint (-T), переменные окружения PERL5LIB и PERLLIB игнорируются Perl. Вы по-прежнему можете настраивать @INC извне программы, используя параметр командной строки -I, как описано в perlrun. Эти две переменные окружения игнорируются, потому что они скрыты, и пользователь, запускающий программу, может не знать, что они установлены, в то время как параметр -I явно виден и поэтому разрешён.
Другой способ изменить @INC без изменения программы — использовать псевдоним lib, например:
perl -Mlib=/foo program Преимущество использования -Mlib=/foo перед -I/foo, состоит в том, что первый автоматически удалит все дублирующиеся каталоги, а второй — нет.
Обратите внимание, что если заражённая строка добавлена в @INC, будет сообщено о следующей проблеме:
Insecure dependency in require while running with -T switch В версиях Perl до 5.26 включительно, при активации режима taint удаляется текущая директория (".") из значения по умолчанию @INC. Начиная с версии 5.26, текущая директория по умолчанию не включается в @INC.
Очистка пути
Для сообщений "Небезопасный $ENV{PATH}" необходимо установить $ENV{'PATH'} на известное значение, а каждая директория в пути должна быть абсолютной и недоступной для записи другими пользователями, кроме владельца и группы. Вы можете столкнуться с этим сообщением даже если путь к исполняемому файлу полностью квалифицирован. Это не генерируется из-за отсутствия полного пути к программе; вместо этого это генерируется, потому что переменная окружения PATH не была установлена или установлена ненадёжным образом. Поскольку Perl не может гарантировать, что исполняемый файл не будет запускать другие программы, зависящие от PATH, он гарантирует, что PATH установлена.
Переменная PATH — не единственная переменная окружения, которая может вызвать проблемы. Поскольку некоторые оболочки могут использовать переменные IFS, CDPATH, ENV и BASH_ENV, Perl проверяет, что они пустые или не заражены при запуске дочерних процессов. Возможно, вам следует добавить что-то подобное в свои скрипты проверки setuid и заражения.
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer Возможны проблемы и с другими операциями, которые не заботятся о том, используют ли они заражённые значения. Аккуратно используйте тесты файлов при работе с именами файлов, предоставленными пользователем. Если это возможно, выполните открытие и другие действия после надлежащего снятия специальных привилегий пользователя (или группы!). Perl не предотвращает открытие заражённых имён файлов для чтения, поэтому будьте осторожны с тем, что вы выводите на печать. Механизм заражения призван предотвратить глупые ошибки, а не избавить вас от необходимости думать.
Perl не использует оболочку для расширения подстановочных знаков, когда вы передаёте system и exec явные списки параметров вместо строк с возможными подстановочными знаками оболочки. К сожалению, функции open, glob и обратных кавычек не имеют подобной альтернативной схемы вызова, поэтому потребуется дополнительное обходное решение.
Perl предоставляет достаточно безопасный способ открыть файл или канал из программы с setuid или setgid: просто создайте дочерний процесс с пониженными привилегиями, который выполнит грязную работу за вас. Сначала создайте дочерний процесс, используя специальную синтаксическую конструкцию open, которая соединит родительский и дочерний процессы с помощью канала. Теперь дочерний процесс сбрасывает свой набор идентификаторов и любые другие атрибуты процесса, такие как переменные окружения, маски, текущие рабочие каталоги, до исходных или известных безопасных значений. Затем дочерний процесс, у которого больше нет никаких специальных разрешений, выполняет open или другую системную вызов. Наконец, дочерний процесс передаёт полученные данные обратно родительскому процессу. Поскольку файл или канал были открыты в дочернем процессе с меньшими привилегиями, чем у родительского, он не подвержен обману, заставляющему его выполнить что-то нежелательное.
Вот как можно безопасно использовать обратные кавычки. Обратите внимание, что exec не вызывается со строкой, которую оболочка могла бы расширить. Это, пожалуй, лучший способ вызова чего-либо, что может быть подвергнуто расширению оболочки: просто вообще не вызывайте оболочку.
use English;
die "Can't fork: $!" unless defined($pid = open(KID, "-|"));
if ($pid) { # parent
while (<KID>) {
# do something
}
close KID;
} else {
my @temp = ($EUID, $EGID);
my $orig_uid = $UID;
my $orig_gid = $GID;
$EUID = $UID;
$EGID = $GID;
# Drop privileges
$UID = $orig_uid;
$GID = $orig_gid;
# Make sure privs are really gone
($EUID, $EGID) = @temp;
die "Can't drop privileges"
unless $UID == $EUID && $GID eq $EGID;
$ENV{PATH} = "/bin:/usr/bin"; # Minimal PATH.
# Consider sanitizing the environment even more.
exec 'myprog', 'arg1', 'arg2'
or die "can't exec myprog: $!";
} Аналогичная стратегия подошла бы для расширения подстановочных знаков через glob, хотя вы можете использовать readdir вместо этого.
Проверка заражения наиболее полезна, когда, хотя вы и доверяете себе, что не написали программу, которая может всё проиграть, вы не обязательно доверяете тем, кто будет её использовать, чтобы не пытаться заставить её сделать что-то плохое. Такая проверка безопасности полезна для программ с set-id и программ, запускаемых от имени другого пользователя, таких как CGI-программы.
Однако это совершенно отличается от того, чтобы не доверять даже автору кода, чтобы он не пытался сделать что-то злонамеренное. Такое доверие необходимо, когда кто-то даёт вам программу, которую вы никогда раньше не видели, и говорит: «Вот, запустите это». Для такой безопасности вы можете ознакомиться с модулем Safe, включённым в стандартное распределение Perl. Этот модуль позволяет программисту создавать специальные отсеки, в которых все системные операции перехватываются, а доступ к именам пространств тщательно контролируется. Safe нельзя считать абсолютно надёжным: он не предотвратит создание бесконечных циклов, выделение гигабайтов памяти или даже использование ошибок Perl для сбоя интерпретатора хоста или его непредсказуемого поведения. В любом случае, от него лучше полностью отказаться, если вы действительно обеспокоены безопасностью.
Гонка условий Shebang
Помимо очевидных проблем, связанных с предоставлением специальных привилегий таким гибким системам, как скрипты, во многих версиях Unix скрипты с set-id изначально небезопасны. Проблема заключается в гонке условий в ядре. Между тем, как ядро открывает файл, чтобы определить, какой интерпретатор запускать, и когда (теперь уже с set-id) интерпретатор возвращается и повторно открывает файл для интерпретации, файл может измениться, особенно если на вашей системе есть символические ссылки.
Некоторые версии Unix, особенно более новые, лишены этой присущей ошибки безопасности. В таких системах, когда ядро передает имя скрипта с set-id для открытия интерпретатору, вместо использования пути, который может быть изменён, оно передает /dev/fd/3. Это специальный файл, уже открытый для скрипта, поэтому злоумышленным скриптам не удастся использовать гонку условий. В таких системах Perl следует компилировать с -DSETUID_SCRIPTS_ARE_SECURE_NOW. Программа Configure, которая создаёт Perl, пытается определить это самостоятельно, поэтому вам никогда не придётся указывать это самостоятельно. Большинство современных выпусков SysVr4 и BSD 4.4 используют этот подход для предотвращения гонки условий в ядре.
Если у вас нет безопасной версии скриптов с set-id, всё ещё не потеряно. Иногда эту «функцию» ядра можно отключить, чтобы ядро либо не запускало скрипты с set-id с set-id, либо не запускало их вообще. В любом случае это предотвращает возможность эксплуатации гонки условий, но не помогает в фактическом запуске скриптов с set-id.
Если функция set-id ядра не отключена, любой скрипт с set-id представляет уязвимость, которую можно использовать. Perl не может избежать этого, но укажет уязвимые скрипты, где это возможно. Если Perl обнаружит, что он применяется к скрипту с set-id, он громко сообщит, что ваш скрипт с set-id небезопасен, и не запустит его. Когда Perl жалуется, вам нужно удалить флаг set-id из скрипта, чтобы устранить уязвимость. Отказ от запуска скрипта сам по себе не устраняет уязвимость; это просто способ Perl побудить вас сделать это.
Чтобы действительно запустить скрипт с set-id, если у вас нет безопасной версии скриптов с set-id, вам понадобится C-оболочка вокруг скрипта. C-оболочка — это просто скомпилированная программа, которая ничего не делает, кроме вызова вашей Perl-программы. Скомпилированные программы не подвержены ошибке ядра, которая затрагивает скрипты с set-id. Вот простая оболочка, написанная на C:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define REAL_PATH "/path/to/script"
int main(int argc, char **argv)
{
execv(REAL_PATH, argv);
fprintf(stderr, "%s: %s: %s\n",
argv[0], REAL_PATH, strerror(errno));
return 127;
} Скомпилируйте эту оболочку в исполняемый файл, а затем сделайте её, а не ваш скрипт setuid или setgid. Обратите внимание, что эта оболочка ничего не делает для очистки среды выполнения, кроме как гарантирует, что используется безопасный путь к скрипту. Она только избегает проблемы гонки условий shebang. Она полагается на собственные функции Perl и на то, что сам скрипт осторожен, чтобы сделать его достаточно безопасным для запуска скрипта с set-id.
Защита ваших программ
Существует несколько способов скрыть исходный код ваших Perl-программ с различными уровнями «безопасности».
Однако в первую очередь вы не можете убрать разрешение на чтение, так как исходный код должен быть читаемым для компиляции и интерпретации. (Это не означает, что исходный код CGI-скрипта доступен для просмотра людям в сети.) Поэтому вам необходимо сохранить разрешения на социально приемлемом уровне 0755. Это позволяет людям в вашей локальной системе видеть только ваш исходный код.
Некоторые люди ошибочно считают это проблемой безопасности. Если ваша программа делает небезопасные вещи и полагается на то, что люди не знают, как использовать эти уязвимости, она не безопасна. Часто можно определить небезопасные вещи и использовать их, не видя исходный код. Безопасность через скрытность, то есть скрытие ваших ошибок вместо их исправления, — это не очень надёжная безопасность.
Вы можете попробовать использовать шифрование с помощью фильтров исходного кода (Filter::* из CPAN или Filter::Util::Call и Filter::Simple с Perl 5.8). Но взломщики могут расшифровать его. Вы можете попробовать использовать компилятор и интерпретатор байт-кода, описанные ниже, но взломщики могут его декомпилировать. Вы можете попробовать использовать компилятор кода на родном языке, описанный ниже, но взломщики могут его дизассемблировать. Они представляют различные степени сложности для людей, которые хотят получить доступ к вашему коду, но ни один из них не может окончательно его скрыть (это справедливо для любого языка, а не только Perl).
Если вас беспокоят люди, которые извлекают выгоду из вашего кода, в конечном счёте, только ограниченная лицензия обеспечит вам правовую безопасность. Лицензируйте своё программное обеспечение и добавьте в него угрожающие заявления, такие как «Это непубличная собственность XYZ Corp. Ваш доступ к нему не даёт вам права использовать его ...». Вам следует проконсультироваться с юристом, чтобы быть уверенными, что формулировка вашей лицензии будет иметь силу в суде.
Unicode
Unicode — новая и сложная технология, и легко можно упустить из виду определённые уязвимости в области безопасности. Ознакомьтесь со статьей perluniintro для обзора, perlunicode для подробностей и "Security Implications of Unicode" в perlunicode для подробностей, в частности, о последствиях для безопасности.
Атаки на алгоритмическую сложность
Некоторые внутренние алгоритмы, используемые в реализации Perl, могут быть атакованы, тщательно выбирая входные данные для потребления большого количества времени или места, или того и другого. Это может привести к так называемым атакам отказ в обслуживании (DoS).
-
Алгоритм хеширования - Алгоритмы хеширования, такие как используемые в Perl, известны своей уязвимостью к атакам на коллизии хеш-функции. Такие атаки предполагают создание набора ключей, которые сталкиваются в одном и том же ведре, что приводит к неэффективному поведению. Такие атаки часто зависят от обнаружения начального значения хеш-функции, используемой для сопоставления ключей с ведрами. Затем это начальное значение используется для подбора набора ключей, которые могут быть использованы для атаки типа отказ в обслуживании. В Perl 5.8.1 были внесены изменения для повышения устойчивости Perl к таким атакам, а затем, в Perl 5.18.0, эти функции были улучшены и добавлены дополнительные средства защиты.
На момент написания этой статьи Perl 5.18.0 считается хорошо защищенным от атак на алгоритмическую сложность его реализации хеширования. Это во многом обусловлено следующими мерами по смягчению атак:
- Случайная инициализация начального значения хеширования
-
Для того чтобы сделать невозможным определение начального значения для генерации набора ключей атаки, это начальное значение случайным образом инициализируется при запуске процесса. Это может быть переопределено с помощью переменной окружения PERL_HASH_SEED, см. "PERL_HASH_SEED" в perlrun. Эта переменная окружения управляет тем, как элементы фактически хранятся, а не тем, как они представлены через
keys,valuesиeach. - Случайная выборка порядка обхода хеш-таблицы
-
Независимо от того, какое начальное значение используется в хеш-функции,
keys,values, иeachвозвращают элементы в случайном порядке для каждой хеш-таблицы. Изменение хеш-таблицы путем вставки изменит порядок итерации этой хеш-таблицы. Это поведение можно переопределить, используяhash_traversal_mask()из Hash::Util или используя переменную среды PERL_PERTURB_KEYS, см. "PERL_PERTURB_KEYS" в perlrun. Обратите внимание, что эта функция управляет видимым порядком ключей, а не фактическим порядком их хранения. - Случайный порядок ведер
-
Когда элементы сталкиваются в данном ведре хеш-таблицы, порядок их хранения в цепочке более не предсказуем в Perl 5.18. Это призвано затруднить наблюдение за столкновениями. Это поведение можно переопределить, используя переменную окружения PERL_PERTURB_KEYS, см. "PERL_PERTURB_KEYS" в perlrun.
- Новая по умолчанию хеш-функция
-
Функция хеширования по умолчанию была изменена с целью затруднения вывода начального значения хеширования.
- Альтернативные хеш-функции
-
Исходный код включает несколько алгоритмов хеширования для выбора. Хотя мы считаем, что стандартная хеш-функция Perl устойчива к атакам, мы включили хеш-функцию Siphash в качестве резервного варианта. На момент выпуска Perl 5.18.0 Siphash считается криптографически стойкой. Она не является по умолчанию, так как значительно медленнее, чем стандартная.
Без компиляции специальной версии Perl нет способа получить точно такое же поведение, как в версиях до Perl 5.18.0. Ближайшее к этому можно получить, установив PERL_PERTURB_KEYS в 0 и установив PERL_HASH_SEED в известное значение. Мы не рекомендуем эти настройки для использования в продакшене из-за вышеуказанных соображений безопасности.
Perl никогда не гарантировал какой-либо порядок хеш-ключей, и этот порядок уже несколько раз менялся за время существования Perl 5. Кроме того, порядок хеш-ключей всегда и продолжает зависеть от порядка вставки и истории изменений, внесённых в хеш-таблицу за её время существования.
Также обратите внимание, что, хотя порядок элементов хеш-таблицы может быть случайным, этот «псевдо-порядок» не следует использовать для задач, таких как случайное перемешивание списка (для этого используйте
List::Util::shuffle(), см. List::Util, стандартный модуль ядра с Perl 5.8.0; или модуль CPANAlgorithm::Numerical::Shuffle), или для генерации перестановок (используйте, например, модули CPANAlgorithm::PermuteилиAlgorithm::FastPermute), или для любых криптографических применений.Связанные хеш-таблицы могут иметь свой собственный порядок и атаки, использующие алгоритмическую сложность.
-
Регулярные выражения - Двигатель регулярных выражений Perl называется NFA (Недетерминированный конечный автомат), что, помимо прочего, означает, что он может довольно легко потреблять большие объемы времени и памяти, если регулярное выражение может совпадать несколькими способами. Тщательное составление регулярных выражений может помочь, но довольно часто это действительно не очень эффективно (книга «Мастерство регулярных выражений» является обязательной для прочтения, см. perlfaq2). Истечение памяти проявляется в том, что Perl выходит из строя.
-
Сортировка - алгоритм быстрой сортировки, используемый в Perl до версии 5.8.0 для реализации функции sort(), очень легко обмануть, чтобы он вел себя неправильно, что приводит к большому потреблению времени. Начиная с Perl 5.8.0 по умолчанию используется другой алгоритм сортировки - слияние. Слияние не может вести себя неправильно на любом вводе.
Дополнительную информацию см. в https://www.usenix.org/legacy/events/sec03/tech/full_papers/crosby/crosby.pdf, а также в любом учебнике по информатике об алгоритмической сложности.
Использование Sudo
Популярный инструмент sudo предоставляет контролируемый способ для пользователей запускать программы от имени других пользователей. Он до некоторой степени очищает среду выполнения и избежит проблемы конфликта shebang. Если у вас нет безопасной версии скриптов set-id, то sudo может быть более удобным способом запуска скрипта от имени другого пользователя, чем написание оболочки C.
Однако sudo устанавливает реальный идентификатор пользователя или группы в соответствии с идентификатором целевого объекта, а не только эффективный идентификатор, как это делают биты set-id. В результате Perl не может обнаружить, что он работает под sudo, и поэтому не будет автоматически применять собственные меры безопасности, такие как включение режима taint. В тех случаях, когда конфигурация sudo определяет, какие команды можно запускать, разрешённая команда может включать опцию -T для perl для включения режима taint.
В общем случае необходимо оценить пригодность скрипта для запуска под sudo с учётом этой среды выполнения. Не является ни необходимым, ни достаточным, чтобы тот же самый скрипт подходил для запуска в традиционной схеме set-id, хотя многие проблемы перекрываются.
См. также
"ENVIRONMENT" в perlrun для описания очистки переменных окружения.
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.32.0/perlsec