Предыдущая статья этой серии описывала принципы работы .NET Framework. Эта информация будет служить в качестве отправной точки для обсуждения защиты на основе прав доступа кода (code access security), основанного на функциональных возможностях, предоставляемых общеязыковой исполняющей средой (CLR, Common Language Runtime). Поэтому, если вы пока не знакомы с .NET Framework, я настоятельно рекомендую вам прочесть предыдущую статью.
Будучи основанной на CLR, защита по правам доступа кода возможна только для управляемых приложений (то есть приложений, написанных в соответствии со спецификациями .NET). Несмотря на то, что стандартные приложения Windows исполняются в контексте безопасности запустившего их пользователя, уровень привилегий, предоставляемых приложению .NET, является настраиваемым. Ресурсы компьютера могут быть защищены не только от атак злоумышленников, то также от потенциальных ошибок или уязвимостей в их коде. Архитектура защиты на основе прав доступа кода концептуально основана на двух главных компоновочных блоках:
Наборе разрешений. Набор разрешений - это коллекция отдельных разрешений на различных ресурсах компьютера, определяющая, какой код может получать доступ к ним (например, предоставление доступа read-only к определенному ключу реестра).
Группе кода. Группа кода - это списки критериев (называемых условиями членства), оцениваемые по отношению к исполняемому коду и набор разрешений, назначаемый коду, который соответствует этим критериям.
Когда пользователь запускает выполнение программы (или файла, называемого в мире .NET сборкой (assembly)), CLR сначала проверяет ее код на ошибку переполнения буфера (ее присутствие создает уязвимость и потенциальную угрозу вторжения). Кроме того, CLR проходит через стадию верификации, в ходе которой анализирует цифровую подпись создателя, назначаемую коду для проверки, было ли данное приложение изменено с момента его выхода.
Если обе проверки приводят к удовлетворительным результатам, то CLR проверяет другие свойства приложения, такие как его происхождение (зона, сайт или системный путь файла) и характеристики кода (хэш, издатель или строгое имя (strong name)). Этот этап часто описывается как "сбор признаков" (evidence gathering).
Затем этот код сравнивается с группами кода, настроенными для локального компьютера. Наборы разрешений, связанных с каждой группой, определяют, какой тип действий приложению разрешается выполнять.
Наборы разрешений и группы кода конфигурируются через инструмент .NET Framework Configuration tool, доступный из меню Administrative Tools в Windows Server 2003 (и на других платформах Windows, если на них установлен .NET framework). Он реализован как часть оснастки Microsoft Management Console и содержит следующие узлы в панели дерева (в левой части окна):
Assembly cache (кэш сборки) предлагает опцию просмотра содержания глобального кэша сборок (GAC, Global Assembly Cache) и добавления к нему новых сборок. GAC расположен в папке Windows\Assembly и хранит совместно используемые сборки, являющиеся кусочками кода, которые могут использоваться многими приложениями .NET. (Кэш сборок служит функциональным эквивалентом папки Windows\ System32, хранящей совместно используемые файлы Win32 DLL (Dynamic Link Library). Сборки в этом хэше реализованы либо в виде DLL-, либо ЕХЕ-файлов).
Configure assemblies (конфигурирование сборок) позволяет задавать два типа политик любой сборке (включая сборки, расположенные не на локальном компьютере).
Binding Policy (связанная политика) определяет версию сборки, которая должна использоваться при помощи соотнесения версии запроса приложения .NET с одним из CLR-провайдеров. Это гарантирует, что будет применена только апробированная версия (например, MyAssembly версии 1.1.1.1 будет перенаправляться на MyAssembly версии 1.2.2.2).
Codebases Policy(политика, основанная на коде) определяет расположение сборок, которые должны использоваться. Чтобы добиться этого, версия, запрашиваемая приложением .NET, ставится в соответствие определенному расположению в формате URI (uniform resource identifier) (например, запрос MyAssembly версии 1.1.1.1 будет перенаправляться на Web-сайт http://www.myassemblies.com или папку file:///c:\MyAssemblies на локальном диске).
Remoting Services (удаленные службы) предоставляет возможность изменять свойства каналов, используемых для коммуникации между локальными приложениями и удаленными службами.
Runtime Security Policies (Политики безопасности периода исполнения) содержит настройки для настройки защиты на основе прав доступа кода (именно это нас и интересует). Этот узел разделен на три подузла, представляющие уровни политики.
Enterprise Level (уровень предприятия): предназначен для политик уровня предприятия и сохраняется по умолчанию в файле enterprisesec.config, расположенном в подкаталоге config каталога, в который установлен .NET Framework (как правило это WINDOWS\Microsoft.NET\Framework). Ясно, что если вы попытаетесь применить эту политику ко всей вашей организации, то нужно обеспечить, чтобы данный файл был совместим со всеми системами. Это может быть легко достигнуто с помощью создания пакета .MSI в мастере Deployment Package Wizard (являющегося частью .NET Framework Configuration tool, доступ к которому можно получить из задачи Create Deployment Package в узле Active Directory Group Policy) и развертывания его на всех целевых системах с помощью Active Directory Group Policy или другого метода развертывания. Обратите внимание на то, что Package Deployment Wizard может быть также использован для развертывания политик отдельно для пользователей или компьютеров.
Machine Level(уровень компьютера) применяется на локальном компьютере. Он хранится в файле security.config, расположенном в том же подкаталоге config, что и файл enterprisesec.config.
User Level (уровень пользователя) применяется к текущим зарегистрировавшимся пользователям. Он хранится в файле security.config, расположенном в папке Applications Data\Microsoft\CLR Security Config в профиле пользователя.
Политика безопасности оценивается исходя из политик защиты на основе прав доступа кода на каждом из уровней, начиная с уровня организации и заканчивая уровнем пользователя. Эти настройки оцениваются независимо и взаимодействуют таким образом, что применяются более ограничивающая из всех трех. Однако, есть возможность, настроить политики более высокого уровня (на отдельном уровне Code Group) с тем, чтобы предотвратить применение политик более низкого уровня (используя опции, доступные на вкладке General диалогового окна Properties для группы кода).
.NET Framework также включает уровень политики Application Domain, который может конфигурироваться только через код (и недоступен в инструменте .NET Framework Configuration tool).
Каждый уровень политики, в свою очередь, содержит три подузла, определяющие конфигурационные настройки:
Code Groups (Группы кода), каждая из которых состоит из имени, условий членства и набора разрешений, назначенных ей. Число различных типов условий членства включаю как происхождение кода (каталог приложения, сайт, URL или зона), так и свойства кода (хэш, издатель или строгое имя). Также возможно определить пользовательские условия членства (импортируемые из файлов формата XML). Условия членства сравниваются со значениями, собранными в ходе стадии "сбора признаков" после того, как было запущено управляемое приложение. Если свойства приложения совпадают с критериями, определенными для некоторой группы, то этому приложению назначается набор разрешений, связанный с данной группой кода. Обратите внимание на то, что инструмент .NET Framework Configuration tool содержит следующие предварительно установленные наборы разрешений:
FullTrust (полное доверие) дает неограниченный доступ ко всем ресурсам (включая возможность пропускать этап верификации);
SkipVerification (пропуск верификации) пропускает начальный процесс верификации (в ходе которого анализируются цифровые подписи);
Execution (выполнение) дает право на исполнение кода.
Nothing (ничего) отменяет все привилегии, включая исполнение;
LocalIntranet (локальная сеть) содержит права по умолчанию, обычно назначаемые локальным сетевым приложениям;
Internet (Интернет) содержит права по умолчанию, обычно назначаемые приложениям Интернета;
Everything (все) дает неограниченный доступ ко всем ресурсам (но не позволяет пропускать процесс верификации).
Также вы можете создавать ваши собственные наборы разрешений с большей гранулированностью, включающие (но не ограниченные этим) просмотр только определенных областей служб каталога, препятствующие доступу к DNS, разрешающие выполнять аудит журналов событий, дающие доступ с правами read или write к переменным среды, контролирующие, какие файлы или папки являются перезаписываемыми, определяющими, какие диалоговые окна (например, Open или Save) используются и какие ключи реестра можно читать.
Policy Assemblies (сборки политики) перечисляют файлы сборок, используемые для реализации различных политик безопасности. Нет необходимости выполнять какие-либо изменения в этом узле, если только вы не реализуете пользовательские разрешения или пользовательские условия членства.
Applications (приложения) позволяют вам настраивать управляемые приложения, установленные на локальной системе. Вы можете, например, изменить свойства сборки мусора или установить путь поиска дополнительных сборок, просмотреть зависимости сборки, изменить связанную политику и лежащий в основе код сборки, совместно используемый приложением или изменить настройки удаленных служб.
Как видите, новые опции, введенные в .NET framework, предлагают громадную гибкость в обеспечении безопасности управляемых приложений. Как обычно, с этим связана и оборотная сторона, связанная, в данном случае, с увеличением административных усилий и уровня сложности.