Работа над KasperskyOS началась в 2002 году с идеи о том, что индустрии требуется полноценная безопасная операционная система, обеспечивающая превентивную защиту от злоумышленников. На тот момент решения по обеспечению безопасности были в роли догоняющих — сначала «плохие» ребята находили какую-нибудь дыру в системе, а потом «хорошие» парни бросались ее закрывать, и инициатива всегда принадлежала первым. А что, если сделать операционную среду, в которой вообще будет невозможно каким-либо программам выполнять посторонние функции? Например, сегодня никто из разработчиков ПО и оборудования смартфона не может гарантировать, что при выполнении умножения 2 на 2 на калькуляторе мобильного устройства оно не будет параллельно отправлять SMS или связываться с сервером. В большинство существующих ОС изначально не закладывались меры безопасности, поэтому соответствующие инструменты обеспечения надежности интегрировались в них в виде дополнительных модулей и функций, что не решало фундаментальной проблемы уязвимости.
В среде, безопасность которой предусмотрена на уровне архитектуры, должно быть запрещено все, что заранее не было разрешено, тогда даже при обнаружении «дыр» злоумышленник не сможет ими воспользоваться. Иными словами, программы внутри такой системы при любых условиях делают только то, для чего они предназначены в соответствии с предварительно прописанными ограничениями. А значит, приложения будут лучше защищены не только от воздействий извне, но и друг от друга.
В качестве теоретической базы разработчики KasperskyOS использовали книги «Радужной серии», в которых описываются стандарты информационной безопасности, сформулированные в США в период с 1980 по 1990 год и ставшие с тех пор эталонными [1]. В них, в частности, отмечается, что безопасность компьютерных систем никогда не будет идеальной и правильнее говорить не о безопасных, а о доверенных системах. В одной из книг описывается концепция доверенной вычислительной базы (Trusted Computer Base, TCB) — совокупности механизмов, реализующих политику безопасности и определяющих степень доверия к системе. TCB предусматривает «мониторинг обращений» для контроля всех взаимодействий компонентов системы между собой, с системными функциями и с оборудованием. Все без исключения взаимодействия происходят только по указанию и с разрешения TCB, а основное правило — «запрещено все, что не разрешено».
KasperskyOS — микроядерная операционная система, в ядре которой (рис. 1) прописаны диспетчер процессов, механизм межпроцессного взаимодействия (inter-process communication, IPC) и система мониторинга обращений (reference monitor), получившая название Kaspersky Security System (KSS). Все остальные процессы и компоненты: управление памятью и периферийными устройствами, драйверы файловых систем и т. п. — в данном случае работали бы против концепции безопасности.
Рис. 1. Архитектура Kaspersky OS |
Процессы в ОС взаимодействуют между собой и с функциями ядра, отправляя и получая IPC-сообщения. Для каждого из этих сообщений KSS решает, разрешить (allow) его или запретить (deny). Применяется принцип default deny «по умолчанию»: если KSS не обнаруживает четкого правила, разрешающего то или иное действие, оно запрещается.
При написании приложений для Kaspersky OS используется особый подход — «компонентная модель», в основе которой лежит понятие «сущности» (entity). Сущностью может быть как целая программа, так и ее отдельная функция. Программа включает в себя набор компонентов со своими сущностями, и, таким образом, выполнение программы в Kaspersky OS превращается в IPC-переписку сущностей.
Чтобы участвовать в переписке, сущность обязана удовлетворять одному важному условию: в ней должен присутствовать код интерфейса доступа к механизму микроядра IPC. Нужно отметить, что разработчик не участвует в создании этой части кода, код автоматически генерируется из описания интерфейса на IDL (Interface Definition Language) — С++-подобном языке спецификации интерфейсов. Cтрогая типизация IDL позволяет проводить формальную верификацию корректности взаимодействия одной сущности с другой и проверять код на безошибочность.
С помощью кода интерфейса формируются две функции: Proxy для клиентских приложений и Dispatch — для серверных. Клиентское приложение вызывает функцию серверного приложения или ядра системы, передает параметры функции Proxy и сериализует их (то есть упаковывает в формат IPC-сообщения). Затем приложение вызывает транспортную функцию IPC в микроядре, передает ей созданное IPC-сообщение, ждет ответного IPC-сообщения, десериализует его (распаковывает параметры для вызываемой функции) и передает сделавшему вызов базовому коду клиента. Функция Dispatch делает обратное: получает IPC-сообщение, десериализует его, передает параметры базовому коду связанного с интерфейсом сервиса и, наконец, сериализует результат в IPC-сообщение.
Если в сущности имеется много разных функций, то они описываются на языке CDL (Component Definition Language). Специально разработанный компилятор Nk генерирует единый в рамках компонента код с интерфейсом, который на самом деле представляет собой совокупность Dispatch-интерфейсов всех входящих функций.
Для описания многокомпонентных сущностей имеется язык EDL (Entity Definition Language), с помощью которого описываются также и отдельные функции с собственными Dispatch-интерфейсами. При компилировании EDL-файла формируется общий код сущности с единым Dispatch-интерфейсом. Найти адресата для него можно по уникальному идентификатору Runtime Interface ID (RIID), который генерируется на этапе компиляции EDL-описания сущности. Такая вложенность типизированных спецификаций позволяет создавать сложные программы, в которых каждая функция будет снабжена собственным Proxy- или Dispatch-интерфейсом.
IPC-взаимодействие — это дело двух сущностей, в чем-то напоминающее технологию P2P, однако, в отличие от нее, происходящее по принципу рандеву. Чтобы рандеву состоялось, создается канал обмена IPC-сообщениями путем выделения сущностям глобальных системных дескрипторов (указателей, handle), идентифицирующих сущности отправителя и получателя. Как только сущности становятся владельцами своих дескрипторов, открывается IPC-канал. Каждая сущность знает только о выделенном ей дескрипторе, а об их паре знает только механизм IPC. Формирование IPC-канала называется «спариванием дескрипторов» (handles pairing). После спаривания посторонний участник не может вклиниться в диалог, а канал остается открытым до тех пор, пока сущности остаются владельцами дескрипторов. Модель IPC-взаимодействия handles pairing запатентована «Лабораторией Касперского».
Никто не может вклиниться в IPС-диалог, однако система KSS может просматривать проходящие по каналу сообщения. В составе KSS выделяются две основные части:
- модуль Security Server, принимающий решение о вердикте на основе политики безопасности (рис. 2);
- структура Decision Cache, хранящая вердикты по отдельным политикам для повышения производительности перлюстрации.
Рис. 2. Принцип работы Kaspersky Security System |
Решение разрешать или запрещать IPC-взаимодействие принимается в соответствии с политикой безопасности, которая зависит от свойств и целей системы. Политика безопасности описывается с помощью формального аппарата — например, в терминах темпоральных логик. Чтобы связать конкретные действия сущностей с конкретными политиками безопасности, был разработан декларативный язык конфигураций безопасности CFG. Конфигурация безопасности, составленная на этом языке, в сочетании с IDL-описанием интерфейса сущности позволяет компилятору Nk сгенерировать структуру данных Gate с уникальным идентификатором SID (Security ID). Эта структура связывает сущность с политикой безопасности, и если у сущности нет структуры Gate, то к ней применяется принцип default deny и она отбрасывается.
Багаж унаследованных приложений иногда не позволяет полностью заменить имеющуюся у пользователей ОС на KasperskyOS, поэтому в некоторых случаях достаточно внедрить KSS в уже существующую операционную систему.
Есть два способа создания приложений, работающих под управлением KasperskyOS:
- Перенос существующих приложений, использующих POSIX API. После переноса процессы, происходящие внутри такого ПО, не будут контролироваться ОС, однако его внешние связи будут безопасными.
- Разработка новых приложений. С точки зрения обеспечения безопасности это лучший вариант: функции будут проверены системой, и при написании кода программисту не надо задумываться о безопасности. Писать для операционной системы KasperskyOS не сложнее, чем для Linux, — здесь используется тот же API, а дополнительный инструментарий и языки, поставляемые в KasperskyOS SDK (компилятор Nk, IDL, EDL, CDL, CFG), ускоряют разработку безопасного ПО. Однако имеются и отличия. Во-первых, разработчику совсем не надо задумываться о функционале безопасности. Во-вторых, на этапе разработки архитектуры требуется продумать разбиение на домены безопасности (сущности) и сформировать политику безопасности, которая будет реализована впоследствии параллельно с созданием функциональной части приложения.
***
Система KasperskyOS предназначена для управления индустриальными сетями (PLC-контроллеры, SCADA-системы), телекоммуникационным оборудованием, «умными» автомобилями и устройствами Интернета вещей в целом. В планах развития ОС — разработка дополнительных функциональных моделей, упрощающих как применение системы, так и создание безопасных приложений, работающих под ее управлением.
Литература
- Руслан Богатырев. Защищенные операционные системы // Открытые системы.СУБД. — 2001. — № 4. — С. 39–43. URL: http://www.osp.ru/os/2001/04/180077 (дата обращения: 8.03.2017).
Андрей Никишин (Andrey.nikishin@kaspersky.com) — руководитель отдела развития технологических проектов, компания «Лаборатория Касперского» (Москва).