Spec-Zone.ru › Perl 5.30

perlsec

СОДЕРЖАНИЕ

  • НАЗВАНИЕ
  • ОПИСАНИЕ
  • КОНТАКТНАЯ ИНФОРМАЦИЯ О НАРУШЕНИЯХ БЕЗОПАСНОСТИ
  • МЕХАНИЗМЫ И ВОПРОСЫ БЕЗОПАСНОСТИ
    • Режим контроля данных
    • Отмывание и обнаружение заражённых данных
    • Переключатели в строке "#!"
    • Режим контроля данных и @INC
    • Очистка пути
    • Проблема гонки shebang
    • Защита ваших программ
    • Unicode
    • Атаки на сложность алгоритма
    • Использование Sudo
  • СМОТРИ ТАКЖЕ

НАЗВАНИЕ

perlsec - Безопасность Perl

ОПИСАНИЕ

Perl разработан для лёгкой программирования в безопасном режиме, даже при выполнении с расширенными привилегиями, такими как setuid или setgid программы. В отличие от большинства командных интерпретаторов, которые основаны на нескольких проходах по замене каждой строки скрипта, Perl использует более стандартную схему оценки с меньшим количеством скрытых проблем. Кроме того, поскольку язык имеет больше встроенных функций, он меньше полагается на внешние (и, возможно, ненадежные) программы для достижения своих целей.

КОНТАКТНАЯ ИНФОРМАЦИЯ О НАРУШЕНИЯХ БЕЗОПАСНОСТИ

Если вы считаете, что обнаружили уязвимость в безопасности Perl, пожалуйста, отправьте подробности по электронной почте на адрес perl5-security-report@perl.org. Это создаст новый запрос в Request Tracker в специальной очереди, которая изначально не является общедоступной. Электронное письмо также будет скопировано на закрытый архивированный список рассылки, который включает всех основных разработчиков, которые смогут помочь оценить влияние проблем, найти решение и скоординировать выпуск исправления для смягчения или устранения проблемы на всех платформах, на которых поддерживается Perl. Пожалуйста, используйте этот адрес только для проблем безопасности в ядре Perl, а не для модулей, распространяемых независимо на CPAN.

При отправке первоначального запроса на адрес электронной почты безопасности, пожалуйста, не рассылайте его другим сторонам, потому что если они ответят всем, ответ создаст ещё один новый запрос. После получения первоначального ответа с номером запроса [perl #NNNNNN] в заголовке, вы можете рассылать последующие ответы третьим сторонам: все электронные письма на адрес perl5-security-report с номером запроса в теме будут добавлены к запросу; без него будет создан новый запрос.

МЕХАНИЗМЫ И ВОПРОСЫ БЕЗОПАСНОСТИ

Режим контроля данных

Perl автоматически включает набор специальных проверок безопасности, называемый режимом контроля данных, когда обнаруживает, что его программа выполняется с разными реальными и эффективными идентификаторами пользователя или группы. Бит setuid в разрешениях Unix имеет режим 04000, бит setgid имеет режим 02000; может быть установлен один или оба бита. Вы также можете явно включить режим контроля данных, используя командную строку -T. Этот флаг настоятельно рекомендуется для серверных программ и любых программ, выполняемых от имени другого пользователя, таких как скрипт CGI. После включения режима контроля данных, он остается активным на протяжении всего выполнения скрипта.

В этом режиме Perl принимает особые меры предосторожности, называемые проверками на наличие заражённых данных, чтобы предотвратить очевидные и скрытые ловушки. Некоторые из этих проверок достаточно простые, такие как проверка того, что каталоги путей не могут быть изменены другими пользователями; внимательные программисты всегда использовали проверки такого рода. Однако другие проверки лучше поддерживаются самим языком, и именно эти проверки в особенности способствуют повышению безопасности программы Perl, работающей с правами setuid, по сравнению с аналогичной программой на 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).

Режим контроля данных и @INC

Когда режим контроля данных (-T) включен, каталог "." удаляется из @INC, а переменные среды PERL5LIB и PERLLIB игнорируются Perl. Вы по-прежнему можете настроить @INC извне программы, используя командную строку -I как объяснено в perlrun. Две переменные среды игнорируются, потому что они скрыты, и пользователь, запускающий программу, может не знать, что они установлены, тогда как параметр -I явно виден и поэтому разрешен.

Другой способ изменить @INC без изменения программы – это использование pragmy lib, например:

perl -Mlib=/foo program

Преимущество использования -Mlib=/foo по сравнению с -I/foo, заключается в том, что первый автоматически удаляет любые дублирующиеся каталоги, в то время как второй – нет.

Обратите внимание, что если заражённая строка добавлена в @INC, будет сообщена следующая проблема:

Insecure dependency in require while running with -T switch

Очистка пути

Для сообщений «Небезопасный $ENV{PATH}» необходимо установить $ENV{'PATH'} на известное значение, а каждый каталог в пути должен быть абсолютным и недоступным для записи пользователями, отличными от владельца и группы. Вас может удивить получение этого сообщения даже в том случае, если путь к исполняемому файлу полностью квалифицирован. Это не генерируется из-за того, что вы не указали полный путь к программе; вместо этого оно генерируется потому, что вы никогда не устанавливали переменную среды PATH или не установили ее в безопасное значение. Поскольку Perl не может гарантировать, что исполняемый файл в вопросе не запустит другую программу, зависящую от вашей переменной среды PATH, он гарантирует, что вы установили PATH.

