Linux традиционно считается хорошо продуманной с точки зрения безопасности операционной системой, и попытки поставить под сомнение этот тезис обычно вызывает недоумение. Однако, следует помнить, что Linux унаследовала систему безопасности Unix, реализованную еще в 70-х годах и не во всем соответствующую требованиям сегодняшнего дня. Остановимся на основных недостатках традиционной модели безопасности ОС Linux.
Недостаточная «разрешающая способность» системы контроля. Многие права доступа предоставляются в Linux по принципу «либо всем, либо только одному». Это относится как к пользователям, так и к другим агентам системы. Следствием этого является то, что пользователь часто вынужден принимать права root (посредством suid-бита или команды su), со всеми полномочиями суперпользователя, для выполнения задач, реально требующих гораздо меньших прав.
Предоставление всех возможных прав и привилегий одной учетной записи суперпользователя. Пользователь, несанкционированно получивший доступ к правам root, приобретает полный контроль над системой.
Отсутствие разграничения прав доступа к некоторым важным объектам системы. Всем, кто знаком с ОС Linux, известно, что из любого пользовательского сеанса можно запустить, например, сервер TCP/IP (если только соответствующий порт уже не занят другим приложением). Очевидно, для большинства пользователей подобная функциональность избыточна и чревата нарушением безопасности.
SELinux
SELinux — набор технологий расширения системы безопасности Linux. Сегодня основу набора составляют три технологии: мандатный контроль доступа, ролевой доступ RBAC и система типов (доменов). SELinux включает модули ядра, разделяемые библиотеки для создания приложений, использующих особенности SELinux, утилиты и другие файлы. SELinux можно установить с любым дистрибутивом Linux, начиная с ядра версии 2.2.x.
Архитектурно SELinux подчиняется трем принципам, способствующим максимально безболезненной интеграции SELinux в Linux-системы:
- параллельное сосуществование с классической системой безопасности Linux;
- независимость от классической системы безопасности Linux;
- приоритет запретов классической системы безопасности Linux над SELinux (то, что запрещено классической системой безопасности, не может быть разрешено SELinux).
SELinux зародился в недрах Агентства национальной безопасности США (непосредственно разработкой занимались компании Network Associates и MITRE) и был выпущен в виде общедоступного открытого программного продукта в декабре 2000 года. Для систем с ядрами 2.2 и 2.4 он выпускался в виде заплаты, а с введением модуля Linux Security Module (LSM) в ядре 2.4 была выпущена версия SELinux для LSM. В ядре 2.6 он также поддерживается посредством LSM. Кроме того, многие элементы SELinux были включены в само ядро. Однако, если операционная система использует ядро 2.6, это еще не означает, что там обязательно есть SELinux или что эту систему легко активировать. Это означает только, что установить SELinux будет проще.
В настоящее время SELinux полностью поддерживается в дистрибутивах RedHat Enterprise Linux 4, Fedora Core 2 и 3, Gentoo Hardened Linux, в каждом из которых имеется параметр включения SELinux во время установки ОС.
Субъекты, объекты и политики
Тремя важнейшими концепциями структуры безопасности SELinux являются субъекты (subject), объекты (object) и действия (action). С точки зрения SELinux всю работу системы можно описать как выполнение субъектами действий над объектами. Субъектами считаются процессы, действующие как от имени определенных пользователей, так и самостоятельно (серверные процессы). Объектами являются, прежде всего, объекты файловой системы (файлы, каталоги, ссылки1), процессы (когда один процесс-субъект выполняет операции с другим процессом, второй процесс выступает в роли объекта), а также дескрипторы файлов (в том числе сокеты, что повышает безопасность работы с сетью) и объекты межпроцессного взаимодействия, не связанные с дескрипторами файлов. Действия в SELinux — это любые операции, которые субъект может выполнить над объектом. Собственно говоря, основная часть работы системы безопасности как раз и заключается в принятии решения о том, имеет ли право данный субъект выполнить данное действие над данным объектом.
Решение о допустимости или не допустимости действия принимается системой на основе политик, представляющих собой способ описания поведения системы безопасности, абстрагирующийся от таких низкоуровневых понятий как векторы доступа (аналоги масок доступа в обычной Linux-системе). Формирование политик безопасности в SELinux напоминает программирование: политика описывается на специальном языке, затем файл политики компилируется в двоичный модуль (обычно при этом используется хорошо знакомая программистам утилита make), а скомпилированный файл динамически загружается в ядро операционной системы.
Политики SELinux позволяют определить, какое решение следует принять для отдельных операций и классов операций: allow (разрешить операцию); auditallow (занести операцию в журнал, независимо от того, разрешена она или нет); dontaudit (запретить операцию, но не вносить данные о попытке выполнить операцию в журнал). Описать логику совместной работы подобных установок можно так: если операция разрешена, она заносится в журнал только в том случае, если принято решение auditallow. Если операция не разрешена, она не заносится в журнал только в том случае, если принято решение dontaudit. Таким образом, в SELinux политика разрешения операций тесно связана с их журналированием.
Более подробно эти вопросы освещены в [1].
Контексты безопасности
Права субъектов и объектов определяются в SELinux контекстами безопасности, состоящими из идентификатора, роли и типа объекта. Идентификатор субъекта — это идентификатор пользователя SELinux, создавшего процесс-субъект. Идентификатором объекта является идентификатор пользователя-владельца объекта (обычно это пользователь, создавший объект). Роли представляют собой наборы привилегий. В любой момент времени каждый пользователь может выступать в одной из доступных ему ролей. Роли позволяют предоставлять пользователю дополнительные привилегии, не утрачивая его идентичности, как это происходит при применении команды su в традиционных системах Unix/Linux. Политика безопасности SELinux может налагать ограничения не только на количество ролей, доступных процессу, но и определять правила перехода из одной роли в другую. Не всякий переход из одной роли в другую допустим.
Очевидно, что роли гораздо чаще используются субъектами, чем объектами, а некоторые объекты (скажем, дисковые файлы), вообще не нуждаются в ролях. Таким объектам присваиваются «пустые роли», не влияющие на безопасность.
Типы объединяют группы субъектов и объектов, предоставляя им определенные права. Важной функцией типов является ограничение возможных действий субъекта над объектом. По этой причине типы иногда называют «песочницами SELinux» (SELinux sandbox). В документации по SELinux можно встретить также термин «домен». В классических работах по безопасности систем (в частности, в модели Flask) понятия «тип» и «домен» имеют разные значения, однако в SELinux эти понятия почти синонимы. Мы говорим о типах, когда речь идет об объектах и о доменах, когда речь идет о субъектах. Домены можно описать как множества процессов (субъектов), обладающих одинаковыми правами. Например, Web-сервер Apache принадлежит домену (типу) httpd_t и обладает всеми правами, связанными с этим доменом. К этому же типу относятся файлы, к которым демон httpd должен иметь полный доступ. В SELinux действует механизм принудительного присвоения типов (type enforcement). В соответствии с этим механизмом каждый процесс оказывается принадлежащим к определенному типу (домену), определяющему права этого процесса. Очевидно, что без принудительного присвоения типов система обязательного контроля доступа не могла бы работать.
Каждый субъект и объект идентифицируется собственным контекстом безопасности, которому соответствует идентификатор безопасности SID, причем система контекстов сильно отличается от традиционной системы учетных записей в ОС Linux поэтому возникает задача их взаимодействия. В соответствии с принципом независимости SELinux поддерживает таблицу контекстов безопасности, независимую от таблицы учетных записей Linux. При этом возможно отображение нескольких учетных записей Linux на одну учетную запись SELinux. Таким образом, изменения в учетных записях Linux не влияют на параметры безопасности SELinux.
Модель безопасности SELinux требует, чтобы каждый файл в системе был связан с определенным контекстом безопасности, поэтому в ходе установки всегда выполняется маркировка (labeling) объектов файловой системы. В соответствии с принципом независимости маркировка файлов не влияет на маски доступа к файлам, а в соответствии с принципом приоритета традиционной системы безопасности запреты, наложенные маской доступа, отменяют разрешения SELinux.
Операции доступа и операции преобразования
Операции SELinux делятся на операции доступа (access) и операции преобразования (transition). Первые система выполняет чаще всего, например, открытие и чтение данных из файла, вторые — операции, связанные с изменением контекста безопасности объектов. В результате операции преобразования объект получает контекст безопасности, отличный от того, который он получил бы по умолчанию. Например, созданный файл по умолчанию получает тот же контекст безопасности, что и каталог, в котором этот файл создан (в таких случаях говорят: «файл наследует контекст безопасности»). С помощью операции преобразования файлу можно присвоить новый контекст безопасности, отличающийся от контекста безопасности по умолчанию.
На самом деле, системы, ведущие авторизацию пользователей, не могут обойтись без операций преобразования в той или иной форме. Процесс, контролирующий вход пользователя в систему обычно имеет права суперпользователя (или другой высокий уровень привилегий). По умолчанию, любой дочерний процесс, созданный этим процессом, получит тот же уровень привилегий. Для того чтобы авторизовать пользователей с разными уровнями привилегий, процесс, осуществляющий авторизацию, должен выполнять операции преобразования. Важной операцией преобразования, характерной для SELinux, является операция преобразования типов (доменов), при которой процесс переходит из одного домена в другой. Обычно с типами связаны группы ролей, поэтому процесс смены типа обычно выполняется с помощью смены роли.
Расширения SELinux
Нетрудно заметить, что модель безопасности SELinux решает в основном проблемы определения доступа пользователей к объектам операционной системы. Однако существует еще один класс проблем безопасности, который отчасти пересекается с проблемами доступа, но имеет и собственные аспекты. Речь идет о нарушении целостности исполняемого кода; его классический пример — переполнение стека. В ходе подобных атак злоумышленник «внедряет» свой код в приложение, заставляя его выполнять свои команды. Универсального способа защиты от подобных атак не существует, и уязвимости для внедрения стороннего кода обнаруживаются в программах регулярно. Специально для решения проблем этого рода разработаны расширения безопасности Linux, позволяющие если не полностью устранить проблему, то, по крайней мере, минимизировать разрушительные последствия атак.
Наиболее интересным из предложенных средств защиты представляется система PAX, использующая технологию случайного расположения программы в адресном пространстве (address space layout randomization, ASLR) [2]. Успех атак, подобных переполнению стека, основан на знании злоумышленником взаимного расположения разных модулей атакуемой программы. Поэтому случайная перестановка этих модулей (выполняемая, естественно, таким образом, чтобы не нарушить целостность и функциональность самой программы) сделает большинство подобных атак бесполезными. Самое большее, чего сможет добиться злоумышленник, — это вызвать аварийное завершение процесса, но не получить контроль над ним; во многих случаях это уже немало. Помимо прочего, «падение» процесса в результате атаки, безусловно, привлечет гораздо больше внимания со стороны системного администратора, чем успешное внедрение кода, которое может пройти незамеченным. Система PAX, функционирующая на уровне ядра Linux, отслеживает запуск определенных процессов и выполняет в них «перестановки», руководствуясь случайным принципом. Другое направление развития PAX, связанное с проблемой несанкционированого кода — это предотвращение исполнения неисполняемых страниц памяти (прием, который также часто применяется при взломе систем).
Основная процессорная архитектура для PAX — IA-32, однако имеются реализации и для других платформ; наиболее полная поддержка PAX на сегодняшний день реализована в рамках проекта Hardened Gentoo Linux.
Сама система PAX является частью проекта grsecurity, преследующего те же цели, что и SELinux. Девиз grsecurity звучит так: «Если система безопасности не дружественна по отношению к пользователю, она бесполезна». Реализацией этого принципа можно считать читабельную, с точки зрения человека, систему конфигурации. Система grsecurity реализует ролевой контроль доступа, что, по-видимому, в ближайшем будущем станет стандартом для Unix-систем. Среди особенностей grsecurity следует отметить систему аудита ядра, особые средства защиты разделяемой памяти (один из механизмов межпроцессного взаимодействия), жесткий контроль операции chroot.
Среди других систем усиления безопасности Linux стоит отметить Bastille Linux (www.bastille-linux.org), набор инструментов безопасности, вобравший в себя многолетний опыт эксплуатации Linux-систем. Bastille Linux поддерживается дистрибутивами Fedora Core, Red Hat Enterprise, SuSE, SuSE Enterprise, Mandrake, Debian и Gentoo. Кроме того — и это уникальный в своем роде факт — Bastille Linux была перенесена в HP-UX и MacOS X (она, как известно, основана на Unix-ядре). Среди особенностей Bastille Linux следует отметить систему регулярных автоматических обновлений безопасности (наподобие той, что действует в Windows XP), защиту каталогов общего доступа. В процессе установки Bastille Linux выполняется скрипт, проверяющий и настраивающий параметры безопасности системы (доступ к каталогам, биты suid и т.п.).
Наконец, нельзя не отметить проект TrustedBSD (www.trustedbsd.org), целью которого является построение системы повышенной безопасности на основе открытой операционной системы FreeBSD.
Конкуренция или конвергенция?
Все рассмотренные продукты поставляются в исходных текстах, и, к примеру, разработчики Bastille Linux не стесняются признавать, что позаимствовали многие идеи и технологии из открытых расширений безопасности Linux и других систем сообщества Open Source. Поэтому говорить о конкуренции между открытыми расширениями обеспечения безопасности Linux не приходится. Не случайно, в [1] система PAX характеризуется именно как дополнение, а не как конкурент SELinux. Сегодня разработчики «корпоративных» дистрибутивов, а также собственных платформ корпоративного уровня на базе Linux имеют широкий спектр выбора открытых решений в области безопасности, которые можно различным образом сочетать между собой и адаптировать к потребностям конкретной платформы.
-
Bill McCarty, SELinux. O`Reilly, 2004.
-
Sandeep Grover, Buffer Overflow Attacks and Their Countermeasures, Linux Journal, 2004, No. 4.
Андрей Боровский (borovsky@pochtamt.ru) — инженер-программист ФГУП РНИИ КП (Москва).
Дискреционный и мандатный контроль доступа
Традиционно ОС Linux реализует дискреционный (добровольный) контроль доступа, при котором владелец объекта в рамках своих полномочий определяет права доступа к объекту. SELinux вводит мандатный (обязательный) контроль доступа, при котором права доступа к объекту контролируются не владельцем, а системой. Мандатный контроль может повысить безопасность системы сразу в нескольких аспектах. Например, в традиционной модели безопасности Linux, злоумышленник, захвативший высокий уровень привилегий, может использовать их для того, чтобы понизить уровень доступа к некоторым важным объектам системы, чтобы затем получить к ним доступ из обычной учетной записи. Мандатный контроль доступа существенно ограничивает подобные возможности, проповедуя принцип «наименьших необходимых привилегий» — один из основных принципов безопасности SELinux. В соответствии с ним каждая программа, запущенная пользователем, обладает только теми привилегиями, которые ей необходимы. Например, почтовая программа может получить доступ к каталогу входящих почтовых сообщений пользователя, но не может получить доступ к файлу конфигурации оболочки пользователя. Обычно почтовая программа, конечно, не станет пытаться получить доступ к файлу конфигурации оболочки. Однако программа, взломанная злоумышленником, может начать выполнять несвойственные ей действия. Дискреционный контроль доступа дает всем процессам, запущенным пользователем, одинаковые права — права самого пользователя, в результате каждый процесс может сделать только то, что может пользователь. Мандатный контроль доступа предоставляет разные наборы прав разным процессам, и, что очень важно, не позволяет пользователю (случайно или намеренно) изменить эти права.
SELinux и графические интерфейсы
Графические интерфейсы — традиционно «слабые звенья» в системах безопасности Unix и SELinux, к сожалению, не исключение и проблемы остаются. Самым узким местом для SELinux является графическая оболочка KDE. Причина этого заключается в том, что разные программы KDE порождают процессы с одинаковыми именами, что создает трудности при назначении этим процессам доменов. В результате многие временные файлы, создаваемые KDE, не могут быть правильно помечены системой типов SELinux. Как следствие, в отношении KDE политика безопасности SELinux часто оказывается либо слишком жесткой, либо слишком мягкой. Можно надеяться, что в будущем проблемы взаимодействия между KDE и SELinux будут решены; пока же пользователям SELinux-систем рекомендуется выбирать другие графические интерфейсы, например GNOME.