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

Кто-нибудь может указать на некоторый код, который имеет дело с безопасностью доступа к файлам через путь, определенный (частично) переменной среды, особенно для 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/ атакующий / pqr.
  • На самом деле это символическая ссылка на /opt/pqr, поэтому, когда одна из программ PQR, называемая pqr-жертва, проверяет каталог, она имеет правильные разрешения.
  • Сразу после успешного завершения проверки безопасности злоумышленник изменяет символическую ссылку, чтобы она указала на /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/ вещь. Это большая база кода - не тривиально исправить.)
  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 / злоумышленник / pqr с /opt/pqr; это не делает проверку безопасности, но это должно быть сделано только на разрешенном пути.

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

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

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

@ S.Lott: атака (обрисованная в общих чертах в вопросе) означает, что по крайней мере одна корневая программа setuid может быть использована для использования строки формата по выбору (непривилегированного) пользователя и может по крайней мере привести к аварийному завершению программы и, следовательно, наиболее вероятно, может получить корневая оболочка. К счастью, требуется локальный доступ к оболочке; это не удаленная атака. Требуется немалое количество знаний, чтобы попасть туда, но я считаю неразумным предполагать, что экспертиза не "там".

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

2 ответа

Решение

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

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

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

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

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

1)

В настоящее время программы проверяют, что $PQRHOME и каталоги ключей в нем "безопасны" (принадлежат pqrusr, принадлежат pqrgrp, не имеют публичного доступа для записи).

2)

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

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

Вопрос для контроля:

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

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


ИЗМЕНЕНО после 3-го комментария:

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


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

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

Другие вопросы по тегам