Безопасный доступ к файлам в каталоге, определенном переменной среды?

StackOverflow https://stackoverflow.com/questions/196244

Вопрос

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

Это большой и длинный вопрос — я не уверен, насколько хорошо он соответствует парадигме SO.

Рассмотрим этот сценарий:

Фон:

  • Программный пакет PQR можно установить в любое место, выбранное пользователем.
  • Переменная среды $PQRHOME используется для идентификации каталога установки.
  • По умолчанию все программы и файлы в $PQRHOME принадлежат специальной группе pqrgrp.
  • Аналогично, все программы и файлы в $PQRHOME принадлежат либо специальному пользователю pqrusr, либо пользователю root (и это корневые программы с SUID).
  • Некоторые программы имеют SUID pqrusr;еще несколько программ — SGID pqrgrp.
  • Большинство каталогов принадлежат pqrusr и принадлежат pqrgrp;некоторые могут принадлежать к другим группам, и члены этих групп получают дополнительные привилегии при работе с программным обеспечением.
  • Многие из привилегированных исполняемых файлов должны запускаться людьми, не являющимися членами pqrgrp;программы должны подтвердить, что пользователю разрешено запускать их по загадочным правилам, которые не имеют прямого отношения к этому вопросу.
  • После запуска некоторые из привилегированных программ должны сохранять свои повышенные привилегии, поскольку они представляют собой долгоработающие демоны, которые могут действовать от имени многих пользователей в течение их жизни.
  • Программам не разрешено менять каталог на $PQRHOME по ряду загадочных причин.

Текущая проверка:

  • В настоящее время программы проверяют, что $PQRHOME и ключевые каталоги в нем «безопасны» (принадлежат pqrusr, принадлежат pqrgrp, не имеют публичного доступа для записи).
  • После этого программы получают доступ к файлам в $PQRHOME через полное значение переменной среды.
  • В частности, G11N и L10N достигаются путем доступа к файлам в «безопасных» каталогах и чтения строк формата для printf() и т. д. из файлов в этих каталогах, используя полный путь, полученный из $PQRHOME, плюс известную подструктуру ( например, $PQRHOME/g11n/en_us/messages.l10n).

Предположим, что значение $PQRHOME «как установлено» равно /opt/pqr.

Известная атака:

  • Злоумышленник устанавливает PQRHOME=/home/attacker/pqr.
  • На самом деле это символическая ссылка на /opt/pqr, поэтому, когда одна из программ PQR, назовем ее pqr-victim, проверяет каталог, у нее есть правильные разрешения.
  • Сразу после успешного завершения проверки безопасности злоумышленник меняет символическую ссылку так, чтобы она указывала на /home/attacker/bogus-pqr, который явно находится под контролем злоумышленника.
  • Ужасные вещи происходят, когда жертва pqr теперь обращается к файлу в предположительно безопасном каталоге.

Учитывая, что PQR в настоящее время ведет себя так, как описано, и представляет собой большой пакет (несколько миллионов строк кода, разработанный более десяти лет в соответствии с различными стандартами кодирования, которые в любом случае часто игнорировались), какие методы вы бы использовали для исправления ситуации? проблема?

Известные варианты включают в себя:

  1. Измените все вызовы форматирования, чтобы использовать функцию, которая проверяет фактические аргументы на соответствие строкам формата, с дополнительным аргументом, указывающим фактические типы, передаваемые в функцию.(Это сложно и потенциально чревато ошибками из-за огромного количества операций форматирования, которые необходимо изменить, но если функция проверки сама по себе исправна, она работает хорошо.)
  2. Установите прямой путь к PQRHOME и проверьте его безопасность (подробности ниже), отказав в запуске, если он небезопасен, и после этого используйте прямой путь, а не значение $PQRHOME (если они различаются).(Для этого требуется, чтобы все файловые операции, использующие $PQRHOME, использовали не значение из getenv(), а сопоставленный путь.Например, для этого потребуется, чтобы программное обеспечение установило, что /home/attacker/pqr является символической ссылкой на /opt/pqr, что путь к /opt/pqr безопасен, и после этого всякий раз, когда файл упоминается как $PQRHOME/some /thing используется имя /opt/pqr/some/thing, а не /home/attacker/pqr/some/thing.Это большая база кода, исправить которую не так-то просто.)
  3. Убедитесь, что все каталоги в $PQRHOME, даже отслеживаемые через символические ссылки, безопасны (подробности еще раз приведены ниже), и программное обеспечение отказывается запускаться, если что-то небезопасно.
  4. Жестко запрограммируйте путь к месту установки программного обеспечения.(Это не будет работать PQR;это превращает тестирование в ад, по крайней мере.Для пользователей это означает, что у них может быть установлена ​​только одна версия, а обновления и т. д. требуют параллельного запуска.Это не работает для PQR.)

