новости
статьи
.sysadmin

SELinux с нуля – интегрирование SELinux в Gentoo

SELinux - реализация мандатного контроля доступа от U.S. National Security Agency и наиболее известная подсистема безопасности в Linux. SELinux входит по умолчанию в установочные пакеты дистрибутивов Fedora и Red Hat Enterprise Linux, а также доступна в виде отдельных установочных пакетов для других дистрибутивов. В этой статье рассказывается о том, как преобразовать систему, не использующую SELinux, вручную, для того чтобы детально рассмотреть интеграцию SELinux в операционную систему.

введение

SELinux - это система мандатного контроля доступа (MAC) , доступная в ядрах Linux, начиная с версии 2.6. Модули безопасности Linux (SELinux) – это наиболее полное и хорошо протестированное решение, которое доступно, и это подтверждено 20-летними исследованиями в области MAC. SELinux сочетает многоуровневую безопасность с поддержкой множества категорий, ролевой контроль доступа.

Большинство людей, которые использовали SELinux, применяли готовый SELinux-дистрибутив – такой, как Fedora, Red Hat Enterprise Linux (RHEL), Debian или Hardened Gentoo. Все эти дистрибутивы содержат SELinux в ядре, предлагают настраиваемую политику безопасности и исправляют большое количество пользовательских библиотек и утилит, чтобы сделать их совместимыми с SELinux.

Если вы – один из множества пользователей, которые просто хотят, чтобы система работала как раньше, но была немного более безопасной, вы можете управлять SELinux, используя хорошо знакомые приложения, а политики безопасности писать на языке высокого уровня. Однако эти методы не годятся в случае, если что-то пойдет не так – например, если ядро и пространство пользователя рассинхронизируются. Также эти методы не дают никакого представления о том, как в действительности работает SELinux. В конце концов, инженерам и сотрудникам безопасности следует понимать, что существуют способы продвинутого применения SELinux, выходящего далеко за рамки тех приемов, которые используются в текущих дистрибутивах. В этой статье описывается, как конвертировать систему, которая изначально полностью несовместима с SELinux, в систему, поддерживающую SELinux.

предварительные требования

Чтобы начать, вам потребуется:

1. QEMU - свободно распространяемый и простой в использовании эмулятор процессора. Это отличная возможность поиграть с новыми ядрами или образами системы, не нанося ущерба вашей реальной системе.

2. Gentoo - дистрибутив Linux, базирующийся на исходниках. Gentoo - это идеал для таких упражнений.

Сделайте образ диска, набрав команду:

qemu-img create -f raw gentoo.img 2G

Следующий шаг – установка QEMU на раздел дискового образа и форматирование одиночного раздела. Это потребует несколько видов загрузочных CD с Linux. Knoppix вполне подойдет, равно как и Gentoo liveCD.

Для более простых ссылок далее – и чтобы меньше набирать – вы можете переименовать образ:

mv install-x86-minimal-2005.1.iso gentoo.iso

Сконфигурируем QEMU для загрузки нашего мини-линукса.

qemu -hda gentoo.img -cdrom gentoo.iso -boot d

Приступим к разметке образа диска:

fdisk /dev/hda
n
p
1
(return)
w


Вышеприведенный листинг создаст один новый (n) первичный (p) раздел, начинающийся с блока 1 (1) и заканчивающийся блоком по умолчанию, который является последним блоком на файловой системе. Затем он записывает (w) новую таблицу разделов на образ диска.

Теперь вернитесь в оболочку QEMU и наберите:

mkfs.ext2 /dev/hda1

Может потребоваться сделать это дважды, чтобы дать udev возможность создать устройство. Затем выключите систему, набрав:

poweroff

Это вернет вас в вашу реальную систему. Если этого не произошло и все зависло на длительное время, нажмите Ctrl-c для завершения процесса. Следующий шаг – установка базового дистрибутива на образ диска. Причина, почему Gentoo отлично подходит для этого упражнения, в том, что вы можете просто загрузить и распаковать образ stage 3 и сразу же получить функциональность системы Gentoo.

