perlsec
СОДЕРЖАНИЕ
- ИМЯ
- ОПИСАНИЕ
- КОНТАКТНАЯ ИНФОРМАЦИЯ О НАРУШЕНИИ БЕЗОПАСНОСТИ
- МЕХАНИЗМЫ И ВОПРОСЫ БЕЗОПАСНОСТИ
- СМОТРИТЕ ТАКЖЕ
ИМЯ
perlsec - Безопасность Perl
ОПИСАНИЕ
Perl разработан для обеспечения лёгкой программирования в безопасном режиме, даже при работе с повышенными привилегиями, такими как программы setuid или setgid. В отличие от большинства командных оболочек, которые основаны на нескольких проходах по подстановке каждой строки скрипта, Perl использует более традиционную схему оценки с меньшим количеством скрытых проблем. Кроме того, поскольку язык обладает большей встроенной функциональностью, он может меньше полагаться на внешние (и, возможно, ненадежные) программы для достижения своих целей.
КОНТАКТНАЯ ИНФОРМАЦИЯ О НАРУШЕНИИ БЕЗОПАСНОСТИ
Если вы считаете, что обнаружили уязвимость в интерпретаторе Perl или модулях, поддерживаемых в ядре Perl, отправьте подробности по электронной почте на адрес perl-security@perl.org. Этот адрес является закрытым списком рассылки, отслеживаемым группой по безопасности Perl.
Дополнительную информацию см. в perlsecpolicy.
МЕХАНИЗМЫ И ВОПРОСЫ БЕЗОПАСНОСТИ
Режим слежения
Perl автоматически включает набор специальных проверок безопасности, называемых режимом слежения, при обнаружении запуска своей программы с разными реальными и эффективными идентификаторами пользователя или группы. Флажок setuid в правах Unix имеет режим 04000, флажок setgid - режим 02000; может быть установлен один или оба. Вы также можете явно включить режим слежения, используя командную строку -T. Этот флаг настоятельно рекомендуется для серверных программ и любых программ, выполняемых от имени другого пользователя, таких как скрипт CGI. После включения режима слежения он остается активным до конца вашего скрипта.
В этом режиме Perl предпринимает особые меры предосторожности, называемые проверками слежения, чтобы предотвратить очевидные и скрытые ловушки. Некоторые из этих проверок довольно просты, например, проверка того, что каталоги пути не могут быть записаны другими пользователями; аккуратные программисты всегда использовали проверки такого рода. Однако другие проверки лучше всего поддерживаются самим языком, и именно эти проверки вносят наибольший вклад в обеспечение большей безопасности программы 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 проверяет, действительно ли все переключатели командной строки, заданные для скрипта с установленным идентификатором пользователя (или идентификатором группы), соответствуют переключателям, заданным в строке #! Некоторые среды Unix и Unix-подобных систем налагают ограничение на одну команду в строке #!, поэтому вам может потребоваться использовать что-то вроде -wU вместо -w -U в таких системах. (Эта проблема должна возникнуть только в средах Unix или Unix-подобных системах, которые поддерживают #! и скрипты с установленным идентификатором пользователя или идентификатором группы).
Режим слежения и @INC
Когда режим слежения (-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 включение режима слежения также удалит текущий каталог (".") из значения по умолчанию @INC. Начиная с версии 5.26, текущий каталог не включается в @INC по умолчанию.
Очистка пути
Для сообщений «Небезопасный $ENV{PATH}» необходимо установить $ENV{'PATH'} в известное значение, и каждый каталог в пути должен быть абсолютным и недоступен для записи пользователями, отличными от владельца и группы. Вас может удивить получение этого сообщения, даже если путь к исполняемому файлу полностью квалифицирован. Это не генерируется из-за того, что вы не указали полный путь к программе; вместо этого это генерируется, потому что вы никогда не задавали переменную среды PATH или не задавали её в безопасном значении. Поскольку Perl не может гарантировать, что исполняемый файл не запустит другую программу, которая зависит от вашего PATH, он гарантирует, что вы установили PATH.
Переменная PATH — не единственная переменная окружения, которая может вызвать проблемы. Поскольку некоторые оболочки могут использовать переменные IFS, CDPATH, ENV и BASH_ENV, Perl проверяет, что они либо пусты, либо не заражены при запуске дочерних процессов. Вы можете добавить что-то подобное в свои скрипты setid и проверки на заражение.
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer Также возможно столкнуться с проблемами при других операциях, которые не заботятся о том, используют ли они заражённые значения. Используйте с умом тесты файлов при работе с именами файлов, предоставленными пользователем. Когда это возможно, выполняйте открытия и подобные операции после надлежащего снятия специальных привилегий пользователя (или группы!). Perl не предотвращает открытие заражённых файлов для чтения, поэтому будьте осторожны, что вы выводите на печать. Механизм заражения предназначен для предотвращения глупых ошибок, а не для устранения необходимости в размышлениях.
Perl не вызывает оболочку для расширения подстановок, когда вы передаёте system и exec явные списки параметров вместо строк с возможными подстановками оболочки. К сожалению, функции open, glob, и обратные кавычки не предоставляют подобной альтернативной схемы вызова, поэтому потребуется больше хитростей.
Perl предоставляет относительно безопасный способ открыть файл или канал из программы с setuid или setgid: просто создайте дочерний процесс с пониженными привилегиями, который выполнит грязную работу за вас. Сначала разделите процесс с помощью специального синтаксиса open, который соединит родительский и дочерний процессы с помощью канала. Теперь дочерний процесс сбросит свои идентификаторы и любые другие атрибуты процесса, такие как переменные окружения, маски umask, текущие рабочие каталоги, обратно к исходным или известным безопасным значениям. Затем дочерний процесс, который больше не имеет особых разрешений, выполняет 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) интерпретатор поворачивается и повторно открывает файл для интерпретации, файл может измениться, особенно если на вашей системе есть символические ссылки.
В некоторых Unixes, особенно в более современных, отсутствует эта встроенная уязвимость. На таких системах, когда ядро передаёт имя скрипта 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». Если у вас нет безопасной версии скриптов с установкой идентификаторов, то sudo может быть более удобным способом запуска скрипта от имени другого пользователя, чем написание C-обертки.
Однако sudo устанавливает реальный идентификатор пользователя или группы на идентификатор целевого пользователя, а не только эффективный идентификатор, как это делают биты set-id. В результате Perl не может обнаружить, что он выполняется под sudo, и поэтому не автоматически принимает собственные меры безопасности, такие как включение режима taint. В конфигурации sudo точно указывается, какие команды могут выполняться, и разрешенная команда может включать опцию -T для perl, чтобы включить режим taint.
В целом, необходимо оценить пригодность скрипта для выполнения под sudo с учетом именно такого типа среды выполнения. Это ни необходимо, ни достаточно для того, чтобы тот же скрипт подходил для традиционной схемы set-id, хотя многие проблемы перекрываются.
СМОТРИТЕ ТАКЖЕ
"ENVIRONMENT" в perlrun для описания очистки переменных среды.
© 1993–2021 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.34.0/perlsec