Предлагаемые критерии безопасных путей:

  • Для каждого каталога необходимо доверять владельцу.(Обоснование:владелец может изменить разрешения в любое время, поэтому необходимо быть уверенным, что владелец не будет вносить случайные изменения, которые нарушат безопасность программного обеспечения.)
  • Для каждого каталога группа либо не должна иметь прав на запись (чтобы члены группы не могли изменять содержимое каталога), либо группа должна быть доверенной.(Обоснование:если члены группы могут изменять каталог, они могут нарушить безопасность программного обеспечения, поэтому либо они не должны иметь возможности изменить его, либо им нужно быть уверенным, что они не изменят его.)
  • Для каждого каталога «другие» не должны иметь права записи в этот каталог.
  • По умолчанию можно доверять пользователям root, bin, sys и pqrusr (при наличии bin и sys).
  • По умолчанию доверять можно группе с GID=0 (также известной как root,wheel или system), bin, sys и pqrgrp.Кроме того, можно доверять группе, владеющей корневым каталогом (которая в MacOS X называется admin).

POSIX-функция realpath() предоставляет службу сопоставления, которая сопоставляет /home/attacker/pqr с /opt/pqr;он не выполняет проверку безопасности, но ее необходимо выполнять только на разрешенном пути.

Итак, с учетом всего этого, существует ли какое-либо известное программное обеспечение, которое проходит через смутно связанные циклы, чтобы обеспечить свою безопасность?Это чрезмерная паранойя?(Если да, то почему – и вы действительно уверены?)

Отредактировано:

Спасибо за различные комментарии.

@С.Лотт:Атака (описанная в вопросе) означает, что по крайней мере одна корневая программа setuid может использовать строку формата по выбору (непривилегированного) пользователя и может, по крайней мере, привести к сбою программы и, следовательно, наиболее вероятно может получить корневую оболочку.К счастью, для этого требуется доступ к локальной оболочке;это не удаленная атака.Для этого требуется немалое количество знаний, но я считаю неразумным предполагать, что таких знаний нет «где-то там».

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

Это было полезно?

Решение

Вариант 2 работает, если вы напишете новое значение для $PQRHOME после определения его реального пути и проверки его безопасности.Таким образом, после этого потребуется изменить очень небольшую часть вашего кода.

Что касается сохранения привилегий setuid, было бы полезно, если бы вы могли сделать какое-то разделение привилегий, чтобы любые операции, включающие ввод данных от реального пользователя, выполнялись под реальным uid.Затем привилегированный процесс и процесс реального uid обмениваются данными, используя socketpair или что-то в этом роде.

Другие советы

Ну, это звуки параноик, но так это или нет, зависит от того, на какой системе(ах) работает ваше приложение и какой ущерб может нанести злоумышленник.

Итак, если ваша база пользователей, возможно, враждебна и если ущерб, возможно, очень велик, я бы выбрал вариант 4, но модифицированный следующим образом, чтобы устранить его недостатки.

Позвольте мне процитировать две важные вещи:

1)

В настоящее время программы проверяют, что $ pqrhome и ключевые каталоги под ним являются «безопасными» (принадлежащие PQRUSR, принадлежат PQRGRP, не имеют публичного доступа к записи).

2)

После этого программы получают доступ к файлам под $ pqrhome через полную стоимость переменной среды.

На самом деле вам не нужно жестко запрограммировать полный путь, вы можете жестко запрограммировать только относительный путь от «программы», которую вы упомянули в 1), до пути, упомянутого в 2), где находятся файлы.

Проблема для контроля:

а) вы должны быть уверены, что нет ничего «доступного для злоумышленника» (например,с точки зрения символических ссылок) между путем к исполняемому файлу и путем к файлам

б) вы должны быть уверены, что исполняемый файл надежно проверяет свой путь, но это не должно быть проблемой во всех известных мне Unix-системах (но я не знаю их всех и не знаю Windows совсем).


ОТРЕДАКТИРОВАНО после третьего комментария:

Если ваша ОС поддерживает /proc, системная ссылка /proc/${pid}/exe — лучший способ решить проблему б)


Отредактировано после сна на нем:

Является ли установка «безопасным» процессом?В этом случае вы можете создать (во время установки) сценарий-оболочку.Этот сценарий должен быть исполняемым, но не доступным для записи (и, возможно, не доступным для чтения).Он установит для переменной env $PQRHOME «безопасное» значение, а затем вызовет вашу реальную программу (в конечном итоге она может делать и другие полезные вещи).Поскольку в UNIX переменные среды запущенного процесса не могу быть изменено чем-либо еще, кроме запущенного процесса, вы в безопасности (конечно, переменные окружения может быть изменено родителем до процесс запускается).Однако я не знаю, работает ли этот подход в Windows.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top