Чтобы распаковать архив со stage 3 на ваш дисковый образ, сначала смонтируйте образ диска в вашей системе. Следующий листинг монтирует пустую файловую систему и распаковывает на нее тарболл.

su (give root password)
ORIG=`pwd`
mount -oloop,offset=32256 gentoo.img /mnt
cd /mnt
tar jxf $ORIG/stage3-x86-2005.1.tar.bz2


Когда образ уже смонтирован, остается еще несколько вещей, о которых нужно позаботиться. Файл /etc/fstab указывает, какая файловая система где смонтирована. Для этой простой системы не нужны разделы boot или swap. Следующий листинг удаляет их и добавляет правильные значения для корневого раздела. Он также устанавливает пароль пользователя root. При запуске passwd убедитесь, что вы запомнили введенный пароль. Безопасность для этой игрушечной системы особо не нужна, поэтому что-то типа "password" вполне подойдет :)

mv /mnt/etc/fstab /mnt/etc/fstab.orig
sed -e '/[BR]OOT/d' -e '/SWAP/d' /mnt/etc/fstab.orig > /mnt/etc/fstab

cat >> /mnt/etc/fstab <7lt; EOF
/dev/hda1 / ext2 noatime 0 1
EOF

chroot /mnt
passwd
exit

cd $ORIG
umount /mnt


Ядро нужно для загрузки образа QEMU. Просто скомпилируйте его с поддержкой SELinux, даже если вы не хотите использовать SELinux прямо сейчас. Возьмите копию linux-2.6.14.tar.bz2 (или последнюю версию) с kernel.org и распакуйте ее. Затем зайдите в каталог Linux-2.6.14 и сконфигурируйте ядро. Обязательно включите следующие опции:

CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_SECURITY=y

CONFIG_SECURITY=y
CONFIG_SECURITY_CAPABILITIES=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_SECURITY_SELINUX_DEVELOP=y
CONFIG_SECURITY_SELINUX_AVC_STATS=y
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1


Теперь скомпилируйте ядро.

Уверен, что вы захотите испытать систему перед конвертированием в SELinux. Вы можете сделать это, используя следующие команды:

qemu -hda gentoo.img -kernel bzImage -append "ro root=/dev/hda1"

Оглянитесь вокруг, добавьте несколько пользователей и поиграйте с вашей системой. Когда вы закончите, выключите ее, используя poweroff. Теперь вы готовы начать конвертировать вашу систему в SELinux.

конвертирование в SELinux

Для конвертирования в систему, которая поддерживает SELinux, вам потребуется изменить программу начальной загрузки системы, /sbin/init, а также добавить несколько других программ для построения политики SELinux и взаимодействия с SELinux.

SysVinit

Начните с получения чистой копии SysVInit. Я загрузил версию 2.86 с ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/sysvinit-2.86.tar.gz (последнюю версию пакета можно всегда найти на странице SysVinit на freshmeat).

Нужно также загрузить патч (sysvinit-init.c.diff); этот патч будет применен на файл init.c , используя процедуру в листинге ниже. Этот патч делает политику SELinux загружающейся при стартапе. Он определяет флаг no_selinux, который установлен в 1, если команда загрузки содержит -p. Если этот флаг установлен, будет выведено предупреждение и процесс загрузки будет продолжен, как обычно. Иначе вызывается функция load_policy(), которая определена в патче.

wget ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/sysvinit-2.86.tar.gz
cd sysvinit-2.86
cd src
patch -p0 < $ORIG/sysvinit-init.c.diff
make init
(su)
mount -oloop,offset=32256 $ORIG/gentoo.img /mnt
mv /mnt/sbin/init /mnt/sbin/init.good
cp init /mnt/sbin/init
umount /mnt
exit


