[FreeBSD] Использование jail для предоставления shell доступа (freebsd chroot shell security web hosting)
Ключевые слова: freebsd , chroot , shell , security , web , hosting , (найти похожие документы )
From: Alexey Zakirov <frank@agava.com >
Date: Mon, 17 May 2004 18:21:07 +0000 (UTC)
Subject: [FreeBSD] Использование jail для предоставления shell доступа
Оригинал: http://hellbell.h1.ru/jail/
Использование jail(2) для предоставления untrusted shell access
Внимание! Нижеприведенные сведения, патчи и прочие материалы не
претендуют на какую-либо полноту изложения и истинность. Автор не
несет никакой ответственности за любое использование данного материала
На данный момент статья устарела. Используйте ссылки ниже.
- Vimage (http://www.tel.fer.hr/zec/BSD/vimage/ )
- Патчи для jail (http://garage.freebsd.pl )
- Lottery scheduler for FreeBSD (http://www-2.cs.cmu.edu/~dpetrou/research.html )
Содержание:
1. Краткое введение в jail(8).
2. Основные проблемы предоставления shell доступа для не доверенных
пользователей.
3. root скомпрометирован. Минимизация ущерба.
4. Вариант построения системы для бесплатного web хостинга.
5. Альтернативные решения.
Краткое введение в jail(2).
Системный вызов jail заключает процесс и всех его потомков в
изолированную среду выполнения. Это означает, что, в общем случае,
процесс не может иметь доступ ни к чему, не принадлежащему этому
jail-у. Более того, даже пользователь с uid 0 не имеет возможности
выполнять большинство операций, которые он может выполнять снаружи
jail-ла.
FreeBSD уже включает в базовую поставку достаточно полную
документацию, в числе: man-ы jail(2) и jail(8), а также статью
Poul-Henning Kamp и Robert N. M. Watson находящуюся в
/usr/share/doc/papers/jail.ascii.gz. Нет необходимости пересказывать
здесь целиком содержимое упомянутых документов, поэтому упомянем
только ключевые моменты, важные для обсуждаемых в данной статье
проблем.
Итак с каждым jail-ом ассоциирован 1 IP адрес и некая файловая
иерархия, в которую осуществляется chroot(2) во время исполнения
системного вызова jail(2).
Внутри jail-а концепция суперюзера несколько нивелируется, т.к. ему
запрещены следующие действия:
* Модификация запущенного ядра и загрузка ядерных модулей.
* Модификация любых сетевых конфигураций.
* Монтирование/размонтирование файловых систем.
* Создание файлов устройств (mknod).
* Доступ к raw, divert и routing сокетам.
* Модифицирование переменных ядра (sysctl).
* Изменение флагов файлов, связанных с securelevel (system flags).
* Доступ к сетевым ресурсам, не ассоциированным с IP адресом jail-а
(например нет localhost).
Остальные операции разрешены, однако есть еще один момент, не
упомянутый в оригинальной статье. Внутри jail-а не разрешено
присоединение к процессу и использование ptrace(2) (т.е. сказать в gdb
attach не удастся).
Таким образом мы видим, что ограничения внутри jail направлены на
уменьшение потенциальной возможности влияния изнутри jail-а на
ресурсы, ему не принадлежащие.
Основные проблемы предоставления shell доступа для не доверенных
пользователей.
Предоставление shell доступа не доверенным пользователям достаточно
сложная задача, которая может привести к постоянной головной боли у
системного администратора, обслуживающего эту систему. К счастью
функция jail-а и направлена во многом на упрощение этой задачи.
Рассмотрим основные проблемы, могущие возникнуть в public shell box-ах
и некоторые методы их решения. Какой же потенциальный вред могут
нанести пользователи, имеющие shell?
1. Устройство варезных файлопомоек с отдачей по http или ftp.
2. Установка не авторизованных сетевых сервисов: прокси серверов, irc
ботов и т.д.
3. Не авторизованное использование большого количества входящего или
исходящего трафика (например трейдинг на варезных irc каналах).
4. Неразрешенная сетевая активность, направленная против внешних
хостов (сканы, попытки удаленных взломов, релеинг спама через
внешние открытые релеи и т.д.).
5. Попытки спам-активности. Рассылка большого количества писем с
помощью mta, установленных на shell машине.
6. Попытки взлома локальной машины и получение повышенных привилегий.
7. Попытки устроить Denial-of-Service (DoS) для прекращения
нормального функционирования сервиса.
Как мы видим, все вышеупомянутые опасности можно разделить на 3
группы: сетевые, почтовые и локальные. С достаточной степенью
надежности можно решить только некоторые эти проблемы. В данном
разделе мы не рассматриваем получение root-а внутри jail-а (это тема
следующего пункта) и считаем, что пользователь - обычный
непривилегированный.
Сетевые возможности
-------------------
С точки зрения безопасности наилучшим способом предотвратить весь этот
класс угроз можно было бы не предоставляя пользователям доступа в
интернет вообще. Однако сделать это необходимо таким образом, чтобы
сервисы типа ftp , http, ssh продолжали работать без проблем.
Сразу приходит в голову очевидное решение: использовать возможность
встроенного во FreeBSD пакетного фильтра ipfw(8) осуществлять
фильтрацию пакетов на основе uid/gid процесса принимающего или
передающего пакет. Однако при этом (если бы мы захотели работать с
правилами), нам пришлось бы иметь все эти uid/gid, кроме jail-а еще и
в основной системе. Кроме того, основную проблему в таком решении
составил бы пассивный режим в ftp. Если хотим разрешить ftpd принимать
коннекты в jail (для пассивного режима), то мы автоматически разрешаем
пользователю сажать другие принимающие коннекты процессы на порты,
определяемые во FreeBSD sysctl-лями группы net.inet.ip.portrange.
Более того, чтобы работал активный режим ftp нам придется разрешить и
исходящие коннекты наружу.
Вариант решения этой проблемы рассмотрен в примере построения public
web hosting далее.
Почтовые проблемы
-----------------
Нежелание получать тонны писем на abuse@ должно привести нас к решению
проблемы - как не допустить пользователю спамить ни через локальный
mta, ни через внешние открытые релеи.
Вот здесь на помощь приходят возможности фильтрации пакетов по uid/gid
процесса. Для начала мы запрещаем коннект на smtp порт локального mta
всем, кроме одного определенного пользователя. Этот пользователь
внутри jail-а должен иметь возможность сабмитить письма внутрь системы
mta. Это можно сделать путем расстановки нужных прав доступа на
maildrop директорию и сам command line агент. Агент должен
представлять из себя оболочку для стандартной программы (например
sendmail), которая проверяет частоту посылания писем пользователем и
количество получателей письма.
Таким образом, используя специальный wrapper, мы можем регулировать
доступ пользователей к посылке почты вообще и регуляцию ее потока в
частности на индивидуальной основе.
Локальные проблемы
------------------
Следует отдавать себе отчет, что в public unix системах обычно
регулярно происходят попытки взлома и DoS, использующие широко
публикуемые эксплойты. Защитится от неизвестного вам эксплойта
практически невозможно. Защиты, основанные на неисполняемом стеке не
дают стопроцентной гарантии. Кроме того для FreeBSD не существует
аналога широко известного патча для ядра Linux от Solar Designer. Из
известных решений для FreeBSD есть патч для gcc, который позволяет
отслеживать ситуации срыва стека, однако он требует пересборки всех
требующих защиты программ.
При построении shell системы следует исходить из минимизации
привилегий. Основными точками приложения атак являются sugid программы
и демоны. Следует регулярно проверять списки рассылки типа bugtraq и
freebsd-security для контроля наличия дырок в используемом вами ПО.
Защита от попыток вывода системы из строя тоже достаточно сложна.
Использование лимитов обязательно для всех пользовательских процессов.
Во FreeBSD существует стандартная система в виде /etc/login.conf, где
прописываются классы пользователей. Не следует забывать, что, к
примеру, тотальный лимит на память, выделяемую через *alloc для всех
процессов пользователя, должен вычисляться из условия
maxproc*datasize.
На момент написания данной статьи во FreeBSD были еще не решены
некоторые проблемы лимитов. В частности это касалось преаллокируемой
памяти в elf бинарниках и общего количества виртуальной памяти. Данную
проблему описывает PR/18209, он же содержит в себе url с патчами,
решающими эти проблемы.
root скомпрометирован. Минимизация ущерба.
-----------------------------------------
Решив поддерживать shell box с публичным доступом, надо четко
понимать, что как в шутке про Неуловимого Джо, который оставался
неуловимым только до тех пор, пока он был никому не нужен, так и в
shell box-ах можно утверждать, что они не скомпрометированы только
пока за вас не взялись всерьез. Поэтому наиболее важной проблемой
становится минимизация последствий компрометации безопасности вашей
юникс системы. Вот тут то и становятся видны основные достоинства
jail-а.
Попробуем перечислить возможные последствия получения не
авторизованной персоной привилегий суперюзера внутри jail-а.
1. Получение не авторизованного доступа к закрытым данным внутри
jail-а. К сожалению защититься от этого на текущих версиях FreeBSD
нельзя, т.к. суперюзер имеет доступ (хотя бы на чтение) ко всем
ресурсам. Можно посоветовать не размещать закрытые данные,
компрометация которых может привести к нежелательным последствиям
внутри shell box-ов, к которым имеют доступ люди с недостаточной
степенью доверия.
2. Попытка получения доступа к ресурсам, не принадлежащим к текущему
jail-у. В данный момент способов выхода из правильно
организованного jail-а неизвестно. Невозможность выхода из jail-а
обусловлена особенностями привилегий суперюзера внутри. Он не
может ни создать файлы устройств (mknod) ни произвести
монтирование/размонтирование файловых систем. Кроме того, сетевые
возможности jail-а ограничены его ip адресом, что также уменьшает
вероятность влияния на чужие сетевые ресурсы.
3. Троянизация системы с целью облегчения дальнейшего доступа или
запуска не разрешенных ранее сервисов или изменение их набора. И
тут возможности jail-а сильно облегчают решение этой проблемы.
Системные флаги для файловой системы не допускают изменения и
снятия изнутри jail-а. Это позволяет выставить schg,sunlnk для
всех файлов, изменение которых не предполагается внутри системы.
Также возможно подмонтирование основных файловых иерархий внутрь
jail-а в режиме readonly. Т.к. операции монтирования запрещены
внутри jail-а, то даже суперюзер не сможет получить доступ на
запись к системным файлам и директориям.
4. Не авторизованное использование сетевых ресурсов. При определенной
организации системы этого легко не допустить. Способ будет
рассмотрен в следующем разделе.
5. Не авторизованное изменение данных других пользователей. В
существующей концепции security в юникс избежать этого практически
невозможно.
6. Denial-of-Service. К сожалению реализация jail(2) во FreeBSD не
позволяет выставлять лимиты на jail целиком. Поэтому суперюзер
внутри jail-а имеет потенциальную возможность использовать так
много ресурсов (кроме дисковых), как ему захочется. Следует
заметить, что путем правильного распределения лимитов для рута и
патчем к ядру, запрещающим поднятия лимитов внутри jail-а можно
добиться некоторой степени защиты от потенциального DoS-а, но, к
сожалению, не стопроцентной.
7. Не авторизованный доступ к почтовой системе. Защитится от этого
практически невозможно.
Как мы видим, не авторизованное получение привилегий суперюзера внутри
jail-а остается серьезной проблемой для держателей shell box-ов.
Однако использование jail-а позволяет нам значительно уменьшить
возможный ущерб и свести к минимуму время восстановления системы.
Вариант построения системы для бесплатного web хостинга.
--------------------------------------------------------
В этом разделе мы рассмотрим пример построения shell box-а,
предназначенного для раздачи бесплатного web хостинга. Данная статья
не направлена на рассмотрение всех вопросов возникающих в процессе
подготовки подобной системы, поэтому вопросы, непосредственно не
связанные с темой статьи (типа конфигурации apache) рассмотрены не
будут.
Итак мы хотим построить систему, позволяющую пользователям размещать
web сайты в Интернет и имеющую следующие характеристики:
* Пользователь имеет возможность размещения web страниц на сайте с
выбранным им самим именем.
* Пользователь может исполнять cgi написанные на любых доступных
внутри системы языках (c, c++, perl, tcl, sh, php etc...).
* Пользователь имеет доступ к различным сервисам: mysql, sendmail и
т.д..
* Мы не хотим иметь проблем от пользователей в виде спама,
нелегальной сетевой активности, влияния друг на друга и т.д.
Рассмотрим построение такой системы по шагам. Для облегчения понимания
на рисунке 1 (http://www.opennet.dev/soft/gen_scheme.gif ) представлена
схема такого хостинга. Если проанализировать наши требования к системе,
то говоря упрощенно нам нужен shell box с запущенным апачем и отрезанным
доступом к сети.
Совершенно очевидно, что для обеспечения работы такой системы нам
понадобится несколько виртуальных хостов/jail-ов (далее VE). Сразу
можно выделить следующие необходимые VE:
* shell. Основной VE в который логинятся пользователи и который
содержит web сервер, отдающий документы и исполняющий CGI.
* database. VE содержащий процесс sql сервера mysql.
* tech. Технологический VE предназначенный для запуска процессов,
работающих с закрытой информацией. Пример такого процесса -
баннерный сервер, выдающий баннерный код для пользователей.
* master. Основная реальная машина, в которой исполняются действия,
недоступные из jail-ов, например выставление дисковой квоты.
Далее рассмотрены шаги решения специфичных для данного применения
проблем.
Отрезание доступа к сети.
Как уже было упомянуто ранее, во FreeBSD существует возможность
фильтрации IP пакетов на основе uid/gid пользователя. На первый взгляд
это решило бы проблему, однако при тщательном рассмотрении мы видим
очевидные слабости подобного подхода. Во-первых мы не можем обеспечить
одновременную работу обоих режимов ftp (active/passive) и запрет на
сетевую активность пользователя. Да, протокол ftp весьма несовершенен,
но это стандарт и мы не хотим лишить часть пользователей (сидящих за
firewall-ами) возможности использовать ftp для обновления сайта.
Во-вторых, в случае компрометации суперюзера, он сможет использовать
возможность манипулирования пользовательскими полномочиями для
получения сетевого доступа.
Решение этой проблемы лежит в использовании способности jail-а
ассоциировать VE только с одним IP адресом. Концепция "наложенных" VE
очень проста. Мы запускаем два jail-а, которые имеют разные hostname и
разные IP адреса, но при этом имеют одну и ту же файловую иерархию.
Это позволяет нам выделить "внутренний" и "внешний" VE. Внешний VE
содержит все сервисы, требующие сетевого доступа, а внутренний
представляет из себя среду выполнения пользовательских процессов и
использует fake IP адрес (для надежности). Следующие сетевые сервисы
мы должны предоставить пользователю:
1. http. Внутренний jail содержит apache, который забинден на fake
адрес. Внешний же содержит http proxy, использующийся в режиме
http accelerator. Это позволяет уменьшить количество "дорогих"
процессов апача и предоставляет доступ снаружи во внутренний jail.
2. ftp. Во внешнем jail-е запущен inetd со сконфигурированным
запуском ftpd. Таким образом ftpd виден снаружи и позволяет
использовать все режимы работы. (*) Замечание: для предотвращения
устройства на хостинге файлопомоек может понадобиться пропатчить
ftpd на предмет запрещения скачивания файлов.
3. ssh. sshd пускается во внутреннем fake jail-е. Чтобы логинится в
него из внешнего мира, во внешнем jail-е запущен generic tcp
proxy, который прокидывает запросы на внутренний sshd.
4. sql. В специальном jail-е с fake IP адресом запущен mysqld. Ничего
необычного в setup-е этого jail-а нет. Пользователи ходят из
внутреннего shell-а на database jail по tcp.
5. Почта. mta и pop3/imap демоны пускаются внешнем jail-е. mta
запускается в режиме relay only, т.е. все почту он отсылает на
находящийся в технологическом jail-е другой mta, который уже и
отсылает письма во внешний мир.
Таким образом мы видим, что пользователь имеет доступ ко всем
необходимым ему сервисам, но не имеет выхода в интернет. По своему
опыту я могу сказать, что много раз находил у пользователей исходные
тексты всевозможных прокси, сетевых сканеров и сетевых эксплойтов,
которые они пытались использовать для нелегальной сетевой активности.
Очевидно, что все эти попытки были безуспешны.
Лимиты, лимиты, лимиты.
Второй по важности проблемой внутри jail-а является предотвращение
DoS-ов, которые в основном связаны с превышением лимитов на ресурсы
(такие как cpu time, используемая память и т.д.).
Следует сразу сказать, что во FreeBSD не решена проблема с установкой
лимитов на общее количество virtual memory, аллоцируемой
пользователем. Существует патч (http://www.redline.ru/~jason/bsd.html ),
сделанный Dmitry Kim (jason at express.ru) , который решает эту проблему.
Его установка обязательна. После этого мы можем сказать (на первый взгляд),
что проблема лимитов для common users решена.
Далее нам следует решить как распределить лимиты. Очевидно, что мы
создаем некоторый класс пользователя в login.conf, который достаточен
для нормальной деятельности, но не позволяет пользователю совершать
действия, могущие привести к нежелательным последствиям. На опыте мы
пришли к таким ограничениям (http://hellbell.h1.ru/jail/files/limits.conf )
(95% пользователей хватает этих лимитов для нормального размещения своих
сайтов). В приведенном куске /etc/login.conf параметр sessiontime
используется для ограничения времени работы CGI приложений пользователя
(его читает suexec).
Следующая проблема: superuser. Получение superuser-ских полномочий
внутри jail-а ведет к неограниченному получению ресурсов системы
(кроме дисковых квот). Эту проблему можно решить (только в очень
специфичных случаях) установкой запрета на модификацию master.passwd и
login.conf и выставлением root-у своего, ограниченного класса. К
сожалению это будет работать только с помощью гипотетического патча,
запрещающего увеличивать лимиты на ресурсы внутри jail-а. Для тех, кто
решил это попробовать, надо покопаться в /sys/kern/kern_resource.c в
dosetrlimit (в районе 404 строчки).
Итак пользователи ограничены. Суперюзер принят как неизбежный риск.
Остается решить проблему с apache, т.е. с запуском CGI. Существует
очень простой патч для apache suexec, описанный в PR/13606, который,
используя setusercontext(3), устанавливает необходимые лимиты для
процесса CGI, который исполняется apache сервером.
Данная технология достаточна для предотвращения большинства
злонамеренных попыток DoS. Например классическая fork-бомба в данной
ситуации просто будет непрерывно висеть, пытаясь породить процессы, но
не причинит особого вреда, т.к. через некоторое время ее приоритет
будет понижен и реальной загрузки системы она создавать не будет.
Таким образом мы видим, что проблему DoS-ов можно решить, но без 100%
гарантии.
Распределение полномочий внутри shell box-а.
Здесь мы кратко рассмотрим распределение unix permissions внутри
jail-а. Наша задача обеспечить доступ пользователя только к незакрытым
данным и предотвратить доступ к данным, могущим повлиять на закрытость
системы.
На самом деле это не так важно, ибо мы всегда закладываемся на
нежелательного суперюзера внутри jail-а. Решение этой задачи лежит в
правильном расставление прав доступа к файлам на fs. Данная проблема
не входит в рамки данной статьи, скажем только, что пользователь не
должен иметь доступ ни к чему, что ему не нужно для работы. Например
/usr/local/etc/rc.d должен иметь permission 0700 и все файлы внутри
тоже должны иметь 0700 в качестве маски доступа.
Любой администратор подобной системы должен проанализировать
компоненты системы (скрипты, конфигурации и т.д.) и расставить нужные
полномочия исходя из принципа least privileges.
Организация раздачи web контента через apache. suexec.
Рассмотрим теперь проблемы, специфичные для организации именно web
хостинга в свободном доступе. Конкретные условия, которые мы хотим
обеспечить пользователям:
* Недоступность содержимого домашних каталогов пользователей (т.е.
их web контента и сопутствующих файлов) другим пользователям.
* Безопасную работу CGI (т.е. устранение необходимости делать 0777
для рабочих каталогов).
* Исполнение php скриптов.
Рассмотрим эти проблемы подробнее. Итак мы сошлись на том, что
пользователь исполняет свои CGI от своего gid и uid. Соответственно
ему можно использовать каталоги, расположенные внутри его домашнего
каталога и не доступные для других пользователей.
Проще всего это рассмотреть на примере распределения permissions
внутри jail-а для домашних каталогов пользователей. Ниже представлен
дамп mtree (http://hellbell.h1.ru/jail/files/homes.mtree ) и
"ls -lRa" (http://hellbell.h1.ru/jail/files/homes.ls-lR ) (возможно более нагляден)
для опытной схемы. Пояснения: apache запущен от пользователя
webserver:webserver. Все пользователи (user1 - userN) имеют primary
группу hosting.
Видно, что при таком распределении пользователи имеют доступ только к
своим каталогам и apache имеет возможность отображать контент из
домашних каталогов пользователей.
Специфичные проблемы и методы их решения.
При организации VE на основе jail(2) возникают некоторые специфичные
проблемы. Здесь мы попробуем их раскрыть, хотя это не готовый рецепт,
а только пути решения.
Read Only файловые иерархии
Одной из основных проблем, встречающихся при организации jail-ов,
является экономия дискового пространства на "общие" данные.
Действительно, зачем бессмысленно держать несколько десятков
одинаковых файловых иерархий, которые не требуют модификации во время
работы, но при этом требуют регулярного maintenance. Эта проблема
должна решаться путем разделения набора данных в каждом jail-е на
read-only и working. Первый представляет из себя не модифицируемый
набор данных: бинари, библиотеки, общие данные. Модификацию его
производит только администратор, следовательно для этого подходит
sharing данных, который помогает создать jail(2). Что можно включить в
эту часть? По опыту своего использования подобных сред я могу выделить
следующие категории данных (файловых иерархий): /usr (целиком),
/bin;/sbin;/dev, /kernel. Никто из них не обязан быть доступным на
модификацию никому внутри jail-а.
Организовать это достаточно просто, благо jail(2) предоставляет для
этого все возможности. Итак мы хотим сделать несколько файловых
иерархий внутри jail-а недоступными на модификацию даже суперюзеру:
1. mount_nfs. Мы может подмонтировать подготовленную файловую
иерархию в jail (например в /.invisible) по NFS с опцией ro с
"мастер" хоста и сделать необходимые симлинки внутри jail-а (/bin
-> /.invisible/bin и т.д.).
2. Multiple mount_ufs in RO mode. Существует патч для ядра,
http://hellbell.h1.ru/jail/files/multi_mount_ro.diff
который использует возможность монтирования ufs разделов в RO
режиме более одного раза. Я использовал этот патч (приведенный
только для 4.x) с 3.x вплоть до 4.3-stable.
3. mount_nullfs. К сожалению данная файловая система может считаться
с натяжкой стабильной только в current. Попытки ее использования
для данной цели на 4.x ни к чему хорошему не привели.
4. mount_union. Здесь ситуация гораздо лучше. В RO режиме можно
использовать union практически без ограничений, подмонтировав его
в "master" каталог и раздав его в ro для jail-ов.
PHP
Очень популярное средство разработки web сайтов, которое приносит
много проблем. Модуль PHP, встраиваемый в apache, содержит некоторые
средства ограничения памяти и времени работы для скриптов, но ни один
нормальный админ не будет доверять таким встроенным средствам
контроля.
Обеспечить исполнение PHP скриптов достаточно просто - исполнять их
как CGI приложение, на общих лимитах системы для данного пользователя.
Проблемой остается - как скрыть это от пользователя? Первое и сразу
приходящее решение - закодировать нужную функциональность в комбинацию
apache/suexec. Пусть все файлы с расширениями *.php и т.д. считаются
apache-м CGI приложениями и пусть он будет пытаться исполнять их как
скрипты, через механизм suexec.
Все остальное очевидно. Мы добавляем в suexec функциональность,
которая вместо попыток запуска скрипта исполняет интерпретатор PHP со
скриптом подаваемым ему на вход.
Другой, очень красивый, способ состоит в модификации лимитов процесса
на лету. Представим себе syscall, который при вызове его суперюзером
позволяет поменять текущие лимиты любому процессу на основе
информации, содержащейся в классе пользователя (login.conf). Сервер
apache, перед исполнением PHP скрипта делает запрос через (например)
unix-domain сокет к демону, запущенному от суперюзера, с просьбой
выставить ему нужные лимиты. После отработки запроса - вернуть лимиты
в исходное состояние. Демон же, идентифицирует запросы через
credentials процесса, который соединяется с ним через сокет.
Существует реализация ядерного модуля для такого syscall-а и пример ее
использования. Осталось допатчить apache :) и написать credential
change daemon.
Ограничение времени работы CGI скриптов
Мы не можем позволить пользователю блокировать "дорогой" процесс
apache скриптом типа "for(;;){}". Чтобы ограничить время исполнения
скриптов пользователя нам необходимо (опять) модифицировать suexec.
Перед исполнением реального скрипта мы форкаемся и родитель сидит в
alarm/waitpid и следит за временем работы child. Если время
исчерпалось, посылается kill. Многие тут же скажут, что достаточно
форкнуться еще раз и сделать daemon(3), чтобы оставить процесс в
background. Так вот - нас это не интересует. Пусть пользователь сажает
что угодно в бэкграунд, дальше своих лимитов он не уедет, а экземпляр
apache это освободит.
30K строк в /etc/master.passwd
К счастью для FreeBSD это не является проблемой, благодаря
эффективному механизму /etc/spwd.db.
Однако проблемой остается манипуляция таким passwd. Видимо есть только
два варианта решения: nis (в общем смысле, это может быть pam, ldap,
nsswitch etc..) и специализированные инструменты манипулирования
/etc/master.passwd.
Первый способ, в данный момент плохо реализуем из-за убогой реализации
pam и отсутствия nsswitch. Второй очевиден - писать утилиты,
манипулирующие с passwd базами эффективным способом.
Disk quota для jail
Как уже было упомянуто выше, в jail не доступен syscall quotactl(2),
который управляет установкой дисковых квот. Единственным способом
установки квот остается установка их из master машины.
Классический вариант решения - демон в мастер машине, слушающий
unix-domain сокеты в каждом jail-ле и выполняющий команды по
установке, поступающие из jail-а.
Естественно демон должен проверять разрешенность команд. Можно
выделить следующие, требующие проверки, условия:
* Откуда пришел вызов - не авторизованные для данных команд jail-ы
игнорируются.
* На какой uid пришел запрос. Только uid, относящиеся к данному
jail-у могут могут изменять свою квоту.
* Не превышает ли единичный запрос максимальную квоту для данного
jail-а.
* Не превышает ли общая (калькулируемая) квота максимальной квоты
для данного jail-а.
Тоже самое может быть решено с помощью ssh.
SYSVSHM
Однозначно, на машине с jail-ами в ядре не должно быть опции SYSV* в
ядре.
К сожалению, в текущей реализации jail(2) не сделана "jail-ификация"
SYSVSHM и т.д. Таким образом SYSVSHM является общей для всех jail-ов и
не рекомендован к использованию.
Однако по опыту использования, крайне малое количество пользователей
(менее 0.1%) нуждается в этой возможности, поэтому мы отбрасываем
msg*(3), как возможность, плохо поддающуюся контролю.
Альтернативные решения.
Наиболее серьезным решением из альтернатив является HSPLinux
(www.swsoft.ru). Множество возможностей выгодно выделяют его среди
аналогов. К сожалению цена (несколько десятков тыс. долларов) доступна
только большим компаниям.
Заключение
Таким образом мы видим, что jail(2) может сильно облегчить решение
некоторых специфичных задач интернет-серверов, особенно, при
предоставлении доступа не доверенным пользователям.
Если вы заметили какие-то неточности, ошибки или недоработки данной
статьи (не претендующей ни на какие абсолютные истины или рецепты),
пожалуйста напишите автору ваши вопросы/пожелания на адрес, указанный
ниже.
P.S. Данная технология используется для построения free public web
hosting с 1999 года и я могу утверждать, что на данном этапе jail(2)
наиболее доступный способ решения security проблем в таких системах.
© 2001 Alexey Zakirov <frank at agava.com>
limits.conf:
shell:\
:cputime=20s:\
:datasize=4M:\
:stacksize=1M:\
:memorylocked=2M:\
:memoryuse=6M:\
:sbsize=1M:\
:filesize=4M:\
:coredumpsize=0M:\
:openfiles=12:\
:maxproc=24:\
:priority=2:\
:sessiontime=30s:\
:tc=default:
multi_mount_ro.diff (монтирование RO FS более одного раза):
--- sys/sys/fcntl.h.orig Mon Mar 20 11:00:39 2000
+++ sys/sys/fcntl.h Mon Mar 20 11:00:24 2000
@@ -93,6 +93,7 @@
#define FMARK 0x1000 /* mark during gc() */
#define FDEFER 0x2000 /* defer for next gc pass */
#define FHASLOCK 0x4000 /* descriptor holds advisory lock */
+#define FMOUNTING 0x8000 /* a block device is being mounted */
#endif
/* Defined by POSIX 1003.1; BSD default, but must be distinct from O_RDONLY. */
--- sys/ufs/ffs/ffs_vfsops.c.orig Mon Jan 10 15:04:25 2000
+++ sys/ufs/ffs/ffs_vfsops.c Mon Mar 20 12:52:35 2000
@@ -572,24 +572,26 @@
dev = devvp->v_rdev;
cred = p ? p->p_ucred : NOCRED;
+ ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
/*
- * Disallow multiple mounts of the same device.
+ * Only allow multiple read-only mounts of the same device.
* Disallow mounting of a device that is currently in use
* (except for root, which might share swap device for miniroot).
* Flush out any old buffers remaining from a previous use.
*/
- error = vfs_mountedon(devvp);
+ error = ronly ? 0 : vfs_mountedon(devvp);
if (error)
return (error);
ncount = vcount(devvp);
-
- if (ncount > 1 && devvp != rootvp)
+ if (!ronly && ncount > 1 && devvp != rootvp)
return (EBUSY);
- vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
- error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
- VOP_UNLOCK(devvp, 0, p);
- if (error)
- return (error);
+ if (ncount <= 1) {
+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
+ VOP_UNLOCK(devvp, 0, p);
+ if (error)
+ return (error);
+ }
/*
* Only VMIO the backing device if the backing device is a real
@@ -604,9 +606,9 @@
VOP_UNLOCK(devvp, LK_INTERLOCK, p);
}
- ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
- error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
+ error = VOP_OPEN(devvp,
+ ronly ? FMOUNTING|FREAD : FMOUNTING|FREAD|FWRITE, FSCRED, p);
VOP_UNLOCK(devvp, 0, p);
if (error)
return (error);
@@ -711,6 +713,7 @@
for (i = 0; i < MAXQUOTAS; i++)
ump->um_quotas[i] = NULLVP;
devvp->v_specmountpoint = mp;
+ if (!ronly) devvp->v_writecount++;
ffs_oldfscompat(fs);
/*
@@ -824,10 +827,12 @@
fs->fs_clean = 0;
return (error);
}
+ ump->um_devvp->v_writecount--;
+ }
+ if (vcount(ump->um_devvp) <= 1) {
+ ump->um_devvp->v_specmountpoint = NULL;
+ vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
}
- ump->um_devvp->v_specmountpoint = NULL;
-
- vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
NOCRED, p);
homes.ls-lR:
total 6
drwxr-xr-x 3 root wheel 512 Oct 3 23:33 .
drwxr-xr-x 21 root wheel 512 Oct 3 23:24 ..
drwxr-x--x 5 homemaster wheel 512 Oct 3 23:30 home
-rw-r--r-- 1 root wheel 0 Oct 3 23:33 homes.ls-lR
-rw-r--r-- 1 root wheel 2166 Oct 3 23:33 homes.mtree
./home:
total 5
drwxr-x--x 5 homemaster wheel 512 Oct 3 23:30 .
drwxr-xr-x 3 root wheel 512 Oct 3 23:33 ..
drwx--x--- 4 user1 webserver 512 Oct 3 23:24 user1
drwx--x--- 4 user2 webserver 512 Oct 3 23:26 user2
drwx--x--- 4 user3 webserver 512 Oct 3 23:26 user3
./home/user1:
total 4
drwx--x--- 4 user1 webserver 512 Oct 3 23:24 .
drwxr-x--x 5 homemaster wheel 512 Oct 3 23:30 ..
drwxr-xr-x 2 user1 hosting 512 Oct 3 23:26 cgi-bin
drwxr-xr-x 2 user1 hosting 512 Oct 3 23:25 www
./home/user1/cgi-bin:
total 4
drwxr-xr-x 2 user1 hosting 512 Oct 3 23:26 .
drwx--x--- 4 user1 webserver 512 Oct 3 23:24 ..
-rwxr-xr-x 1 user1 hosting 1968 Oct 3 23:26 vote.pl
./home/user1/www:
total 9
drwxr-xr-x 2 user1 hosting 512 Oct 3 23:25 .
drwx--x--- 4 user1 webserver 512 Oct 3 23:24 ..
-rw-r--r-- 1 user1 hosting 6582 Oct 3 23:25 index.html
./home/user2:
total 4
drwx--x--- 4 user2 webserver 512 Oct 3 23:26 .
drwxr-x--x 5 homemaster wheel 512 Oct 3 23:30 ..
drwxr-xr-x 2 user2 hosting 512 Oct 3 23:26 cgi-bin
drwxr-xr-x 2 user2 hosting 512 Oct 3 23:26 www
./home/user2/cgi-bin:
total 4
drwxr-xr-x 2 user2 hosting 512 Oct 3 23:26 .
drwx--x--- 4 user2 webserver 512 Oct 3 23:26 ..
-rwxr-xr-x 1 user2 hosting 1968 Oct 3 23:26 vote.pl
./home/user2/www:
total 9
drwxr-xr-x 2 user2 hosting 512 Oct 3 23:26 .
drwx--x--- 4 user2 webserver 512 Oct 3 23:26 ..
-rw-r--r-- 1 user2 hosting 6582 Oct 3 23:25 index.html
./home/user3:
total 4
drwx--x--- 4 user3 webserver 512 Oct 3 23:26 .
drwxr-x--x 5 homemaster wheel 512 Oct 3 23:30 ..
drwxr-xr-x 2 user3 hosting 512 Oct 3 23:26 cgi-bin
drwxr-xr-x 2 user3 hosting 512 Oct 3 23:26 www
./home/user3/cgi-bin:
total 4
drwxr-xr-x 2 user3 hosting 512 Oct 3 23:26 .
drwx--x--- 4 user3 webserver 512 Oct 3 23:26 ..
-rwxr-xr-x 1 user3 hosting 1968 Oct 3 23:26 vote.pl
./home/user3/www:
total 9
drwxr-xr-x 2 user3 hosting 512 Oct 3 23:26 .
drwx--x--- 4 user3 webserver 512 Oct 3 23:26 ..
-rw-r--r-- 1 user3 hosting 6582 Oct 3 23:25 index.html
1 , reaper (?? ), 14:32, 16/11/2007 [ответить ]
+ /–
если это кто-нибудь еще прочитает :)
поясните момент насчет sshd - раз 10 прочитал, все равно не доходит, что хотел сказать автор
3 , Daemony (? ), 07:03, 01/11/2008 [^ ] [^^ ] [^^^ ] [ответить ]
+ /–
Имелось в виду, что кроме всего прочего в том числе SSH соединения от fake jail'а назад к клиенту будут выходить не напрямую (поскольку из fake jail'а отрезаются все коннекты во внешний мир), а через прокси, запущенный в соседнем jail'е, который в отличии от фейкового имеет возможность выходить во внешний мир...
2 , Daemony (? ), 06:58, 01/11/2008 [ответить ]
+ /–
Спасибо. Статья зачетная!
И хоть попалась на глаза через 4.5 года после опубликования, многое почерпнул полезного и актуального по сегодняшний день.
4 , a55 (?? ), 03:54, 03/11/2008 [ответить ]
+ /–
© 2001 Alexey Zakirov <frank at agava.com>
Дочитал бы сначала ;)
5 , Daemony (? ), 08:53, 03/11/2008 [^ ] [^^ ] [^^^ ] [ответить ]
+ /–
>© 2001 Alexey Zakirov <frank at agava.com>
>
>Дочитал бы сначала ;)
Дочитал, дочитал. :)
Просто посмотрел сюда:
From: Alexey Zakirov <frank@agava.com>
Date: Mon, 17 May 2004 18:21:07 +0000 (UTC)
Subject: [FreeBSD] Использование jail для предоставления shell доступа