Linux игнорирует бит setuid¹ во всех интерпретируемых исполняемых файлах (т.е. исполняемых файлах, начинающихся со #!
строки). Comp.unix.questions FAQ объясняет проблемы безопасности с УИП сценариями оболочки. Эти проблемы бывают двух видов: связанные с Шебангом и связанные с оболочкой; Я вхожу в более подробную информацию ниже.
Если вы не заботитесь о безопасности и хотите разрешить сценарии setuid, в Linux вам нужно будет исправить ядро. Что касается ядер 3.x, я думаю, вам нужно добавить вызов install_exec_creds
в load_script
функцию перед вызовом open_exec
, но я не проверял.
Сетуид Шебанг
Существует способ состязания, свойственный тому, как #!
обычно реализуется shebang ( ):
- Ядро открывает исполняемый файл и находит, что оно начинается с
#!
.
- Ядро закрывает исполняемый файл и открывает вместо него интерпретатор.
- Ядро вставляет путь к сценарию в список аргументов (as
argv[1]
) и выполняет интерпретатор.
Если в этой реализации разрешены сценарии setuid, злоумышленник может вызвать произвольный сценарий, создав символическую ссылку на существующий сценарий setuid, выполнив ее и организовав изменение ссылки после того, как ядро выполнит шаг 1 и до того, как интерпретатор дойдет до открывая свой первый аргумент. По этой причине большинство юнитов игнорируют бит setuid при обнаружении шебанга.
Одним из способов защиты этой реализации было бы то, чтобы ядро блокировало файл сценария до тех пор, пока интерпретатор не откроет его (обратите внимание, что это должно предотвратить не только удаление или перезапись файла, но также переименование любого каталога в пути). Но Unix-системы, как правило, уклоняются от обязательных блокировок, а символические ссылки делают правильную блокировку особенно трудной и агрессивной. Я не думаю, что кто-то так делает.
Несколько систем UNIX ( в основном OpenBSD, NetBSD и Mac OS X, все из которых требуют настройки ядра должны быть включены) осуществлять безопасное Setuid хижины с помощью дополнительной функции: путь относится к файлу уже открыт дескриптор файла N (так открытие является примерно эквивалентно ). Многие системы Unix (включая Linux) имеют, но не имеют сценариев setuid./dev/fd/N
/dev/fd/N
dup(N)
/dev/fd
- Ядро открывает исполняемый файл и находит, что оно начинается с
#!
. Допустим, дескриптор файла для исполняемого файла равен 3.
- Ядро открывает интерпретатор.
- Ядро вставляет
/dev/fd/3
список аргументов (как argv[1]
) и выполняет интерпретатор.
Страница Шебанга Свена Машика содержит много информации о Шебанге в разных отделениях, включая поддержку setuid .
Сетуид переводчики
Предположим, вам удалось запустить программу от имени root, либо потому, что ваша ОС поддерживает setuid shebang, либо потому, что вы использовали встроенную двоичную оболочку (например, sudo
). Вы открыли дыру в безопасности? Может быть . Проблема здесь не в интерпретируемых, а в скомпилированных программах. Вопрос в том, будет ли ваша среда выполнения работать безопасно, если она выполняется с привилегиями.
Любой динамически связанный собственный двоичный исполняемый файл интерпретируется динамическим загрузчиком (например /lib/ld.so
), который загружает динамические библиотеки, необходимые для программы. На многих устройствах вы можете настроить путь поиска динамических библиотек в среде ( LD_LIBRARY_PATH
это общее имя переменной среды) и даже загрузить дополнительные библиотеки во все исполняемые двоичные файлы ( LD_PRELOAD
). Вызывающий программы может выполнить произвольный код в контексте этой программы путем размещения специально созданный libc.so
в $LD_LIBRARY_PATH
(среди других тактик). Все вменяемые системы игнорируют LD_*
переменные в исполняемых файлах setuid.
В оболочках, таких как sh, csh и производные, переменные среды автоматически становятся параметрами оболочки. Благодаря таким параметрам, как PATH
, IFS
, и многое другое, запустившего сценарий имеет много возможностей для выполнения произвольного кода в контексте сценариев оболочки игровая. Некоторые оболочки устанавливают эти переменные в разумные значения по умолчанию, если обнаруживают, что скрипт был вызван с привилегиями, но я не знаю, есть ли какая-то конкретная реализация, которой я бы доверял.
Большинство сред выполнения (будь то нативное, байт-код или интерпретируемое) имеют сходные функции. Мало кто принимает особые меры предосторожности в исполняемых файлах setuid, хотя те, которые запускают нативный код, часто не делают ничего более хитрого, чем динамическое связывание (которое требует предосторожности).
Perl является заметным исключением. Он явно поддерживает сценарии setuid безопасным способом. Фактически, ваш скрипт может запускать setuid, даже если ваша ОС игнорирует бит setuid в скриптах. Это связано с тем, что perl поставляется с корневым помощником setuid, который выполняет необходимые проверки и повторно вызывает интерпретатор для нужных сценариев с желаемыми привилегиями. Это объясняется в руководстве perlsec . Раньше было так, что #!/usr/bin/suidperl -wT
вместо этого #!/usr/bin/perl -wT
, но на большинстве современных систем, #!/usr/bin/perl -wT
достаточно было бы использовать perl-скрипты setuid .
Обратите внимание, что использование встроенной двоичной оболочки ничего не делает само по себе, чтобы предотвратить эти проблемы . На самом деле, это может сделать ситуацию еще хуже , потому что это может предотвратить среды выполнения от обнаружения того, что она вызывается с правами и в обход его выполнения настраиваемость.
Собственная двоичная оболочка может сделать сценарий оболочки безопасным, если оболочка дезинфицирует среду . Сценарий должен позаботиться о том, чтобы не делать слишком много предположений (например, о текущем каталоге), но это так. Вы можете использовать sudo для этого при условии, что он настроен для очистки среды. Переменные в черном списке подвержены ошибкам, поэтому всегда белый список. С помощью sudo убедитесь, что env_reset
опция включена, setenv
выключена env_file
и env_keep
содержит только безобидные переменные.
TL, DR:
- Сетуид Шебанг небезопасен, но обычно игнорируется.
- Если вы запускаете программу с привилегиями (либо через sudo, либо через setuid), пишете собственный код или perl, либо запускаете программу с оболочкой, которая дезинфицирует среду (например, sudo с
env_reset
опцией).
Discussion Это обсуждение в равной степени применимо, если вы замените «setgid» на «setuid»; они оба игнорируются ядром Linux в сценариях