Функция load_policy() монтирует экземпляр файловой системы selinuxfs в каталог /selinux и открывает файл /etc/policy.bin для чтения. Заметьте, что /selinux и /etc/policy.bin – произвольные имена до тех пор, пока любое пользовательское приложение, которое может захотеть использовать их, согласно с этими именами. Когда политика SELinux скомпилирована, бинарная версия должна быть скопирована в /etc/policy.bin. Далее load_policy() отображает mmap()-файл /etc/policy.bin и вызывает security_load_policy, определенную сразу над load_policy. Она, открывает файл /selinux/load, расположенный на файловой системе selinuxfs, для записи, и записывает все содержимое /etc/policy.bin в /selinux/load.

создание политики

SELinux – это гибкая система контроля доступа, где решения о доступе принимаются на базе политики, определенной администратором. Дистрибутивы, которые поддерживают SELinux, поставляются с предопределенной политикой. Если это возможно, для редактирования политики, вы обычно изменяете политику только частично, исключая все части политики, относящиеся к ПО, не установленному в системе. Более детальное изменение политики обычно производят только эксперты SELinux. Однако, в этом упражнении, вы определите свою собственную политику.

Программа, находящаяся в архиве mdp.tar.gz, автоматически создаст простейшую политику, базирующуюся на версии вашего ядра. Так как это потребует анализа исходников ядра, вам будет нужно указать путь к дереву исходных кодов, которое вы использовали, чтобы скомпилировать ядро для образа QEMU. Распакуйте mdp.tar.gz в $ORIG/ и войдите в полученный каталог mdp/.
Наберите:

./build.sh -k ../linux-2.6.14.

Это компилирует программу mdp и запускает ее с аргументом – каталогом исходных кодов ядра. mdp по очереди проверяет классы объектов и разрешения, которые поддерживает ядро, и создает политику SELinux, которая содержит эти данные. Результирующая политика будет содержать одного пользователя SELinux, одну роль SELinux, и один тип SELinux. Единственный тип будет применен ко всем типам файлов, объектов ядра и процессам, и будет иметь полный доступ к себе самому. Мы поиграем с правилами этой политики позже, но сейчас она приемлима для инициализации и использования SELinux.

Когда build.sh запустит mdp, он создаст несколько файлов. Вам потребуются policy.conf и file_contexts. Это текстовое представление политики, последний файл содержит инструкции по разметке файловой системы.

Я рассмотрю подробное policy.conf позже, поэтому пропустите первые пять или шесть сотен строк, до этой строки:

type base_t;

Это только определение типа в этой политике. Следующая строка:

role base_r types { base_t };

определяет одиночную роль, base_r, которая ассоциирована с типом base_t. Это означает, что процесс в роли code_r может работать в домене base_t. Дальше идет длинный список состояний allow, каждое из которых специфицирует класс объекта, предоставляющий процессу в домене domain base_t доступ к классам объекта типа base_t для всех разрешений, определенных в классе.

Далее политика определяет пользователя, user_u, который ассоциирован с ролью base_r. Поэтому, процесс, работающий, как пользователь SELinux user_u, может работать в роли base_r. Вы уже заметили, что base_r ассоциирован с типом base_t, поэтому эти два состояния вместе делают user_u:base_r:base_t валидным контекстом, и, значит, процессу будет разрешено работать в данном контексте.

Следующие несколько строк также интересны. Первая:

sid kernel user_u:base_r:base_t

назначает единственный валидный контекст первому процессу в системе. Двумя строками далее вы видите:

sid unlabeled user_u:base_r:base_t

которые назначают одинаковый контекст любым файлам, которые не имеют метки.

Теперь обратим свой взор на файл под названием file_contexts. Он содержит всего две строки следующего формата:

<regexp> <context>

где regexp – это регулярное выражение, используемое для сравнения имен файлов, а context – это контекст SELinux, который применяется к файлу, если он удовлетворяет регулярному выражению. Строка:

/.* user_u:base_r:base_t

используется для назначения контекста на все файлы в системе.

инсталляция SELinux userspace