PATH — не единственная переменная среды, которая может вызвать проблемы. Поскольку некоторые оболочки могут использовать переменные IFS, CDPATH, ENV и BASH_ENV, Perl проверяет, что они пустые или не загрязнены при запуске дочерних процессов. Возможно, вы захотите добавить что-то подобное в свои скрипты сетапа и проверки на загрязнение.

delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};   # Make %ENV safer

Также возможно столкнуться с проблемами при других операциях, которые не заботятся о том, используют ли они загрязнённые значения. Используйте файлы тестов при работе с именами файлов, предоставленными пользователем. По возможности, открывайте файлы и выполняйте подобные действия после корректного отключения специальных привилегий пользователя (или группы!). Perl не препятствует открытию зараженных файлов для чтения, поэтому будьте внимательны к тому, что вы выводите на печать. Механизм заражения предназначен для предотвращения глупых ошибок, а не для устранения необходимости продумывания действий.

Perl не вызывает оболочку для расширения шаблонов, когда вы передаете system и exec явные списки параметров вместо строк с возможными символами подстановки оболочки. К сожалению, функции open, glob и обратных кавычек не предоставляют такой альтернативной схемы вызова, поэтому потребуется дополнительная хитрость.

Perl предоставляет достаточно безопасный способ открыть файл или канал из программы с установленным пользователем или группой: просто создайте дочерний процесс с уменьшенными привилегиями, который выполнит грязную работу за вас. Сначала разделите дочерний процесс, используя специальный 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 вместо этого.

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

Однако это совершенно отличается от того, чтобы не доверять даже автору кода, чтобы не пытаться сделать что-то злонамеренное. Именно такой уровень доверия требуется, когда кто-то даёт вам программу, которую вы никогда раньше не видели, и говорит: «Вот, запустите это». Для обеспечения такой безопасности вы можете изучить модуль Safe, включённый в стандартную поставку Perl. Этот модуль позволяет программисту создавать специальные отсеки, в которых все системные операции отслеживаются, а доступ к именам пространств тщательно контролируется. Safe не следует считать абсолютно надёжным: он не предотвратит выполнение чужим кодом бесконечных циклов, выделение гигабайтов памяти или даже злоупотребление ошибками perl для вывода интерпретатора-хозяина из строя или непредсказуемого поведения. В любом случае, его лучше полностью избегать, если вы действительно обеспокоены вопросами безопасности.

Условие гонки shebang

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

Некоторые версии Unix, особенно более новые, свободны от этой встроенной уязвимости безопасности. В таких системах, когда ядро передаёт имя скрипта с установленным пользователем для открытия интерпретатору, вместо использования пути, подверженного вмешательствам, оно вместо этого передаёт /dev/fd/3. Это специальный файл, уже открытый в скрипте, так что не может возникнуть условия гонки для злонамеренных скриптов. В таких системах Perl должен быть скомпилирован с -DSETUID_SCRIPTS_ARE_SECURE_NOW. Программа Configure, которая собирает Perl, пытается выяснить это самостоятельно, поэтому вам никогда не придётся указывать это самостоятельно. Большинство современных версий SysVr4 и BSD 4.4 используют этот подход для предотвращения условия гонки в ядре.

Если у вас нет безопасной версии скриптов с установленным пользователем, всё ещё не всё потеряно. Иногда эту «функцию» ядра можно отключить, так что ядро либо не запускает скрипты с установленным пользователем с установленным пользователем, либо не запускает их вообще. В любом случае это предотвращает возможность использования уязвимости условия гонки, но не помогает фактически запускать скрипты с установленным пользователем.

Если функция ядра «скрипт с установленным пользователем» не отключена, любой скрипт с установленным пользователем представляет собой уязвимость. Perl не может избежать использования уязвимости, но укажет на уязвимые скрипты, где это возможно. Если Perl обнаруживает, что он применяется к скрипту с установленным пользователем, он громко сообщит, что ваш скрипт с установленным пользователем небезопасен и не запустит его. Когда Perl жалуется, вам нужно удалить бит «установленный пользователь» из скрипта, чтобы устранить уязвимость. Отказаться от запуска скрипта само по себе не устраняет уязвимость; это просто способ Perl побудить вас сделать это.

Чтобы фактически запустить скрипт с установленным пользователем, если у вас нет безопасной версии скриптов с установленным пользователем, вам потребуется создать оболочку на C вокруг скрипта. C-оболочка — это просто скомпилированная программа, которая ничего не делает, кроме вызова вашей программы Perl. Скомпилированные программы не подвержены ошибке ядра, которая поражает скрипты с установленным пользователем. Вот простая оболочка, написанная на 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 и на то, что сам скрипт осторожен, чтобы сделать его достаточно безопасным для запуска скрипта с установленным пользователем.

Защита ваших программ

Существует несколько способов скрыть исходный код ваших программ 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; или модуль CPAN Algorithm::Numerical::Shuffle), или для генерации перестановок (используйте, например, модули CPAN Algorithm::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, учитывая именно такую среду выполнения. Это ни необходимо, ни достаточно для того, чтобы тот же скрипт подходил для работы в традиционной схеме смены идентификаторов, хотя многие проблемы перекрываются.

См. также

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.30.3/perlsec

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API