Могу ли я доверять переменным окружения?
Я пишу набор утилит в bash
, который имеет общую библиотеку. Каждый script, который я пишу, должен иметь блок кода, который определяет путь библиотеки относительно исполняемого файла. Не настоящий код, а пример:
#!/bin/bash
DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
. $DIR/../lib/utilities/functions
Вместо преамбулы, которая пытается найти библиотеку, я имел яркую идею использовать переменную окружения для указания расположения библиотек.
#!/bin/bash
. $TOOLS_LIBRARY_PATH
Я мог бы использовать программу-оболочку для установки этой переменной среды, или я мог бы установить ее по своему пути. Могут быть лучшие способы организовать набор инструментов bash
, но вопрос:
Могу ли я доверять переменным окружения?
Это один из тех, которые я никогда не думал об этом. При программировании на других языках пути используются для поиска библиотек (например, LD_LIBRARY_PATH
, PYTHONPATH
, PERLLIB
, RUBYLIB
, CLASSPATH
, NODE_PATH
), но мне никогда не приходилось останавливаться и думать о том, как это может быть небезопасно.
Фактически, LD_LIBRARY_PATH
имеет Почему LD_LIBRARY_PATH
является плохим, чтобы препятствовать его использованию. Переменные среды пути библиотеки Ruby и Perl игнорируются, если вызывается их механизмы безопасности, $SAFE
и -T
(taint mode) соответственно.
Мои мысли до сих пор...
- Пользователь может установить
TOOLS_PATH_LIBRARY
в библиотеку по своему выбору, но утилита будет работать под их uid. Они могли просто запустить свою вредоносную библиотеку напрямую с помощью bash
.
- Мои инструменты
sudo
некоторые вещи. Кто-то может установить их TOOLS_PATH_LIBRARY
на то, что использует это. Но инструменты не запускаются через sudo
, они только вызывают sudo
здесь и там. Пользователь должен был бы быть sudoer
в любом случае, он мог просто вызвать sudo
напрямую.
- Если я не могу доверять
TOOLS_PATH_LIBRARY
, то я не могу доверять PATH
. Все вызовы программы должны использовать абсолютные пути.
- Я видел, как программы оболочки используют псевдонимы для абсолютных программ, поэтому вместо вызова
ls
используйте переменную, например LS=/bin/ls
. Из того, что я читал, это защита от переопределения программных дефолтов в качестве псевдонимов. Смотрите: PATH, функции и безопасность. Bash лучшие примеры использования сценариев..
- Perl taint mode рассматривает все переменные среды как "испорченные", которые предвещают, поэтому я пытаюсь рассуждать о рисках окружающей среды.
- Невозможно изменить одну другую среду, если только пользователь не является пользователем root. Таким образом, я беспокоюсь только о том, что пользователь меняет свою среду для повышения привилегий. См.: Есть ли способ изменить другие переменные среды процесса?
Я резина уклонилась в ответ, но я все еще собираюсь опубликовать его, так как это не ответ pat.
Обновить. Каковы проблемы безопасности, связанные с использованием переменных среды, для указания путей к библиотекам и исполняемым файлам?
Ответы
Ответ 1
Короткий ответ:
Предполагая, что пользователь в любом случае может запускать программы и код по своему выбору, вам не нужно доверять тому, что они вам кормят, включая среду. Если учетная запись ограничена в некотором роде (без доступа к оболочке, без доступа на запись к файловым системам, которые разрешают выполнение), это может изменить изображение, но пока ваши скрипты делают только то, что пользователь может сделать сам, зачем защищать от вредоносных вмешательство?
Дольше ответ:
По соображениям безопасности есть как минимум два отдельных вопроса:
- Что и с кем нам нужно защищать?
- (тесно связанный вопрос: что может сделать наша программа на самом деле и что она может сломать?)
- Как мы это делаем?
Если и до тех пор, пока ваша программа работает под идентификатором пользователя пользователя, запускающего программу, и предоставляя все входные данные (т.е. только тот, кто может монтировать любую атаку), есть только редкие ситуации, когда это имеет смысл в все, чтобы ожесточить программу против атак. На ум приходит защита от копирования и совместное использование высоких баллов, но эта группа вещей касается не только ресурсов, но, вероятно, даже более того, чтобы пользователь не читал код и память. Скрытие кода оболочки script без какого-либо трюка suid/sgid - это я ничего не знаю, как это сделать; лучшее, что я мог придумать, будет скрывать код.
В этой ситуации все, что пользователь мог бы обмануть в программе, они могли бы сделать и без помощи инструмента, поэтому попытка "защитить" от атак этого пользователя спорна. Ваше описание не читается так, как будто вам действительно нужна защита от атак.
Предполагая, что вам нужна защита, вы просто не можете полагаться на переменные среды - и если вы не можете reset вещи, такие как LD_LIBRARY_PATH
и LD_PRELOAD
, даже вызовы с абсолютными путями, такими как /bin/id
или /bin/ls
, не будут давать вы надежный ответ, если этот инструмент не статически скомпилирован. Вот почему sudo
имеет значение env_reset
по умолчанию и почему запуск suid-программ должен игнорировать определенные переменные среды. Обратите внимание, что это означает, что ваша точка, в которой TOOLS_PATH_LIBRARY
и PATH
в равной степени заслуживает доверия, может быть правдой в вашей ситуации, но не обязательно является истиной в случае с другими ситуациями: sysadmin может reset PATH
для sudo
использования, но пусть проходят нестандартные переменные среды.
Как указано выше, argv[0]
(или его bash эквивалент ${BASH_SOURCE[0]}
) не более надежна, чем переменные среды. Пользователь может не только сделать копию или символическую ссылку на ваш исходный файл; execve
или bash exec -a foo bar
позволяет помещать что-либо в argv[0]
.
Ответ 2
Хотя механизмы существуют в разных программах для предотвращения изменения переменных среды, в нижней строке нет, вы не можете доверять переменным окружения. Проблема безопасности очень проста:
В любое время, когда пользователь может изменить то, что ожидается для выполнения, возникает возможность использования уязвимости.
Случай-в-точке, посмотрите CVE-2010-3847. При этом недопустимый злоумышленник с доступом для записи в файловую систему, содержащую двоичные файлы setuid или setgid, может использовать этот недостаток для повышения своих привилегий. Он включает переменную среды, изменяемую пользователем.
CVE-2011-1095 - еще один пример и не содержит двоичные коды SUID. Сделайте поиск Google для "среды glibc cve", чтобы увидеть виды вещей, которые люди могли сделать с модификациями переменных среды. Довольно коварный.
Ваши проблемы действительно сводятся к вашему утверждению:
Пользователь может установить TOOLS_PATH_LIBRARY в библиотеку по своему выбору, но утилита будет работать под их uid. Они могли просто запустить свою вредоносную библиотеку напрямую с помощью bash.
Ключевая фраза здесь - запуск их вредоносной библиотеки. Это предполагает, что их библиотека также принадлежит их UID.
В этом случае система безопасности сделает вам много хорошего. Тот, который я написал, который сосредоточен исключительно на этой проблеме, вы можете найти здесь:
https://github.com/cormander/tpe-lkm
Модуль останавливает вызовы execve/mmap/mprotect на файлы, которые можно перезаписывать или не принадлежит доверенному пользователю (root). Пока они не могут помещать вредоносный код в файл/каталог, принадлежащий доверенному пользователю, они не могут использовать систему таким образом.
Если вы используете двоичные файлы SUID или sudo, которые включают эти переменные, вы можете подумать о том, чтобы включить "параноидальные" и "строгие" опции, чтобы остановить даже root из доверенных двоичных файлов, не принадлежащих root.
Я должен упомянуть, что этот метод проверки доверенного пути защищает прямое выполнение с помощью двоичных файлов и разделяемых библиотек. Он мало чем отличается от интерпретируемых языков, поскольку они анализируют байт-код и не выполняют его напрямую. Таким образом, вам по-прежнему нужна определенная степень осторожности с PYTHONPATH
, PERLLIB
, CLASSPATH
и т.д. И используйте упомянутые вами механизмы безопасности языка.
Ответ 3
Вы никогда не сможете доверять кому-то другому.
Почему бы просто не создать нового пользователя, который содержит весь этот важный код. Затем вы можете получить информацию непосредственно из /etc/passwd
или использовать синтаксис ~foo
, чтобы найти домашний каталог пользователя.
# One way to get home directory of util_user
DIR=$(/usr/bin/awk -F: '$1 == "util_user" {print $6}' /etc/passwd)
# Another way which works in BASH and Kornshell
[ -d ~util_dir ] && DIR=~util_dir
# Make sure DIR is set!
if [ -z "$DIR" ]
then
echo "Something wrong!"
exit
fi