Следующий этап – установить некоторый код, который скомпилирует политику SELinux, которая записана в виде текста, в бинарный формат, который требуется ядру, а также установка программы для разметки вашей корневой файловой системы. Исходный код доступен через CVS из SourceForge.

su
mount -oloop,offset=32256 $ORIG/gentoo.img /mnt
cd /mnt/usr/src
cvs -z3 -d:pserver:anonymous@cvs.sf.net:/cvsroot/selinux co -P \
nsa/selinux-usr


Скопируйте текст политики на образ диска:

cp -r $ORIG/mdp /mnt/usr/src

Войдите в каталог nsa/selinux-usr и скомпилируйте libsepol, checkpolicy, libselinux и policycoreutils, как указано далее:

chroot /mnt
cd /usr/src/nsa/selinux-usr/
cd libsepol/
make && make install
cd ../libselinux/
make && make install
cd ../checkpolicy/
make && make install
cd ../policycoreutils/
make && make install


Если вы столкнулись с ошибками на последнем шаге, удостоверьтесь, что setfiles установлены, набрав следующее:

cd setfiles
make
make install


Теперь, чтобы скомпилировать политику, используйте программу checkpolicy:

cd /usr/src/mdp
checkpolicy -o policy.bin policy.conf
cp policy.bin /etc/
exit # exit chroot
exit # exit root shell


Переразметка файловой системы требует загрузки в виртуальной машине. Не забудьте указать опцию -p при этом, чтобы /sbin/init не пытался загрузить политику SELinux:

qemu -hda gentoo.img -kernel bzImage -append "ro root=/dev/hda1 -p"

SELinux взаимодействует с пользовательскими программами через свою собственную файловую систему - selinuxfs. Пользовательские программы ожидают, что она смонтирована в /selinux. Создайте каталог /selinux и переразметьте файловую систему, как указано далее:

mkdir /selinux
cd /usr/src/mdp
setfiles file_contexts /
poweroff


Теперь вы можете перезагрузиться в SELinux!

qemu -hda gentoo.img -kernel bzImage -append "ro root=/dev/hda1"

изучение политики SELinux

SELinux принимает решения о доступе на основании контекстов безопасности, ассоциированных с процессами, файлами и другими объектами. SELinux предоставляет интерфейсы для запроса этих контекстов и выдачи необходимых прав доступа для их установки. Например, SELinux сообщает контекст процесса через интерфейс procattr. Если вы наберете:

cat /proc/$$/attr/current

вы увидите контекст текущего процесса ($$). Используя скрипт pidctx.sh, вы можете легко просматривать контекст всех процессов в системе. Скрипт просто печатает файл /proc/pid/attr/current для каждого процесса в системе.

SELinux сохраняет контексты файла, используя расширенные атрибуты. Наиболее распространенные файловые системы в Linux (ext2, ext3, jfs, xfs, etc.) поддерживают расширенные атрибуты, но reiserfs, к сожалению, представляет собой исключение. Это пары (имя, значение) данных, ассоциированные с инодами. Расширенные атрибуты SELinux находятся в безопасном пространстве имен и идентифицируются по "selinux", так что полное имя значения некоторого атрибута будет "security.selinux". Новый набор системных вызовов позволяет пользователям запрашивать и устанавливать расширенные атрибуты. Системный вызов для запроса расширенного атрибута - getxattr(2). Он принимает имя файла, имя атрибута, буфер, в который будет возвращено значение атрибута и размер предоставляемого буфера.

Файл showctx.c просто запускается для всех имен файлов, заданных аргументами командной строки и печатает значение расширенного атрибута security.selinux, если оно существует, его можно читать и оно помещается в данный размер буфера.

Вы можете загрузить showctx.tar.gz, и распаковать showctx.c. Затем поместите его на образ QEMU любым путем. Один из способов – выключить образ QEMU, а затем сделать следующее:

(su)
mount -oloop,offset=32256 $ORIG/gentoo.img /mnt
cp showctx.c /mnt/usr/src
umount /mnt
exit


Теперь запустите QEMU, если он еще не запущен. Чтобы скомпилировать showctx наберите:

gcc -o showctx showctx.c cp showctx /bin/

Сейчас вы можете набрать:

showctx / /tmp /home /root /usr/src

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

игры с политикой SELinux

Создадим политику для секретных данных.

Для начала выберем секретный каталог, пусть будет /secret, в котором SELinux не будет разрешать процессам чтение.

В политике SELinux создадим новый тип, secret_t, на который другой тип, base_t, не будет иметь разрешений. Сначала, вы определите тип, добавив:

type secret_t;

после определения base_t в policy.conf. Дополнительно, так как файлы типа secret_t будут иметь роль base_r, роли base_r нужно разрешить быть ассоциированной с типом secret_t. Строка, следующая за той, которую вы только что добавили, выглядит следующим образом:

role base_r types { base_t };

Отредактируйте ее:

role base_r types { base_t secret_t };

Теперь для пересборки политики наберите:

checkpolicy -o policy.bin policy.conf
cp policy.bin /etc/


Далее добавьте следующие строки в файл file_contexts:

/secret user_u:base_r:secret_t
/secret/helloworld user_u:base_r:base_t
/secret/.* user_u:base_r:secret_t


Это сообщит системе, что каталог /secret и любые имена файлов в нем, должны быть типа secret_t, за исключением файла /secret/helloworld, который должен остаться типа base_t. Для назначения этих контекстов на диск используйте setfiles:

setfiles file_contexts /

О нет, ошибка! SELinux еще не знает о типе secret_t. На самом-то деле я знаю, что возможно динамически перезагрузить политику SELinux. Сейчас, однако, чтобы упростить процесс, просто перезагрузите образ QEMU. Конечно, так как загрузчик не был установлен, простая перезагрузка не заработает. Следовательно, вам потребуется набрать poweroff чтобы выключить образ QEMU. Если окно не пропало после надписи "Power down", то нажмите Ctrl-c в окне qemu. Введите команду qemu для перезапуска. Затем попробуйте запустить команду setfiles снова.

Проверьте, что политика перезагружена корректно:

showctx / /secret /secret/helloworld /secret/dontlook cat /secret/dontlook

Но подождите! Вы можете видеть секретный тип.

Это результат одной из опций компиляции ядра, CONFIG_SECURITY_SELINUX_DEVELOP. Эта опция по-умолчанию устанавливает SELinux в non-enforcing режим. Чтобы проверить это, наберите команду:

cat /selinux/enforce

которая должна вернуть 0. Чтобы установить SELinux в режим enforcing, наберите:

echo 1 > /selinux/enforce

Если желаете, вы можете делать это автоматически при загрузке посредством скрипта инициализации, как показано ниже, или просто скомпилируйте ядро без поддержки SELINUX_DEVELOP.

cat >> /etc/rc.d/selinux-enforce << EOF
#!/bin/sh
echo 1 > /selinux/enforce
EOF
chmod ugo+x /etc/rc.d/selinux-enforce
rc-update add default selinux-enforce


Теперь, когда SELinux в режиме enforcing, попробуйте перейти в /secret снова. Заметьте, что даже несмотря на то, что контекст вашего процесса имеет право на чтение /secret/helloworld, вы реально не сможете читать его, потому что вы не можете получить /secret. Жесткая ссылка на файл может, безусловно, обойти это. Это не верно для остальных файлов в /secret/, так как эти файлы сами по себе невозможно прочесть.

заключение

Из этой статьи вы узнали, как воспроизвести действия, которые уже проделаны в некоторых дистрибутивах для поддержки SELinux. Если это кажется пугающим, расслабьтесь – просто установите свежую копию последней Fedora, и использование SELinux будет столь прозрачным, что вы можете даже не знать, что она установлена. Цель этого упражнения - не убедить вас, что безопасность сложна, но продемонстрировать, что происходит «за сценой» в правильно интегрированной системе SELinux.



Серж Галин, штатный программист, IBM
обсудить статью
© сетевые решения
.
.