• Система безопасности доступа к коду
  • Группы кода
  • Caspol.exe — утилита политики системы безопасности доступа к коду
  • Полномочия доступа к коду и множества полномочий
  • Просмотр полномочий сборки
  • Уровни политики: машина, пользователь и предприятие
  • Поддержка безопасности в .NET
  • Требуемые полномочия
  • Запрашиваемые полномочия
  • Неявное полномочие
  • Отказ от полномочий
  • Заявляемые полномочия
  • Создание полномочий доступа к коду
  • Декларативная безопасность
  • Система безопасности на основе ролей
  • Принципал
  • Принципал Windows
  • Роли
  • Система безопасности на основе декларативной роли
  • Управление политикой системы безопасности
  • Конфигурационный файл системы безопасности
  • Простой пример
  • Управление группами кода и полномочиями
  • Включение и выключение системы безопасности
  • Восстановление политики системы безопасности
  • Создание группы кода
  • Удаление группы кода
  • Изменение полномочий группы кода
  • Создание и применение множеств полномочий
  • Распространение кода с помощью строгого имени
  • Распространение кода с помощью сертификатов
  • Управление зонами
  • Заключение
  • Глава 25

    Система безопасности .NET

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

    Этот вид неявного обновления станет нормой в недалеком будущем, но очевидно, что здесь существуют проблемы, связанные с безопасностью так называемого мобильного кода. Какие имеются доказательства, что загруженный код надежен? Как узнать, что был получен именно тот модуль, который был запрошен? Что неявно делает CLR, чтобы гарантировать, например, что элемент управления на сайте Web не читает нашу почту?

    Платформа .NET реализует политику системы безопасности в сборках. Она использует информацию о сборках, например, откуда они и кем опубликованы, чтобы разделить их на группы кодов с общими характеристиками. Например, весь код из локальной интранет помещается в единую группу. Он использует политику безопасности (обычно определяемую системным администратором с помощью утилиты caspol.exe или ММС) для назначения привилегий.

    Политика безопасности .NET в сборках позволяет убедиться, что сборка исходит от того, кто ее опубликовал, и распределена между группами с одинаковыми характеристиками. Что необходимо сделать, чтобы инициировать систему безопасности для машины или для определенного приложения? Ничего — весь код автоматически выполняется в контексте безопасности CLR, хотя и возможно отключение системы безопасности по какой-либо причине.

    В дополнение к уверенности в том, что выполняемый код надежен, также важно знать, что мы предоставляем пользователю приложения доступ к требуемым ему свойствам, но не более того. В эффективном управлении пользователями и их ролями может помочь система безопасности .NET на основе ролей.

    В этой главе мы обсудим свойства управления безопасностью, доступные в .NET, включая защиту от злонамеренного кода, администрирование политиками безопасности и программный доступ к подсистеме безопасности. Мы также рассмотрим развертывание системы безопасности приложений .NET в коротких примерах приложений, которые закрепят концепции этой главы.

    Система безопасности доступа к коду

    Система безопасности доступа к коду является свойством .NET, которое управляет кодом в зависимости от нашего уровня доверия ему. Если система CLR достаточно доверяет коду, она начнет его выполнение. Однако в зависимости от полномочий, предоставленных сборкой, это может происходить в ограниченной среде. Если код недостаточно надежен для выполнения, или если он реализуется, но затем пытается выполнить действие, для которого не имеет соответствующих прав, порождается исключение безопасности (типа

    SecurityException
    или его подкласса). Система безопасности доступа к коду означает, что можно остановить выполнение злонамеренного кода или позволить коду выполняться в защищенной среде, где он не принесет никакого вреда.

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

    Для большинства приложений система безопасности доступа к коду в .NET является существенным достоинством, но только одной из многих. Она предоставляет высокий уровень защиты от злонамеренного кода, но обычно нам не требуется в это вмешиваться. Особенно важно для нас, что одной из областей, в которую мы будем вовлечены, является управление политикой безопасности при конфигурации настольных компьютеров для надежного кода из приложения, поступившего от поставщиков программного обеспечения.

    Другой областью, где система безопасности доступа к коду наиболее важна, является создание приложения, включающего элемент, безопасность которого необходимо тщательно контролировать. Например, если существует база данных в организации, содержащая крайне важные данные, необходимо использовать систему безопасности доступа к коду, чтобы можно было определять, какому коду разрешается доступ к базе данных, а какой код не может получить к ней доступ.

    Важно понимать, что система безопасности доступа к коду предназначена для защиты ресурсов (локальных дисков, сети, интерфейса пользователя) от злонамеренного кода, но она не является инструментом для защиты программного обеспечения от пользователя. Для системы безопасности, связанной с пользователями, обычно используется встроенная в Windows 2000 подсистема безопасности пользователей или система безопасности .NET на основе ролей, которая будет рассмотрена позже.

    Система безопасности доступа к коду основывается на двух высокоуровневых концепциях: Code Groups (Группы кодов) и Permissions (Полномочия).

    □ Группы кодов (Code Groups) собирают вместе код, который имеет общие характеристики, хотя наиболее важным свойством является источник его происхождения. Например, группы кодов "Интернет" (источники кода из Интернета) и "интранет" (источники кода в LAN). Информация, используемая для помещения сборок в группы кода, называется свидетельством (evidance). Другое свидетельство, собираемое CLR, включает издателя кода, его устойчивое имя и (где применимо) URI, из которого он был загружен. Группы кода организуются в иерархию, и сборки почти всегда соответствуют нескольким группам кода. Группа кода в корне иерархии называется "All Code" и содержит все другие группы кода. Иерархия используется для определения, каким группам кода принадлежит сборка; если сборка не предоставляет свидетельство, которое соответствует определенной группе в дереве, не делается никаких попыток отнести ее к описанным ниже группам кода.

    □ Полномочия (Permissions), или права, являются действиями, которые разрешается выполнить каждой группе кода. Например, полномочия включают "возможность обратиться к интерфейсу пользователя" и "возможность обратиться к локальной памяти". Системный администратор обычно управляет полномочиями, и это можно делать на уровне предприятия, уровне машины и уровне пользователя.

    Виртуальная система выполнения внутри CLR загружает и реализует программы. Она предоставляет функции, необходимые для выполнения управляемого кода, и использует метаданные сборок для соединения в модули. Когда VES загружает сборку, она соответствует одной или нескольким группам кода. Каждой группе кода даются одно или несколько полномочий, которые определяют, какие действия могут делать сборки в этих группах кода. Например, если группе кода

    MyComputer
    присвоено полномочие
    FileIOPermission
    , то это означает, что сборки локальной машины могут читать и записывать в локальную файловую систему.

    Группы кода

    Группы кода имеют требование записи, называемое условием членства (Membership Condition). Чтобы сборка была внесена в группу кода, она должна соответствовать условию членства группы. Условия членства выглядят как запись "сборка с сайта www.microsoft.com" или "Издателем этого программного обеспечения является Microsoft Corporation".

    Каждая группа кода имеет одно и только одно условие членства. Здесь представлены типы условий членства в группах кода, доступные в .NET:

    □ Zone (Зона) — регион, из которого происходит код.

    □ Site (Сайт) — сайт Web, из которого происходит код.

    □ Strong name (Строгое имя) — уникальное, проверяемое имя кода. Часто называется 'общим именем'.

    □ Publisher (Издатель) — издатель кода.

    □ URL — определенное расположение, из которого происходит код.

    □ Hash value (хэш-значение) — хэш-значение сборки.

    □ Skip verification (Контроль пропуска) — код, который запрашивает сборку, обходит проверки контроля кода.

    □ Application directory (Каталог приложения) — расположение сборки в приложении.

    □ All code (Весь код) — весь код удовлетворяет этому условию.

    □ Custom (Специальный) — определяемое пользователем условие.

    Первым типом условия членства в списке является условие Zone, оно наиболее часто используется. В зоне определяется регион происхождения фрагмента кода: MyComputer, Intranet, Trusted и Untrusted. Эти регионы управляются с помощью Security Options в Internet Explorer, об этом мы узнаем больше в последующем при рассмотрении управления политиками системы безопасности. Хотя настройки управляются с помощью Internet Explorer, они применимы ко всей машине. Ясно, что эти конфигурационные параметры недоступны в браузерах других компаний и, фактически, внутристраничные элементы управления, написанные с помощью .NET Framework, не будут работать в браузерах, отличных от Internet Explorer.

    Группы кодов организуются в иерархию с условием членства All Code в корне.

    Можно видеть, что каждая группа кода имеет одно условие членства и обладает полномочиями, которые должны быть предоставлены группе кода. Мы рассмотрим полномочия более подробно позже. Отметим, что если сборка не соответствует условию членства в группе кода, CLR не пытается сопоставить ее с нижерасположенными группами кода.

    Caspol.exe — утилита политики системы безопасности доступа к коду

    К утилите командной строки политики системы безопасности доступа к коду мы часто прибегаем в этой главе. Она позволяет просматривать и управлять политикой безопасности. Чтобы получить список ее параметров, введите следующую команду:

    caspol.exe

    .NET содержит также подключаемый модуль (snap-in) для управляющей консоли Microsoft, обеспечивающий регулирование системы безопасности доступа к коду. Однако ограничимся утилитой командной строки, в этом случае будет легче следовать приведенным примерам и можно создавать сценарии для изменения политики системы безопасности, очень полезные применительно к большому числу машин.

    Рассмотрим группы кода на машине с помощью утилиты caspol.exe. Вывод команды перечисляет иерархическую структуру групп кода, дающую описание каждой группы кода. Введите следующую команду:

    caspol.exe -listdescription


    Microsoft (R) .NET Framework CasPol 1.0.xxxx.xx

    Copyright (c) Microsoft Corp 1999-2001. All rights reserved.


    Security is ON

    Execution checking is ON

    Policy change prompt is ON


    Level = Machine


    Full Trust Assemblies:


    1. All_Code: This code group grants no permissions and forms the root of the code group tree.

     1.1. My_Computer_Zone: This code group grants full trust to all code originating on the local machine.

     1.2. Local.Intranet_Zone: This code group grants the intranet permission set to code from the intranet zone. This permission set grants intranet code the right to use isolated storage, full UI access, some capability to do reflection and limited access to environment variables.

      1.2.1. Intranet_Same_Site_Access: All intranet Code gets the right to connect back to the site of its origine.

      1.2.2. Intranet_Same_Directory_Access: All intranet code gets the right to read from its install directory.

     1.3. Internet_Zone: This code group grants code from the Internet zone the Internet permission set. This permission set grants Internet code the right the use isolated storage an a limited UI access.

      1.3.1. Internet_Same_Site_Access: All Internet Code gets the right to connect back to the site of its origin.

     1.4. Restricted_Zone: Code coming from a restricted zone does not receive any permissions.

     1.5. Trusted_Zone: Code from a trusted zone is granted the Internet permission set. This permission set grants the right the use isolated storage and limited UI access.

      1.5.1. Trusted_Same_Site_Access: All Trusted Code gets the right to connect back to the site of its origin.

     1.6. Microsoft_Strong_Name: This code group grants code signed with the Microsoft strong name full trust.

     1.7. Standards_Strong_Name: This code group grants code signed with the Standards strong name full trust.

    Success

    Подсистема безопасности .NET следит, чтобы коду из каждой группы разрешалось делать только определенные вещи. Например, код из зоны Интернета будет, по умолчанию, иметь значительно более строгие ограничения, чем код с локального диска. Коду с локального диска обычно предоставляется доступ к данным на локальном диске, но сборкам из Интернета по умолчанию это полномочие не предоставляется.

    Используя утилиту caspol и ее эквивалент в панели управления Microsoft, можно определить, какой уровень доверия мы имеем для каждой группы доступа к коду, а для группы управляющего кода рассмотреть полномочия более детальным образом.

    Давайте еще раз взглянем на группы доступа к коду, но в более обобщенном виде. Зарегистрируйтесь в системе как локальный администратор, откройте командную строку и введите команду:

    caspol.exe -listgroups

    Появится вывод:

    Microsoft (R) .NET Framework CasPol 1.0.xxxx.x

    Copyright (c) Microsoft Corp 1999-2001. All rights reserved.


    Security is ON

    Execution checking is ON

    Policy change prompt is ON


    Level = Machine


    Code Groups:

    1. All code: Nothing

     1.1. Zone - My Computer: FullTrust

     1.2. Zone - Intranet: FullTrust

      1.2.1. All code: Same site Socket and Web.

      1.2.2. All code: Same directory FileIO — Read, PathDiscovery

     1.3. Zone — Internet: Internet

      1.3.1. All code: Same site Socket and Web.

     1.4. Zone — Untrusted: Nothing

     1.5. Zone — Trusted: Internet

      1.5.1. All code: Same site Socket and Web.

     1.6. Strong Name -

    00240000048000009400000006020000002400005253413100040000010001000

    7D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F7FB03766C834C999

    21EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177

    108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB9

    9285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A124

    36518206DC093344D5AD293:

    FullTrust

     1.7. StrongName - 00000000000000000400000000000000: FullTrust

    Success

    Можно заметить в начале вывода

    Security is ON
    . Позже в этой главе мы увидим, что это может быть выключено и снова включено.

    Настройка

    ExecutionChecking
    задается включенной по умолчанию, это означает, что всем сборкам должно быть предоставлено разрешение выполнения, прежде чем они смогут выполниться. Если проверка выполнения выключена с помощью
    caspol
    (
    caspol.exe -execution on|off
    ), то сборки, которые не имеют полномочий на выполнение, смогут реализоваться, хотя они способны вызвать исключения системы безопасности, если попытаются действовать вопреки политике безопасности в ходе этого выполнения.

    Параметр

    Policy change prompt
    определяет, будет ли появляться предупреждающее сообщение "
    Are you sure
    " при попытке изменить политику безопасности.

    Когда код разбит на группы, можно управлять системой безопасности на более детальном уровне и применять full trust (полное доверие) к значительно меньшей части кода. Отметим, что каждая группа имеет свою метку (такую, как "1.2"). Эти метки генерируются автоматически .NET и могут различаться на разных машинах. Обычно безопасность не контролируется для каждой сборки, она применяется на уровне группы кода.

    Представляет интерес вопрос, как действует

    caspol.exe
    , когда машина имеет несколько установок .NET. При таких обстоятельствах выполняемая копия
    caspol.exe
    будет изменять политику безопасности только для связанной с ней установкой .NET. Чтобы сохранить простым управление политикой безопасности, вполне можно удалить предыдущие копии .NET при установке последующих версий.

    Просмотр групп кода сборки

    Сборки соответствуют группам кода в зависимости от условий членства. Если вернуться к примеру групп кода и загрузить сборку с web-сайта https://intranet/, она будет соответствовать группам кода таким образом:

    Сборка является членом корневой группы кода (All Code); так как она приходит из локальной сети, то она является также членом группы кода Intranet, но вследствие того, что она была загружена со специального сайта https://intranet, то ей также предоставляется

    FullTrust
    , что соответствует выполнению без ограничений.

    Легко увидеть группы кода, членом которых является сборка, используя команду:

    caspol.exe -resolvegroup assembly.dll

    Выполнение этой команды для сборки на локальном диске создает вывод:

    Microsoft (R) .NET Framework CasPol 1.0.2728.0

    Copyright (с) Microsoft Corp 1999-2001. All rights reserved.


    Level = Enterprise

    Code Groups:

    1. All code: FullTrust


    Level = Machine

    Code Groups:

    1. All code: Nothing

     1.1. Zone — MyComputer: FullTrust


    Level = User

    Code Groups:

    1. All code: FullTrust


    Success

    Можно заметить, что группы кода перечислены на трех уровнях — Enterprise, Machine и User (Предприятие, Машина и Пользователь). В данный момент сосредоточимся только на уровне Machine, два других более подробно рассмотрим позже. Если вы желаете знать об отношениях между тремя уровнями, то эффективные полномочия, предоставляемые сборке, являются пересечением полномочий из трех уровней. Например, если удалить полномочие

    FullTrust
    из зоны Internet политики на уровне Enterprise, то все полномочия отменяются для кода из зоны Internet и настройки двух других уровней становятся неподходящими.

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

    caspol.exe -resolvegroup http://server/assemply.dll

    Microsoft (R) .NET Framework CasPol 1.0.2728.0

    Copyright (с) Microsoft Corp 1999-2001. All rights reserved.


    Level = Enterprise

    Code Groups:

    1. All code: FullTrust


    Level = Machine

    Code Groups:

    1. All code: Nothing

     1.1. Zone — Internet: Internet

      1.1.1. All code: Same site Socket and Web.


    Level = User

    Code Groups:

    1. All code: FullTrust


    Success

    Для сборки в этот раз можно видеть, что пересечение полномочий оставляет полномочия

    Internet
    и
    Same site S
    ocket.

    Полномочия доступа к коду и множества полномочий

    Представьте себя администратором политики безопасности в сети персональных машин большого предприятия. В такой среде весьма полезно для CLR собирать свидетельства о коде, прежде чем его выполнять, но в равной степени администратор должен иметь возможность строго контролировать, что разрешается делать коду на нескольких сотнях машин, которыми он управляет, если CLR знает, откуда он пришел. Именно здесь начинают играть свою роль полномочия.

    После того как сборка сопоставлена с группами кода, CLR просматривает политику системы безопасности для определения предоставляемых сборке полномочий. Это на самом деле похоже на систему безопасности учетных записей пользователей в Windows 2000. Полномочия обычно применяются не к пользователям, а к группам. То же самое справедливо для сборок: полномочия применяются к группам кода, а не к отдельным сборкам, что делает управление политикой системы безопасности в .NET гораздо более простой задачей.

    Политика безопасности определяет, какие действия разрешается выполнять сборками в группе кода. Давайте обсудим полномочия доступа к коду, предоставляемые CLR. Нижеследующий список показывает, какие возможности предоставляют полномочия доступа к коду:

    □ DirectoryServicesPermission — получение доступа к активному каталогу (Active Directory) с помощью классов

    System.DirectoryServices
    .

    □ DnsPermission — использование системы имен доменов TCP/IP (DNS).

    □ EnvironmentPermission — чтение и запись переменных окружения.

    □ EventLogPermission — чтение и запись в журнал событий.

    □ FileDialogPermission — доступ к файлам, которые были выбраны пользователем в диалоговом окне Open.

    □ FileIOPermission — работа с файлами (чтение, запись и добавление в файл, а также создание и изменение папок).

    □ IsolatedStorageFilePermission — доступ к закрытым виртуальным файловым системам.

    □ IsolatedStoragePermission — доступ к изолированной памяти; памяти, которая ассоциируется с отдельным пользователем и с некоторыми аспектами идентичности кода, такими как его web-сайт, сигнатура или издатель.

    □ MessageQueuePermission — использование очереди сообщений с помощью Microsoft Message Queue.

    □ OleDbPermission — доступ к базам данных с помощью OLE DB.

    □ PerformanceCounterPermission — использование показателей производительности.

    □ PrintingPermission — доступ к печати.

    □ ReflectionPermission — доступ к информации о типе с помощью

    System.Reflection
    .

    □ RegistryPermission — чтение, запись, создание или удаление ключей и значений в реестре.

    □ SecurityPermission — выполнение, объявление полномочий, обращение к неуправляемому коду, пропуск проверки, и другие полномочия.

    □ ServiceControllerPermission — получение доступа (для выполнения или остановки) к службам Windows.

    □ SocketPermission — создание или принятие соединения TCP/IP на транспортном адресе.

    □ SQLClientPermission — доступ к базам данных SQL.

    □ UIPermission — доступ к интерфейсу пользователя.

    □ WebPermission — осуществление или принятие соединения с/из Web.

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

    С практической точки зрения настоятельно рекомендуется все попытки использования ресурсов, связанных с полномочиями в этом списке, помещать внутри блоков обработки ошибок try-catch, чтобы приложение ухудшалось постепенно, если ему придется выполняться с ограниченными полномочиями. Конструкция приложения должна определять, как приложение будет действовать в такой ситуации, не стоит предполагать, что оно начнет выполняться с такой же политикой системы безопасности, с которой оно разрабатывалось. Например, если приложение не может обратиться к локальному диску, закончится ли оно или должно действовать другим способом?

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

    Существует другое множество полномочий, которыми располагает CLR на основе идентичности кода. Эти права не могут быть предоставлены явно, так как они связаны непосредственно со свидетельством, которое CLR сопоставляет со сборкой, и называются полномочиями идентичности (Identity Permisssions). Вот имена классов для полномочий идентичности:

    □ PublisherIdentityPermission — цифровая подпись издателя программного обеспечения.

    □ SiteIdentityPermission — расположение web-сайта, из которого получен код.

    □ StrongNameIdentityPermission — устойчивое имя сборки.

    □ URLIdentityPermission — URL, откуда получен код (включая протокол, например

    https://
    )

    □ ZoneIdentityPermission — зона, являющаяся местом происхождения сборки.

    Обычно полномочия применяются блоками, вот почему .NET предоставляет также множества полномочий (Permission Sets). Это списки прав доступа к коду, сгруппированные в именованном множестве. Вот готовые именованные множества полномочий, существующие в системе:

    □ FullTrust — никаких ограничений на полномочия.

    □ Execution — возможность выполнения, но без доступа к каким-либо защищенным ресурсам.

    □ Nothing — никаких полномочий и невозможность выполнения.

    □ LocalIntranet — политика по умолчанию для локальной интранет, подмножество полного множества полномочий. Можно изменять это множество полномочий.

    □ Internet — политика по умолчанию для кода неизвестного происхождения. Администратор может управлять полномочиями в этом множестве полномочий.

    □ Everything — все стандартные полномочия, за исключением полномочия пропускать проверку кода. Администратор может изменить чье-либо право в этом множестве полномочий. Это полезно там, где политика по умолчанию должна быть строже.

    Отметим, что из этих именованных множеств можно изменять определения только трех последних, а первые три являются фиксированными и не могут изменяться.

    Полномочия идентичности не могут включаться в множества полномочий, так как CLR является единственным уполномоченным, который может предоставить коду права идентичности. Например, если фрагмент кода принадлежит определенному издателю, то мало смысла со стороны администратора предоставлять ему полномочия идентичности, связанные с другим издателем. CLR дает права, если необходимо, а мы может затем при желании их использовать.

    Просмотр полномочий сборки

    Предположим, что используется приложение, написанное компанией Microsoft, и мы пытаемся использовать свойство, которое раньше не использовалось. Приложение не имеет копии кода, хранящейся локально, поэтому оно запрашивает ее, и код загружается в глобальный кэш сборок. При таком сценарии для кода из Интернета, опубликованного указанной организацией, подписавшей сборку с помощью сертификата, мы обнаружим, что членство группы кода сборки выглядит примерно так:

    Согласно политике в этом примере, группы кода All Code и Internet предоставляют только ограниченные полномочия, а членство группы кода в правом нижнем углу предоставляет сборке полномочие FullTrust. Права всех групп кода объединяются в создании общего эффективного полномочия самого высокого уровня. Таким образом, каждая группа кода, к которой принадлежит сборка, вносит дополнительные полномочия.

    Кроме групп кода, к которым принадлежит сборка, мы можем наблюдать полномочия, присвоенные группам кода, а также полномочия идентичности кода, которые дают нам доступ к свидетельству, представленному кодом во время выполнения. Чтобы увидеть полномочия для групп кода сборки, используется команда:

    caspol.exe -resolveperm assembly.dll

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

    caspol.exe -resolveperm http://intranet/assembly.dll


    Microsoft (R) .NET Framework CasPol 1.0.xxxx.x

    Copyright (c) Microsoft Corp 1999-2001. All rights reserved.


    Resolving permissions for level = Enterprise

    Resolving permissions for level = Machine

    Resolving permissions for level = User


    Grant =

    <PermissionSet class="System.Security.PermissionSet" version="1">

     <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Read="USERNAME;TEMP;TMP" />

     <IPermission class ="System.Security.Permissions.FileDialogPermission, mscorlib, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Unrestricted="true" />

     <IPermission class="System.Security.Permissions.IsolatedStorageFilePermission, mscorlib Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Allowed="AssemblyIsolationByUser"

      UserQuota="9223372036854775807"

      Expiry = "9223372036854775807"

      Permanent="True" />

     <IPermission class="System.Security.Permissions.ReflectionPermission, mscorlib, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Flags="ReflectionEmit" />

     <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Flags="Assertion, Execution, RemotingConfiguration" />

     <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Unrestricted="true" />

     <IPermission class="System.Net.WebPermission, System, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1">

      <ConnectAccess>

       <URI uri="(https|http)://intranet/.*"/>

      </ConnectAccess>

     </IPermission>

     <IPermission class="System.Net.DnsPermission, System, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Unrestricted="true"/>

     <IPermission class="System.Drawing.Printing.PrintingPermission, System.Drawing, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

      version="1"

      Level="DefaultPrinting" />

     <IPermission сlass="System.Diagnostics.EventLogPermission, System, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1">

      <Machine name="." access="Instrument" />

     </IPermission>

     <IPermission class="System.Security.Permissions.SiteIdentityPermission, mscorlib, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Site="intranet" />

     <IPermission class="System.Security.Permissions.UrlIdentityPermission, mscorlib, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Url="http://intranet/assembly.dll" />

     <IPermission сlass="System.Security.Permissions.ZoneIdentityPermission, mscorlib, Version=1.0.xxxx.x, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Zone="Intranet" />

    </PermissionSet>


    Success

    Этот вывод показывает каждое из полномочий в виде кода XML, включая определяющий полномочие класс, содержащую класс сборку, версию полномочия и признак шифрования. Вывод предполагает, что можно создать свои собственные полномочия, больше об этом будет сказано позже. Можно также видеть, что каждое из полномочий идентичности содержит более подробную информацию, скажем, о классе

    UrlIdentityPermission
    , предоставляющем доступ к URL кода.

    Отметим, что в начале вывода

    caspol.exe
    разрешает полномочия на уровнях
    Enterprise
    ,
    Machine
    и
    User
    и затем перечисляет действующие представленные права. Теперь перейдем к этому вопросу.

    Уровни политики: машина, пользователь и предприятие

    До сих пор безопасность рассматривалась в контексте одной машины. Часто необходимо определить политику системы безопасности для определенных пользователей или для всей организации, и именно поэтому .NET предоставляет не один, а три уровня групп кода:

    □ Machine (Машина)

    □ Enterprise (Предприятие)

    □ User (Пользователь)

    Уровни групп кода управляются независимо и существуют параллельно:

    Если существует три вида политики безопасности, как узнать, какая применяется? Действующим полномочием является пересечение полномочий трех уровней. Каждый из трех уровней имеет возможность запретить права, предоставленные другими,— это хорошая весть для администраторов, так как их настройки будут переопределять настройки пользователя.

    Для работы с группами кода и полномочиями на уровнях пользователя или предприятия с помощью

    caspol.exe
    добавьте либо аргумент
    enterprise
    , либо аргумент
    user
    , чтобы изменить режим команды,
    caspol.exe
    работает по умолчанию на уровне
    Machine
    ; таким образом эта утилита до сих пор и использовалась. Просмотрим группы кода, перечисленные на уровне
    User
    :

    caspol.exe -user -listgroups

    Так выглядит вывод команды при установке по умолчанию:

    Security is ON

    Execution checking is ON

    Policy change prompt is ON


    Level = User

    Code Groups:


    1. All code: FullTrust

    Success

    Теперь выполним ту же самую команду, но в этот раз, чтобы увидеть группы кода на уровне

    Enterprise
    :

    caspol.exe -enterprise -listgroups

    Вывод команды выглядит так:

    Security is ON

    Execution checking is ON

    Policy change prompt is ON


    Level = Enterprise

    Code Groups:


    1. All code: FullTrust

    Success

    Как можно видеть, по умолчанию оба уровня,

    User
    и
    Enterprise
    , конфигурируются с предоставлением
    FullTrust
    для единственной группы кода
    All Code
    . В результате этого настройка по умолчанию для системы безопасности .NET не налагает никаких ограничений на уровне пользователя или предприятия, и реализованная политика диктуется исключительно политикой уровня машины. Например, если требуется применить более строгое полномочие или множество полномочий к уровню пользователя или предприятия, эти ограничения будут налагаться на все полномочия и, возможно, переопределять права на уровне машины. Действующие полномочия являются пересечением, поэтому, например, если необходимо применить
    FullTrust
    к группе кода, это полномочие должно быть присвоено группе кода на каждом из трех уровней политики.

    При выполнении

    caspol.exe
    администратором по умолчанию используется уровень машины, но если выйти из системы и зарегистрироваться как пользователь, который не принадлежит группе пользователей
    Administrator
    ,
    caspol.exe
    выберет по умолчанию уровень пользователя. Кроме того,
    caspol.exe
    не позволит изменить политику безопасности таким образом, чтобы сделать саму утилиту
    caspol.exe
    неработоспособной.

    Теперь мы получили общее представление об архитектуре безопасности в .NET и можем перейти к обсуждению, как получить доступ к ее свойствам программным путем.

    Поддержка безопасности в .NET

    Чтобы система безопасности .NET работала, программистам необходимо доверить CLR обеспечение политики безопасности. Как это сделать? Когда вызывается метод, требующий специальных полномочий (например, доступ к файлу на локальном диске), CLR будет просматривать стек с целью гарантии того, что участник цепочки вызовов имеет требуемые права.

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

    Для справки, наиболее применимыми в этой главе частями библиотеки .NET Framework являются:

    System.Security.Permissions

    System.Security.Policy

    System.Security.Principal

    Отметим, что система безопасности доступа к коду на основе свидетельства работает в паре с системой безопасности регистрации в Windows. Если вы захотите выполнить приложение для настольного компьютера .NET, то ему должны быть предоставлены соответствующие полномочия системы безопасности доступа к коду .NET, но регистрирующийся пользователь должен также работать под учетной записью Windows, которая имеет соответствующие права для выполнения кода. В применении к настольным приложениям это означает, что текущему пользователю должны быть предоставлены соответствующие права для доступа к соответствующим файлам сборки на диске. Для приложений Интернета учетная запись, с которой работает Информационный сервер Интернет, должна иметь доступ к файлам сборки.

    Требуемые полномочия

    Создадим приложение Windows Forms с кнопкой, которая при нажатии будет выполнять действие, обращающееся к диску. Предположим, что если приложение не имеет подходящего полномочия для доступа к локальному диску (

    FileIOPermission
    ), кнопка будет помечаться как недоступная (серым цветом).

    В следующем коде представлен конструктор формы, который создает объект

    FileIOPermission
    , вызывает его метод
    Demand()
    и затем обрабатывают результат:

    using System;

    using System.Drawing;

    using System.Collections;

    using System.ComponentModel;

    using System.Windows.Forms;

    using System.Data;

    using System.Security;

    using System.Security.Permissions;


    namespace SecurityApp4 {

     public class Form1 : System.Windows.Forms.Form {

      private System.Windows.Forms.Button button1;

      private System.ComponentModel.Container components;

      public Form1() {

       InitializeComponent();

       try {

        FileIOPermission fileioperm = new

        FileIOPermission(FileIOPermissionAccess.AllAccess, @"C:\");

        fileioperm.Demand();

       } catch {

        button1.Enabled = false;

       }

      }

      public override void Dispose() {

       base.Dispose();

       if(component != null) components.Dispose();

      }

    #region Windows Form Designer generated code

      /// <summary>

      /// Требуемый метод для поддержки конструктора — не изменяйте

      /// содержимое этого метода с помощью редактора кода.

      /// </summary >

      private void InitializeComponent() {

       this.button1 = new System.Windows.Forms.Button();

       this.SuspendLayout();

       //

       // button1

       //

       this.button1.Location = new System.Drawing.Point(48, 104);

       this.button1.Name = "button1";

       this.button1.Size = new System.Drawing.Size(192, 23);

       this.button1.TabIndex = 0;

       this.button1.Text = "Button Requires FileIOPermission";

    //

       // Form1

       //

       this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

       this.ClientSize = new System.Drawing.Size(292, 273);

       this.Controls.AddRange(new System.Windows.Forms.Control[] {this.button1});

       this.Name = "Form1";

       this.Text = "Form1";

       this.ResumeLayout(false);

      }

    #endregion

      /// <summary>

      /// Основная точка входа для приложения.

      /// </summary >

      [STAThread]

      static void Main() {

       Application.Run(new Form1());

      }

     }

    }

    Можно заметить, что

    FileIOPermission
    содержится в пространстве имен
    System.Security.Permissions
    , которое имеет все множество полномочий, а также предоставляет классы для декларативных атрибутов полномочий и перечисления параметров, используемых при создании объектов прав (например, при создании
    FileIOPermission
    , определяющего, нужен нам полный доступ или только для чтения).

    При выполнении приложения с локального диска, где используемая по умолчанию политика безопасности разрешает доступ к локальной памяти, приложение будет выглядеть следующим образом:

    Но если скопировать исполняемый файл на сетевой диск общего доступа и снова его выполнить, то он будет действовать внутри множества полномочий LocalIntranet, которое блокирует доступ к локальной памяти, и кнопка будет неработоспособной (серой):

    Если при нажатии на кнопку была реализована функциональность для доступа к диску, не требуется писать никакой код для системы безопасности, так как соответствующий класс в .NET Framework будет запрашивать полномочия файла и CLR гарантирует, что каждый вызывающий в стеке будет иметь эти полномочия, прежде чем продолжить. При выполнении приложения из интранет, которое пытается открыть файл на локальном диске, будет порождаться исключение при условии, что политика безопасности не была изменена.

    При желании перехватывать исключения, порождаемые CLR, когда код пытается действовать вопреки предоставленным ему правам, можно перехватывать исключение типа

    SecurityException
    , которое предоставляет доступ к ряду полезных элементов информации, включая читаемую человеком трассировку стека (
    SecurityException.StackTrace
    ) и ссылку на метод, порождающий исключение (
    SecurityException.TargetSite
    ).
    SecurityException
    предоставляет также свойство
    SecurityException.PermissionType
    , возвращающее тип объекта
    Permission
    , который порождает исключения безопасности.

    Запрашиваемые полномочия

    Как мы видели выше, требуемые полномочия вполне четко определяют, что необходимо во время выполнения, однако можно сконфигурировать сборку так, чтобы она делала более мягкий запрос прав прямо в начале выполнения, где она объявляет, что ей нужно: Можно запросить полномочия тремя способами:

    □ Минимальные полномочия (Mimimum) — полномочия, которые требуются коду для выполнения.

    □ Необязательные полномочия (Optional) — полномочия, которые код может использовать, но способен эффективно выполняться и без них.

    □ Непригодные полномочия (Refused) — полномочия, которые не должны предоставляться коду.

    Почему необходимо запрашивать полномочия при запуске сборки? Существует несколько причин:

    □ Если сборке требуются некоторые полномочия для выполнения, то имеет смысл сообщить об этом в начале, а не во время выполнения.

    □ Будут предоставлены только запрашиваемые полномочия и никакие другие. Это сокращает риск воздействия сборки на области, для которых у нее нет прав.

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

    Запрос полномочий скорее всего будет тем нужнее, чем более сложная разработка реализуется, но существует высокий риск, что приложение будет установлено на машине, которая не предоставляет необходимых прав. Обычно для приложения более предпочтительно знать в самом начале выполнения, где ему не предоставлены полномочия, а не в середине процесса выполнения.

    Чтобы успешно запрашивать полномочия для сборки, нужно точно отслеживать, какие права использует сборка. В частности, необходимо знать о требованиях полномочий вызовов, которые делает сборка в других библиотеках классов, включая .NET Framework.

    Три примера из файла

    AssemblyInfo.cs
    (см. ниже) демонстрируют использование атрибутов для запроса полномочий. Эти примеры можно найти в проекте
    SecurityАрр9
    среди загружаемых с сайта издательства Wrox файлов. Первый атрибут выдвигает требование, чтобы сборка имела
    UIPermission
    , что даст приложению доступ к интерфейсу пользователя. Запрос делается для минимальных полномочий, а если это право не предоставляется, то сборка не сможет запуститься.

    Using System.Security.Permissions;

    [assembly:UIPermissionAttribute(SecurityAction.RequestMimimum)]

    Затем запрашивается, отказывается ли сборка от доступа к диску

    C:\
    . Настройка атрибута означает, что для всей сборки будет заблокирован доступ к этому диску:

    [assembly:FileIOPermissionAttribute(SecurityAction.RequestRefuse, Read="C:\\")]

    Ниже дан атрибут, который запрашивает для сборки необязательные полномочия, чтобы обеспечить доступ к неуправляемому коду:

    [assembly:SecurityPermissionAttribute(SecurityAction.RequestOptional,

     Flags = SecurityPermissionFlag.UnmanagedCode)]

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

    При рассмотрении требований полномочий для приложения обычно необходимо выбрать одну из следующих возможностей:

    □ Запрос всех необходимых полномочий в начале выполнения и постепенное снижение требований или выход, если эти полномочия не предоставлены.

    □ Отказ от запроса полномочий в начале выполнения, но готовность обрабатывать исключения безопасности внутри приложения.

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

    permview.exe assembly.dll

    Вывод для приложения, использующего три показанных атрибута, будет выглядеть так.

    minimal permission set:

    <PermissionSet class="System.Security.PermissionSet" version="1">

     <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=1 .0.2411.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1" Unrestricted="true" />

    </PermissionSet>

    optional permission set:

    <PermissionSet class="System.Security.Permission.Set" version="1">

     <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=1.0.2411.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Flags="UnmanegedCode" />

    </PermissionSet>

    refused permission set:

    <PermissionSet class="System.Security.PermissionSet" version="1" >

     <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=1.0.2411.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

      version="1"

      Read="C:\" />

    </PermissionSet>

    В дополнение к запрашиваемым полномочиям можно также запросить целое множество прав сразу. Так как некоторые множества полномочий (

    Internet
    ,
    LocalIntranet
    и
    Everything
    ) изменяются с помощью политики безопасности при выполнении сборки, то они запрашиваться не могут. Например, если сборка сообщила, что ей необходимо предоставить для выполнения все полномочия в множестве полномочий
    LocalIntranet
    , а администратор затем сузил множество прав
    LocalIntranet
    во время выполнения приложения, то может быть неизвестно, в каком множестве прав происходит работа.

    Существует три множества полномочий, которые нельзя изменить во время выполнения приложения, эти множества могут запрашиваться с помощью атрибутов:

    □ 

    Nothing

    □ 

    Execution

    □ 

    FullTrust

    Вот пример того, как запрашивается встроенное множество полномочий:

    [assembly:PermissionSetAttribute(SecurityAction.RequestMinimum,

     Name = "FullTrust")]

    В этом примере сборка запрашивает, как минимум, встроенное множество полномочий

    FullTrust
    . Если это множество не будет предоставлено, то сборка породит во время выполнения исключение безопасности.

    Неявное полномочие

    Часто, когда предоставлена некоторые полномочия, возникает неявное утверждение, что также даны и другие полномочия. Например, если присвоено полномочие

    FileIOPermission
    для
    C:\
    , то неявно предполагается, что также имеется доступ к его подкаталогам (допущение системы безопасности учетных записей Windows).

    Если необходимо проверить, что данное полномочие неявно вносит другое полномочие в качестве подмножества, то можно сделать следующее.

    // Пример из SecurityApp5

    class Class1 {

     static void Main(string[ ] args) {

      CodeAccessPermission permissionA =

       new FileIOPermission(FileIOPermissionAccess.AllAccess, @"C:\");

      CodeAccessPermission permissionB =

       new FileIOPermission(FileIOPermissionAccess.Read, @"C:\temp");

      if (permissions.IsSubsetOf(permissionA) {

       Console.WriteLine("PermissionB is a subset of PermissionA");

      } else {

       Console.WriteLine("PermissionB is NOT a subset of PermissionA");

      }

     }

    }

    Вывод будет выглядеть следующим образом:

    PermissionB is a subset of PermissionA

    Отказ от полномочий

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

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

    Deny()
    :

    using System;

    using System.IO;

    using System.Security;

    using System.Security.Permissions;

    namespace SecurityApp6 {

     class Class1 {

      static void Main(string[] args) {

    CodeAccessPermission permission =

        new FileIOPermission(FileIOPermissionAccess.AllAccess, @"C:\");

       permission.Deny();

       UntruscworthyClass.Method();

       CodeAccessPermission.RevertDeny();

      }

     }

     class UntrustworthyClass {

      public static void Method() {

       try {

        StreamReader din = File.OpenText(@"C:\textfile.txt");

       }

       catch {

        console.WriteLine("Failed to open file");

       }

      }

     }

    }

    Если выполнить этот код, то будет выведено сообщение

    Failed to open file
    , так как ненадежный класс не имеет доступа к локальному диску.

    Отметим, что вызов

    Deny()
    делается на экземпляре класса полномочия, в то время как вызов
    RevertDeny()
    выполняется статически. Причина этого заключается в том, что вызов
    RevertDeny()
    возвращает в прежнее состояние все запросы
    Deny()
    в рамках текущего стека. Таким образом, если было сделано несколько вызовов
    Deny()
    , то необходимо сделать только один последующий вызов
    RevertDeny()
    .

    Заявляемые полномочия

    Пусть имеется сборка, которая была установлена в системе пользователя с полномочиями Full Trust. В этой сборке существует метод, который сохраняет контрольную информацию в текстовом файле на локальном диске. Если позже будет установлено приложение, для которого следует воспользоваться свойством контроля, то для приложения необходимо будет иметь соответствующие полномочия

    FileIOPermission
    для сохранения данных на диске.

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

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

    Приведенный ниже код содержит класс

    AuditClass
    , реализующий метод
    Save()
    , который получает строку и сохраняет контрольные данные в
    C:\audit.txt
    . Метод AuditClass заявляет полномочия, которые ему нужны для добавления контрольных строк в файл. Чтобы протестировать это, метод приложения
    Main()
    явно отвергает полномочие файла, которое требуется методу
    Audit
    :

    using System;

    using System.IO;

    using System.Security;

    using System.Security.Permissions;

    namespace SecurityApp7 {

     class Class1 {

      static void Main(string[] args) {

       CodeAccessPermission permission =

        new FileIOPermission(FileIOPermissionAccess.Append, @"C:\audit.txt");

       permission.Deny();

       AuditClass.Save("some data to audit");

       CodeAccessPermission.RevertDeny();

      }

     }

     class AuditClass {

      public static void Save (string value) {

       try {

        FileIOPermission permission =

         new FileIOPermission(FileIOPermissionAccess.Append, @"C:\audit.txt");

        permission.Assert();

        FileStream stream new FileStream(@"C:\audit.txt", FileMode.Append, FileAccess.Write);

        // код для записи файла контроля здесь

        CodeAccessPermission.RevertAssert();

        Console.WriteLine("Data written to audit file");

       } catch {

        Console.WriteLine("Failed to write data to audit file");

       }

      }

     }

    }

    При выполнении этого кода оказывается, что вызов метода

    AuditClass
    не порождает исключения безопасности, несмотря на то, что при вызове он не имел требуемых полномочий для доступа к диску.

    Как и в случае

    RevertDeny()
    ,
    RevertAssert()
    , являясь статическим методом, отменяет все заявления в текущей среде выполнения. Важно быть очень осторожным при использовании заявлений. Мы явно присваиваем полномочия методу, вызываемому кодом, который вполне может не иметь этих полномочий. Например, в коде с контролем, даже если политика безопасности диктует, что установленные приложения не могут делать записей на локальный диск, данное приложение выполнит это, если функции контроля были установлены с полномочиями Full Trust.

    Создание полномочий доступа к коду

    .NET Framework реализует полномочия безопасности доступа к коду, которые предоставляют защиту для ресурсов. Однако в ситуациях, когда необходимо создать свои собственные полномочия, это можно сделать с помощью подклассов

    CodeAccessPermission
    . Вывод из этого класса предоставляет возможности системы безопасности доступа к коду из .NET, включая просмотр стека и управление политикой.

    Вот два случая, когда может понадобиться создание своих собственных полномочий доступа к коду:

    □ Защита ресурса, еще не защищенного с помощью Framework. Например, разработано приложение .NET для автоматизации, которое реализуется с помощью встроенного аппаратного устройства. Создавая свой собственный код полномочий доступа, можно получить достаточно развитый уровень управления доступом для данного устройства автоматизации.

    □ Дополнительное ограничение существующих полномочий. Например, хотя .NET Framework дает права, допускающие точный контроль за доступом к локальной файловой системе, можно иметь приложение, где желательно контролировать доступ к определенному файлу или папке более жестко. При таком сценарии полезно создать полномочие доступа к коду, которое связано специально с этим файлом или папкой, и без этого полномочия никакой управляемый код не может получить доступ к этой области на диске.

    Декларативная безопасность

    Можно отказаться, запросить или заявить полномочия, вызывая классы в .NET Framework, но можно также использовать атрибуты и определять требования полномочий декларативно.

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

    Допустим, мы объявляем, что метод для выполнения должен иметь полномочие на чтение с

    C:\
    .

    using System;

    using System.Security.Permissions;

    namespace SecurityApp8 {

     class Class1 {

      static void Main(string[] args) {

       MyClass.Method();

      }

     }

     [FileIOPermission(SecurityAction.Assert, Read="C:\\")]

     class MyClass {

      public static void Method() {

       // реализация находится здесь

      }

     }

    }

    Помните, что если атрибуты применяются для заявления или запроса полномочий, невозможно перехватить исключения, возникающие в случае отказа действия, так как не существует обязательного кода, который можно поместить в предложение try-catch-finally.

    Чтобы узнать обо всех доступных атрибутах, можно ознакомиться с перечислением

    System.Security.Permissions.SecurityAction
    .

    Система безопасности на основе ролей

    Как мы видели, система безопасности доступа к коду дает CLR возможность неявно решить, должен ли код выполняться и с какими полномочиями на основе свидетельства о коде. В дополнение к этому .NET предоставляет систему безопасности на базе ролей, которая определяет, может ли код выполнить действия на основе свидетельства о пользователе и его роли.

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

    Система безопасности на основе ролей также является идеальной для использования в соединении с учетными записями Windows 2000, Microsoft Passport или специальным каталогом пользователя для управления доступом к ресурсам на основе Web. Например, web-сайт может ограничить доступ к своему содержимому, пока пользователь не зарегистрирует свои данные на этом сайте, и затем дополнительно предоставит доступ к специальному содержимому, только если пользователь является оплаченным подписчиком. Во многих отношениях ASP.NET делает систему безопасности на основе ролей проще, так как большая часть кода находится на сервере.

    Например, если желательно реализовать службу Web, требующей аутентификации, то можно использовать подсистему учетных записей Windows 2000 и написать метод для Web таким образом, чтобы он проверял, является ли пользователь членом определенной группы пользователей Windows 2000, прежде чем предоставлять доступ к функциональности метода.

    Принципал

    .NET предоставляет текущему потоку выполнения простой доступ к пользователю приложения, который обозначается как

    Principal
    . Принципал является ядром системы безопасности, предоставленной .NET, на основе ролей, и через него можно получить доступ к объекту
    Identity
    пользователя, который отображается в учетной записи пользователя одного из приведенных ниже типов:

    □ Учетная запись Windows

    □ Учетная запись Passport

    □ Пользователь, аутентифицированный с помощью cookie из ASP.NET

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

    IPrincipal
    . Если вы не полагаетесь на аутентификацию Windows, Passport или простую аутентификацию с помощью
    cookie
    , необходимо рассмотреть вопрос о создании своей собственной аутентификации с помощью специального класса
    principal
    .

    С помощью доступа к принципалу можно делать выводы о безопасности на основе идентичности и ролей принципала. Роль является совокупностью пользователей, которые имеют одинаковые полномочия безопасности, и является единицей администрации пользователей. Например, при использовании аутентификации Windows будет применяться тип WindowsIdentity в качестве варианта Identity. Можно выбрать этот тип для выяснения, является ли пользователь членом определенной группы учетных записей пользователей Windows, а затем использовать эту информацию для решения, предоставить или отменить доступ к коду и ресурсам.

    Обычно значительно легче управлять безопасностью, если доступ к ресурсам и функциональности разрешается на основе полномочий, а не ролей. Представьте сценарий, где имеется три метода, каждый из них предоставляет доступ к свойству, для которого требуется строгий контроль, чтобы гарантировать, что только авторизованному персоналу доступ к нему открыт. Если приложение имеет, скажем, четырех пользователей, то достаточно легко определить в каждом методе, какие пользователи могут и какие не могут получить доступ к методу. Однако представим ситуацию, где число свойств возрастает до девяти. Чтобы разрешить доступ для дополнительного пользователя, потенциально потребуется изменить каждый из девяти методов, хотя это является административной задачей. Даже хуже, так как пользователи меняются ролями в компании и понадобится изменять код каждый раз, когда это происходит. Если вместо этого реализовать систему, использующую роли, то можно просто добавлять и удалять пользователей из ролей, а не добавлять и удалять отдельных пользователей из приложения. Таким образом, выполнение приложения облегчается, и для каждого метода мы только ставим условие, чтобы пользователь был членом определенной группы. Ото также упрощает управление ролями, так как эту работу может делать администратор, а не разработчик приложения. Говоря проще, разработчик сосредоточивается на том, что, например, Managers, но не Secretaries, могут получить доступ к методу, а не на том, каковы возможности Julie и Bob, но не Conrad.

    Система безопасности на основе ролей в .NET строится на системе безопасности из MTS и COM+ 1.0 и предоставляет гибкую среду, создающую ограждения вокруг разделов приложения, которые должны быть защищены. Если система COM+ 1.0 установлена на машине, ее безопасность на основе ролей будет интерпретироваться в NET, однако COM не требуется .NET на основе ролей для функционирования системы безопасности.

    Принципал Windows

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

    System.Security.Principal
    и
    System.Threading
    . Прежде всего нужно задать, что мы хотим, чтобы .NET автоматически соединял принципал с описанной ниже учетной записью Windows, так как в .NET это не происходит автоматически по соображениям безопасности. Наше задание:

    using System;

    using System.Security.Principal;

    using System.Security.Permissions;

    using System.Threading;


    namespace SecurityApplication2 {

     class Class1 {

      static void Main(string[] args) {

       AppDomain.CurrentDomain.SetPrincipalPolicy(

        PrincipalPolicy.WindowsPrincipal);

    Можно использовать метод

    WindowsIdentity.GetCurrent()
    для доступа к данным учетной записи Windows, однако такой способ подходит, когда необходимо взглянуть на принципал один раз. Если необходимо обратиться к принципалу несколько раз, то более эффективно задать политику так, чтобы текущий поток выполнения предоставлял доступ к принципалу. При использовании метода
    SetPrincipalPolicy
    определяется, что принципал в текущем потоке выполнения должен поддерживать объект
    WindowsIdentity
    . Добавим код для доступа к свойствам принципала из объекта
    Thread
    :

       WindowsPrincipal principal =

       (WindowsPrincipal)Thread.CurrentPrincipal;

       WindowsIdentity identity = (WindowsIdentity)principal.Identity;

       Console.WriteLine("IdentityTyрe:" + identity.ToString());

       Console.WriteLine("Name:" + identity.Name);

       Console.WriteLine(

        "Users'?:" + principal.IsInRole("BUILTIN\\Users"));

       Console.WriteLine(

        "Administrators' ?: " +

        principal.IsInRole(WindowsBuiltInRole.Administrator));

       Console.WriteLine("Authenticated:" + identity.IsAuthenticated);

       Console.WriteLine("AuthType:" + identity.AuthenticationType);

       Console.WriteLine("Anonymous?:" + identity.IsAnonymous);

       Console.WriteLine("Token:" + identity.Token);

      }

     }

    }

    Вывод из этого консольного приложения будет выглядеть похожим на следующий, в зависимости от конфигурации машины и ролей, ассоциированных с учетной записью, под которой вы зарегистрировались в системе:

    IdentityType:System.Security.Principal.WindowsIdentity

    Name:MACHINE\alaric

    'Users'?:True

    'Administrators'?:True

    Authenticated:True

    AuthType:NTLM

    Anonymous?:False

    Token:256

    Очевидно, что крайне полезно иметь возможность получить так легко доступ к данным о текущем пользователе и его ролях, чтобы с помощью этой информации решать, какие действия выполнить и какие отменить. Роли и группы пользователей Windows предоставляют администраторам дополнительную возможность использовать стандартные утилиты администрирования пользователей, и обычно можно избежать изменения кода, когда изменяются роли пользователя. Рассмотрим роли более подробно.

    Роли

    Представим сценарий, где имеется приложение интранет, использующее учетные записи Windows. Система имеет группу

    Manager
    и группу
    Assistant
    , пользователи относятся к этим группам в зависимости от их роли в организации. Пусть приложение содержит свойство, выводящее информацию о сотрудниках, и желательно, чтобы к нему имела доступ только группа
    Manager
    . Можно легко применить код, который проверяет, является ли текущий пользователь членом группы
    Manager
    , и разрешать или запретить ему доступ на основе этого.

    Однако, если в дальнейшем будет решено реорганизовать группы учетных записей и ввести группу

    Personnel
    , которая также имеет доступ к данным о сотрудниках, то возникнет проблема. Придется просмотреть весь код и обновить его, чтобы включить правила для этой новой группы.

    Лучшим решением было бы создание полномочия, называемого, предположим,

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

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

    Так же, как в случае с системой безопасности доступа к коду, можно реализовать запросы безопасности на основе ролей ("пользователь должен быть в группе Administrators"), используя обязательные запросы (см. предыдущий раздел), или использовать атрибуты. Возможно декларативное определение требований к полномочию на уровне класса в таком виде:

    using System;

    using System.Security;

    using System.Security.Principal;

    using System.Security.Permissions;


    namespace SecurityApp3 {

     class Class1 {

      static void Main(string[] args) {

       AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);

       try {

        ShowMessage();

       } catch (SecurityException exception) {

        Console.WriteLine(

         "Security exception caught (" + exception.Message + ")");

        Console.WriteLine(

         "The current principal must be in the local"

         + "Users group");

       }

      }

      (PrincipalPermissionAttribute(SecurityAction.Demaid, Role =

       "BUILTIN\\Users"));

      static void ShowMessage() {

       Console.WriteLine("The current principal is longed in locally");

       Console.WriteLine("they are a member of the local Users group)");

      }

     }

    }

    Метод

    ShowMessage()
    будет порождать исключение, если приложение выполняется не в контексте пользователя из группы локальных Users в Windows 2000. Что касается приложений Web, то учетная запись, под которой выполняется код ASP.NET, должна быть в группе, хотя в реальном мире определенно будут избегать добавления этой учетной записи в группу администраторов.

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

    The current principal is logged in locally

    (they are a member of the local Users group)

    Дополнительную информацию о системе безопасности на основе ролей в .NET можно найти в документации MSDN для пространства имен

    System.Security.Principal
    .

    Управление политикой системы безопасности

    Аспекты безопасности .NET разработаны значительно полнее и шире, чем какие-либо другие вопросы в Windows, но все же есть и которые ограничения, о которых необходимо знать:

    □ Политика системы безопасности .NET не обеспечивает безопасность на неуправляемом коде (хотя обеспечивает некоторую защиту от обращении к неуправляемому коду).

    □ Если пользователь копирует сборку на свою локальную машину, сборка имеет полномочия

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

    □ Политик системы безопасности .NET предоставляет очень небольшую помощь при борьбе со злонамеренными файлами .ЕХЕ Win32 и вирусами на основе сценариев, с которыми Microsoft борется различными способами. Например недавние версии Outlook не позволяют обрабатывать исполнимые файлы из почтовых сообщений, пользователь предупреждается, что они могут содержать вирусы, и сохраняет их на диске, где имеются возможности для установки административных ограничений, включая блокирование доступа к локальному диску и работу антивирусного программного обеспечения.

    Однако .NET существенно помогает операционной системе в ответах на вопросы, сколько полномочий предоставить коду, будет ли он приложением интранет, элементом управления на странице Web или приложением Windows Forms, загруженным от поставщика программного обеспечения в Интернете.

    Конфигурационный файл системы безопасности

    Как мы уже видели, общим звеном, соединяющим группы кода, полномочия и множества полномочий, являются три уровня политики системы безопасности (Enterprise, Machine и User). Информация о конфигурации системы безопасности в .NET хранится в конфигурационных файлах XML, которые защищены системой безопасности Windows. Например, политика безопасности уровня Machine распространяется только на пользователей групп Administrator, Power User и SYSTEM в Windows 2000.

    В Windows 2000 файлы, которые хранят политику безопасности расположены в следующих местах:

    Конфигурация политики предприятия

    C:\WinNT\Microsoft.NET\Framework\v1.0.xxxx\Config\enterprise.config

    Конфигурация политики машины

    C:\WinNT\Microsoft.NET\Framework\v1.0.xxxx\Config\security.config

    Конфигурация политики пользователя

    %USERPROFILE%\application data\Microsoft\CLR security config\vxx.xx\security.config

    Номер версии, отмеченный несколькими 'x', будет меняться в зависимости от версии .NET Framework, установленной на машине. При необходимости можно вручную редактировать эти конфигурационные файлы, например, если администратору нужно сконфигурировать политику для пользователя не регистрируясь в системе со своей учетной записью. Однако в общем рекомендуется использовать

    caspol.exe
    или подключаемый модуль ММС для управления политикой системы безопасности.

    Простой пример

    Создадим небольшое приложение, обращающееся к локальному диску, поведение которого требует тщательного управления. Приложение относится к C# Windows Forms с окном списка и кнопкой. Если нажать на кнопку, то окно списка заполняется из файла с именем

    animals.txt
    в корне диска
    C:\
    :

    Приложение создается с помощью Visual Studio.NET, единственными изменениями в нем являются добавления к форме окна списка и кнопки Load Data, а также подключение к кнопке события, что выглядит следующим образом.

    // Пример из SecurityAppl

    private void button1_Click(object sender, System.EventArgs e) {

     StreamReader stream = File.OpenText(@"C:\animals.txt");

     String str;

     while ((str = stream.ReadLine()) != null) {

      listBox1.Items.Add(str);

     }

    }

    Метод открывает простой текстовый файл из корня диска

    C:\
    , который содержит список животных на отдельных строках, и загружает каждую строку в переменную типа string, которая затем используется для создания каждого элемента в окне списка.

    Если выполнить приложение на локальной машине и нажать кнопку, то мы увидим загруженные из корня диска

    C:\
    данные, выведенные в окне списка, как и ожидалось. Неявно среда выполнения предоставила сборке полномочие, которое необходимо для выполнения, доступа к интерфейсу пользователя и чтения данных с локального диска:

    Вспомним, что полномочия группы кода в зоне интранет являются более строгими, чем на локальной машине, в частности, они не разрешают доступ к локальному диску (за исключением папки, из которой выполняется приложение). Если снова выполнить приложение, но в этот раз с общего сетевого диска, оно будет выполняться так же, как и раньше, поскольку ему предоставлены полномочия для выполнения и доступа к интерфейсу пользователя. Однако, если теперь нажать кнопку Load Data на форме, будет порождаться исключение безопасности:

    В тексте сообщения исключения упоминается объект

    System.Security.Permissions.FileIOPermission
    . Он является полномочием, не предоставленным приложению и запрошенным классом из Framework, который используется для загрузки данных из файла на локальном диске.

    По умолчанию группе кода Intranet предоставляется множество полномочий

    LocalIntranet
    . Изменим с помощью следующей команды это множество полномочий на
    FullTrust
    , чтобы любой код из зоны интранет мог выполняться полностью без ограничений.

    caspol.exe -chggroup 1.2 FullTrust

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

    C:\
    и исключения не возникают.

    В подобных сценариях, где используются ресурсы, управляемые полномочиями, рекомендуется расширять код, чтобы исключения безопасности перехватывались и приложение могло постепенно уменьшать свою деятельность. Например, в данном приложении можно добавить блок try-catch вокруг кода доступа к файлу и, если порождается исключение

    SecurityException
    , то в окне списка выводится строка "Permission denied accessing file" ("Полномочия не разрешают доступ к файлу"):

    // Код из SecurityАрр1

    private void button1_Click(object sender, System.EventArgs e) {

     try {

      StreamReader din = File.OpenText(@"C:\animals.txt");

      String str;

      while((str = din.ReadLine() != null) {

       listBox1.Items.Add(str);

      }

     } catch (SecurityException exception) {

      listBox1.Items.Add("Permission denied accessing file");

     }

    }

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

    Управление группами кода и полномочиями

    В управляемой безопасности .NET, если сборка отказывает с исключением безопасности, обычно имеются три пути продолжения работы:

    □ Смягчить политику полномочий

    □ Переместить сборку

    □ Применить для сборки строгое имя

    Принимая решения такого рода, нужно брать в расчет уровень надежности сборки.

    Включение и выключение системы безопасности

    По умолчанию система безопасности .NET обычно включена. Если по какой-то причине необходимо ее выключить, это делается таким образом:

    caspol.exe -security off

    Чтобы снова включить систему безопасности, используйте команду:

    caspol.exe -security on

    Риски безопасности, присущие открытию машины при отключении системы безопасности, для нас означают, что систему безопасности необходимо отключать только для тестирования и отладки. Необходимо знать, что приведенная выше команда не требует административных привилегий, т.е. любой пользователь (или вирус) может отключить систему безопасности .NET. Поэтому настоятельно рекомендуется включать систему безопасности Windows, чтобы защититься против злонамеренного или необдуманного использования.

    Восстановление политики системы безопасности

    Если необходимо восстановить конфигурацию системы безопасности в ее первоначальном состоянии, можно ввести команду:

    caspol.exe -reset

    Эта команда переводит политику системы безопасности в состояние установки по умолчанию.

    Создание группы кода

    Можно создавать свои собственные группы кода и затем применять к ним определенные полномочия. Например, мы определяем, что хотим доверять любому коду с web-сайта

    www.wrox.com
    и предоставляем ему полный доступ к системе (не доверяя коду с любого другого web-сайта). Прежде всего необходимо получить числовую метку группы кода, в которой будет находиться новая группа кода.

    caspol.exe -listgroups

    Эта команда выводит приблизительно:

    Code Groups:

    1. All code: Nothing

     1.1. Zone — MyComputer: FullTrust

     1.2. Zone — Intranet: LocalIntranet

      1.2.1. All code: Same site Socket and Web.

      1.2.2. All code: Same directory FileIO — Read, PathDiscovery

     1.3. Zone - Internet: Internet

      1.3.1. All code: Same site Socket and Web.

     1.4. Zone - Untrusted: Nothing

     1.5. Zone — Trusted: Internet

      1.5.1. All code: Same site Socket and Web.

    Используя тот факт, что

    Zone: Internet
    помечена как 1.3, вводим команду:

    caspol.exe -addgroup 1.3 -site www.wrox.com FullTrust

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

    caspol.exe -listgroups
    , можно увидеть, что была добавлена новая группа кода, которой присвоено
    FullTrust
    .

    Code Groups:

    1. All code: Nothing

     1.1. Zone - MyComputer: FullTrust

     1.2. Zone — Intranet: LocalIntranet

      1.2.1. All code: Same site Socket and Web.

      1.2.2. All code: Same directory FileIO - Read, PathDiscovery

     1.3. Zone — Internet: Internet

      1.3.1. All code: Same site Socket and Web.

      1.3.2. Site - www.wrox.com: FullTrust

     1.4. Zone — Untrusted: Nothing

     1.5. Zone - Trusted: Internet

      1.5.1. All code: Same site Socket and Web.

      1.5.2.

    В другом примере предположим, что мы хотим создать группу кода в группе кода

    Intranet (1.2)
    , которая предоставляет
    FullTrust
    всем приложениям, выполняющимся с определенного общего сетевого диска:

    caspol.exe -addgroup 1.2 -url file:///\\intranetserver/sharename/*FullTrust

    Удаление группы кода

    Чтобы удалить созданную группу кода, можно ввести команду:

    caspol.exe -remgroup 1.3.2

    Она будет запрашивать подтверждение того, что вы хотите изменить политику системы безопасности, и если ответить положительно, она сообщит, что группа удалена.

    Необходимо знать, что нельзя удалить группу кода

    All Code
    , но можно удалить группы кода на уровень ниже, включая группы для
    Internet
    ,
    MyComputer
    и
    LocalIntranet
    .

    Изменение полномочий группы кода

    Чтобы ослабить или ограничить полномочия, присвоенные группе кода, можно снова использовать

    caspol.exe
    . Предположим, что мы хотим применить
    FullTrust
    к зоне
    Intranet
    . В этом случае сначала мы должны получить метку, которая представляет группу кода
    Intranet
    :

    caspol.exe -listgroups

    Вывод показывает группу кода

    Intranet
    :

    Code Groups:

    1. All code: Nothing

     1.1 Zone - MyComputer: FullTrust

     1.2. Zone — Intranet: LocalIntranet

      1.2.1. All code: Same site Socket and Web.

      1.2.2. All code: Same directory FileIO - Read, PathDiscovery

     1.3. Zone - Internet: Internet

      1.3.1. All code: Same site Socket and Web.

     1.4. Zone — Untrusted: Nothing

     1.5. Zone — Trusted: Internet

      1.5.1. All code: Same site Socket and Web.

    После получения метки группы кода

    Intranet
    вводим вторую команду, чтобы изменить полномочия группы кода:

    caspol.exe -chggroup 1.2 FullTrust

    Команда будет запрашивать подтверждение изменения политики системы безопасности, и если теперь снова выполнить команду

    caspol.exe -listgroups
    , можно будет увидеть, что полномочие в конце строки
    Intranet
    изменилось на
    FullTrust
    :

    Code Groups:

    1. All code: Nothing

     1.1. Zone - MyComputer: FullTrust

     1.2. Zone - Intranet: FullTrust

      1.2.1. All code: Same site Socket and Web.

      1.2.2. All code: Same directory FileIO - Read, PathDiscovery

     1.3. Zone - Internet: Internet

      1.3.1. All code: Same site Socket and Web.

     1.4. Zone — Untrusted: Nothing

     1.5. Zone - Trusted: Internet

      1.5.1. All code: Same site Socket and Web.

    Создание и применение множеств полномочий

    Можно создавать новые множества полномочий с помощью команды:

    caspol.exe -addpset CustomPermissionSet permissionset.xml

    Эта команда определяет, что создается новое множество полномочий с именем

    CustomPermissionSet
    на основе содержимого указанного файла XML. Файл XML должен содержать стандартный формат, определяющий
    PermissionSet
    . Для справки здесь представлен файл множества полномочий для множества полномочий
    Everything
    , который можно сократить до требуемых размеров:

    <PermissionSet class="NamedPermissionSet" version="1" Name="Everything"

     Description="Allows unrestricted access to all resources covered by built in permissions">

     <IPermission class="EnvironmentРеrmission" version="1" Unrestricted="true" />

     <IPermission class="FileDialogPermission" version="1" Unrestricted="true" />

     <IPermission class="FileIOPermission" version="1" Unrestricted="true" />

     <IPermission class="IsolatedStorageFilePermission" version="1" Unrestricted="true" />

     <IPermission class="ReflectionPermission" version="1" Unrestricted="true" />

     <IPermission class="RegistryPermission" version="1" Unrestricted="true" />

     <IPermission class="SecurityPermission" version="1"

    Flags="Assertion, UnmanagedCode, Execution, ControlThread, ControlEvidence, ControlPolicy, SerializationFormatter, ControlDomainPolicy, ControlPrincipal, ControlAppDomain, RemotingConfiguration, Infrastructure" />

     <IPermission class="UIPermission" version="1" Unrestricted="true" />

     <IPermission class= "DnsPermission" version="1" Unrestricted="true" />

     <IPermission class="PrintingPermission" version="1" Unrestricted="true" />

     <IPermission class="EventLogPermission" version="1" Unrestricted="true" />

     <IPermission class="SocketPermission" version="1" Unrestricted="true" />

     <IPermission class="WebPermission" version="1" Unrestricted="true" />

     <IPermission class="PerformanceCounterPermission" version="1" "Unrestricted="true" />

     <IPermission class="DirectoryServicesPermission" version="1" Unrestricted="true" />

     <IPermission class="MessageQueuePermission" version="1" Unrestricted="true" />

     <IPermission class="ServiceControllerPermission" version="1" Unrestricted="true" />

    </PermissionSet>

    Чтобы увидеть все множества полномочий в формате XML, можно использовать команду:

    caspol.exe -listpset

    При желании применить конфигурационный файл PermissionSet XML к существующему множеству полномочий можно использовать команду:

    caspol.exe -chgpset permissionset.xml CustomPermissionSet

    Распространение кода с помощью строгого имени

    .NET предоставляет возможность сопоставить сборку с группой кода, когда идентичность и целостность сборки подтверждена с помощью строгого имени. Этот сценарий широко используется при распространении сборок через сети, например распространение программного обеспечения через Интернет.

    Если компания, производящая программное обеспечение, желает предоставить код своим заказчикам через Интернет, то создается сборка и для нее задается устойчивое имя. Устойчивое имя гарантирует, что сборка может быть идентифицирована уникальным образом, и также предоставляет защиту против подделки. Заказчики могут встроить это устойчивое имя в свою политику системы безопасности доступа к коду, а сборке, которая соответствует этому уникальному устойчивому имени, затем явно присвоить полномочия. Как мы видели в главе о сборках, устойчивое имя включает контрольные суммы для хэш-значений всех файлов в сборке, поэтому имеется строгое подтверждение, что сборка не была изменена с момента создания издателем устойчивого имени.

    Отметим, что, если приложение использует программу установки, то эта программа будет устанавливать сборки, для которых уже задано устойчивое имя. Устойчивое имя создается однажды для каждого дистрибутива перед отправкой заказчику, программа установки не выполняет такие команды. Причина заключается в том, что устойчивое имя предоставляет гарантию, что сборка не была модифицирована с момента отправки из компании. Обычный способ достичь этого состоит в предоставлении заказчику не только кода приложения, но также отдельно — копию устойчивого имени сборки. Может оказаться полезным передавать устойчивое имя заказчику с помощью защищенной формы (возможно, факс или зашифрованное сообщение e-mail), чтобы защитить сборку от подделки в пути.

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

    FullTrust
    .

    Прежде всего необходимо создать пару ключей, так как устойчивые имена используют криптографию с открытым ключом. Открытый и закрытый ключи хранятся в указанном файле и используются для подписи устойчивого имени. Чтобы создать два ключа, используется

    sn.exe
    (Strong Name Tool — утилита устойчивого имени), которая помимо помощи в создании ключей, может также использоваться для управления ключами и устойчивыми именами. Попробуем создать ключ, для чего введем команду:

    sn.exe -k key.snk

    Затем файл с ключами (

    key.snk
    в данном случае) поместим в ту же папку, где Visual Studio создает файл вывода (обычно папка Debug), а затем ключ добавим в код с помощью атрибута сборки. Когда этот атрибут добавлен в
    AssemblyInfo.cs
    , остается только заново скомплектовать сборку. Перекомпиляция обеспечивает, новое вычисление хэш-значения и сборка защищается против злонамеренных модификаций:

    [assembly: AssemblyKeyFileAttribute("key.snk")]

    Итак, наша сборка откомпилирована и подписана, она имеет уникальное идентифицирующее устойчивое имя. Теперь можно создать новую группу кода на машине, где мы хотим выполнить сборку. Эта группа имеет условие членства, которое требует соответствия с устойчивым именем сборки.

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

    FullTrust
    :

    caspol.exe -addgroup 1 -strong -file \bin\debug\SecurityApp10.exe -noname -noversion FullTrust

    Приложение в этом примере будет теперь выполняться из любой зоны, даже зоны

    Internet
    , так как устойчивое имя предоставляет достаточное свидетельство того, что сборка является надежной. Просмотрев группы кода с помощью
    caspol.exe -listgroups
    , увидим новую группу кода (1.8) и ее ассоциированный открытый ключ (в шестнадцатеричном представлении): 

    1. All code: Nothing

     1.1. Zone — MyComputer: FullTrust

     1.2. Zone — Intranet: LocalIntranet

      1.2.1. All code: Same site Socket and Web.

      1.2.2. All code: Same directory FileIO — Read, PathDiscovery

     1.3. Zone — Internet: Internet

      1.3.1. All code: Same site Socket and Web.

     1.4. Zone — Untrusted: Nothing

     1.5. Zone — Trusted: Internet

      1.5.1. All code: Same site Socket and Web.

     1.6. StrongName —

    02400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32

    E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723

    CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622

    CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293:

    FullTrust

     1.7. StrongName - 00000000000000000400000000000000: FullTrust

    1.8. StrongName -

    00240000048000009400000006020000002400005253413100040000010001007508D0780C56AF85BA

    1BAD6D88E2C653E0A836286682C18134CC989546C1143252795A791F042238040F5627CCC1590ECEA3

    0A9CD4780F5F0B29B55C375D916A33FD46B14582836E346A316BA27CD555B8F715377422EF589770E5

    A5346A00BAABB70EF36774DFBCB17A30B67C913384E62A1C762CF40AFE6F1F605CCF406ECF:

    FullTrust

    Success

    Для доступа к строгому имени в сборке можно применить утилиту

    secutil.exe
    с файлом манифеста сборки. Воспользуемся
    secutil.exe
    для просмотра данных устойчивого имени нашей сборки. Мы добавим параметр
    -hex
    , чтобы открытый ключ был показан в шестнадцатеричном представлении (как в
    caspol.exe
    ), и аргумент
    strongname
    , определяющий, что мы хотим увидеть строгое имя. Введите эту команду, и появится листинг, содержащий открытый ключ устойчивого имени, имя сборки и версию сборки.

    secutil.exe -hex -strongname securityapp10.exe

    Microsoft (R) .NET Framework SecUtil 1.0.xxxx.x

    Copyright (c) Microsoft Corp 1999-2001. All rights reserved.

    Public Key =

    0x002400000480000094000000060200000024000052534131000400000100010x7508D0780C56AF85BAl

    BAD6P88E2C653E0A836286682C18134CC988546C1143252795A791F042238040F5627CCC1590ECE

    A30A9CD4780F5F0B29B55C375D916A33FD46B14582836E346A316BA27CD555B8F715377422EF589770

    E5A5346AOOBAABB70EF36774DFBCB17A30B67C913384E62A1C762CF40AFE6F1F605CCF406ECF

    Name = SecurityApp10

    Version = 1.0.513.28751

    Success

    Можно заметить, что по умолчанию устанавливаются два строгих имени групп кода. Одно из них является ключом устойчивого имени кода Microsoft, а второй ключ устойчивого имени предназначен для частей .NET, представленных для стандартизации в ЕСМА, над которыми Microsoft имеет значительно меньший контроль.

    Распространение кода с помощью сертификатов

    В последнем разделе было рассмотрено, как можно применять уникальное устойчивое (строгое) имя к сборке, чтобы системный администратор мог явно предоставить сборкам полномочия, которые соответствуют этому устойчивому имени с помощью группы доступа к коду. Этот метод управления политикой системы безопасности может быть весьма эффективным, но иногда необходимо работать на более высоком уровне, где администратор политики системы безопасности предоставляет полномочия на основе издателя программного обеспечения, а не каждого отдельного программного компонента.

    Чтобы предоставить информацию об издателе программного обеспечения, мы используем цифровые сертификаты и подписываем сборки, чтобы потребители программного обеспечения могли проверить идентичность издателя программного обеспечения. В коммерческой среде мы получаем сертификаты от таких компаний как Verisign или Thawte.

    Преимущество покупки сертификата от внешнего поставщика перед созданием своего собственного состоит в том, что он предоставляет высокие уровни надежности в своей идентичности; поставщик действует как надежная третья сторона. Однако в целях тестирования .NET включает утилиту командной строки, которую можно использовать для создания тестового сертификата. Процесс создания сертификатов и их использование для публикации программного обеспечения является сложным, но чтобы дать представление о том, что сюда вовлечено, мы разберем пример, не вдаваясь в подробности.

    Представим, что мы являемся компанией ABC Corporation, и создадим сертификат для нашего программного продукта "ABC Suite". Прежде всего необходимо создать тестовый сертификат, для чего вводим команду:

    makecert -sk ABC -n "CN=ABC Corporation" abccorptest.cer

    Эта команда создает тестовый сертификат с именем "ABC Corporation" и сохраняет его в файле

    abccorptest.cer
    . Аргумент
    -sk
    ABC создает расположение контейнера ключа, который используется криптографией с открытым ключом.

    Чтобы подписать сборку с помощью сертификата, применяется утилита

    signcode.exe
    с файлом сборки, содержащим манифест сборки. Часто простейшим способом подписать сборку является использование утилиты
    signcode.exe
    в ее режиме мастера. Для запуска мастера введите
    signcode.exe
    без параметров:

    Если нажать кнопку Next, вам будет предложено определить, где находится файл, который надо подписать. Для сборки подписывается файл, содержащий манифест.

    Если нажать кнопку Next и выбрать режим Custom в следующем окне, будет предложено определить сертификат, который должен использоваться для подписи сборки. Нажав Select from File и указав файл

    abccorptest.cer
    , увидите экран подтверждения:

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

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

    Затем задается ряд вопросов о способе выполнения подписи, включая это окно, которое просит определить алгоритм шифрования:

    После этого мы определяем имя приложения и URL страницы Web, которая дает о нем дополнительную информацию.

    Это по сути окончание процесса, последнее окно подтверждает данные сертификата и тот факт, что сборка была успешно подписана.

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

    Разберем подписанную сборку более подробно. Хотя мы используем тестовый сертификат, можно временно сконфигурировать .NET для использования тестовых сертификатов как вызывающих доверие, выпущенных надежной третьей стороной, используя утилиту

    setreg.exe
    , которая позволяет преобразовать открытый ключ и настройки сертификата в реестре. Если ввести следующую команду, машина будет сконфигурирована таким образом, чтобы доверять тестовому сертификату в корне, что дает нам более содержательную тестовую среду.

    setreg.exe 1 true

    Проверим нашу сборку и ее уровень надежности с помощью утилиты

    chktrust.exe
    :

    chktrust.exe securityapp11.exe
     

    Эта команда выведет окно:

    Отметим, что

    chktrust.exe
    успешно подтвердила достоверность издателя программного обеспечения, используя сертификат, но напоминает, что, хотя сертификат был проверен, он является тестовым сертификатом.

    Обратим теперь наше внимание к машине, которую мы хотим сконфигурировать для надежного программного обеспечения ABC Corporation. Для этого можно создать новую группу доступа к коду, которая соответствует программному обеспечению ABC Corporation. Итак, мы извлекаем шестнадцатеричное представление сертификата из сборки с помощью утилиты

    secutil.exe
    :

    secutil.exe -hex -х securityapp11.exe

    Эта команда выведет что-то подобное:

    Microsoft (R) .NET Framework SecUtil 1.0.xxxx.x

    Copyright (c) Microsoft Corp 1999-2001. All rights reserved.


    X.509 Certificate =

    0x3082017B30820125A0030201020210D69BE8D88D8FF9B54A9C689A71BB7E33300D06092A864886F7

    0001010405003016311430120603550403130B526F6F74204167656E6379301E170D30313035323831

    38333133305A170D3339313233313233353935395A301A311830160603550403130F41424320436F72

    706F726174696F6E305C300D06092A864886F70D0101010500034B003048024100ECBEFB348C1364B0

    A3AE14FA9805F893AD180C7B2E57ADABBBE7EF94694A1E92BC5B4B59EF76FBDAC8D04D3DF2140B7616

    550FE2D5AE5F15E03CBB54932F5CBB0203010001A34B304930470603551D010440303E801012E4092D

    061D1D4F008D6121DC166463A1183016311430120603550403130B526F6F74204167656E6379821006

    376C00AA00648A11CFB8D4AA5C35F4300D06092A864886F70D010104050003410011D1B5F6FBB0C4C0E

    85A9BB5FDA5FEC1B8D9C229BB0FBBA7CBE3340A527A5B25EAA2A70205DD71571607291272DA581981C

    73028AB849FF273465FAEF2F4C7174


    Success

    Создадим новую группу кода и применим полномочие

    FullTrust
    к сборкам, опубликованным ABC Corporation, с помощью следующей команды (достаточно длинной):

    caspol -addgroup 1. -pub -hex

    3082017B30820125A0030201020210D69BE8D88D8FF9B54A9C689A71BB7E33300D06092A864886F70D

    01010405003016311430120603550403130B526F6F742041678656E6379301E170D3031303532383138

    333133305A170D3339313233313233353935395A301A311830160603550403130F41424320436F7270

    6F726174696F6E305C300D06092A864886F70D0101010500034B003048024100ECBEFB348C1364BOA3

    AE14FA9805F893AD180C7B2E57ADABBBE7EF94694A1E92BC5B4B59EF76FBDAC8D04D3DF2140B761655

    0FE2D5AE5F15E03CBB54932F5CBB0203010001A34B304930470603551D010440303E801012E4092D06

    1D1D4F008D6121DC166463A1183016311430120603550403130B526F6F74204167656E637982100637

    6C00AA00648A11CFB8D4AA5C35F4300D06092A86

    4886F70D01010405000341001D1B5F6FBB0C4C0E85A9BB5FDA5FEC1B8D9C229BB0FB8A7CBE3340A527

    A5B25EAA2A70205DD71571607291272D5A81981C73028AB849FF273465FAEF2F4C7174 FullTrust

    Параметры определяют, что группа кода должна добавляться к верхнему уровню (1.), условие членства в группе кода имеет тип

    Publisher
    , а последний параметр определяет множество полномочий для предоставления (
    FullTrust
    ). Команда будет требовать подтверждения:

    Microsoft (R) .NET Framework CasPol 1.0.xxxx.x

    Copyright (c) Microsoft Corp 1999-2001. All rights reserved.


    The operation you are performing will alter security policy.

    Are you sure you want to perform this operations? (yes/no) у

    Added union code group with "-pub" membership condition to the Machine level.

    Success

    Машина теперь сконфигурирована при наличии полного доверия всем сборкам, которые были подписаны с помощью сертификата ABC Corporation. Чтобы подтвердить это, выполним команду

    caspol.exe -lg
    , которая выводит новую группу доступа к коду (1.8):

    Security is ON

    Execution checking is ON

    Policy change prompt is ON


    Level = Machine


    Code Groups:

    1. All code: Nothing

     1.1. Zone - MyComputer: Full Trust

      1.1.1. Zone — Intranet: LocalIntranet

      1.2.1. All code: Same site Socket and Web.

      1.2.2. All code: Same directory FileIO - Read, PathDiscovery

     1.3. Zone — Internet: Internet

      1.3.1. All code: Same site Socket and Web.

     1.4. Zone — Untrusted: Nothing

     1.5. Zone — Trusted: Internet

      1.5.1. All code: Same site Socket and Web.

     1.6. StrongName - 0024000004800000940000000602000000240000525341310004000001

    000190007DlFA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5

    DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8

    F1645C4C0C93C1AB99285D622CAA652C1FAD63D745D6F2DF5F17E5EAF0FC4963D261C8A1143651820

    6DC093344D5AD293: FullTrust

     1.7. StrongName - 0000000000000000040000000000000: FullTrust

     1.8. Publisher -

    3048024100ECBEFB348C1364B0A3AE14FA9805F893AD180C7B2E57ADABBBE7EF94694A1E92BC5B4B59

    EF76FBDAC8D04D3DF2140B7616550FE2D5AE5F1 5E03CBB54932F5CBB0203010001: FullTrust

    Success

    В качестве еще одной проверки попросим

    caspol.exe
    сообщить, какие группы кода соответствуют нашей сборке:

    caspol.exe -resolvegroup securityapp11.exe


    Level = Enterprise

    Code Groups:

    1. All code: FullTrust


    Level = Machine

    Code Groups:

    1. All code: Nothing

     1.1. Zone — Intranet: LocalIntranet

      1.1.1. All code: Same site Socket and Web.

      1.1.2. All code: Same directory FileIO — Read, PathDiscovery

     1.2. Publisher - 3048024100ECBEFB348C1364B0A3AE14FA9805F893AD180C7B2E57ADABB

    BE7EF94694A1E92BC5B4B59EF76FBDAC8D04D3DF2140B7616550FE2D5AE5F15E03CBB54932F5CBB0

    203010001: FullTrust


    Level = User

    Code Groups:

    1. All code: FullTrust


    Success

    Результаты работы утилиты показывают, что сборка получает множество полномочий

    FullTrust
    при соответствии новой группе кода.

    Управление зонами

    Мы уже говорили о зонах, предоставляемых Windows, которыми мы управляем с помощью инструментов безопасности из Internet Explorer. Вот эти четыре зоны:

    □ 

    Intranet 
    — все сайты Web, которые не находятся в интранет текущей организации.

    □ 

    Trusted Sites
     — сайты Web, которые не способны разрушить данные пользователя.

    □ 

    Restricted Sites
    — сайты Web, которые потенциально могут повредить компьютер.

    □ 

    Internet
    — все сайты Web, не попавшие в другие зоны.

    Эти настройки управляются из Internet Explorer, так как они применимы к сайтам, посещаемым с помощью браузера, имеющего доступ к коду .NET (либо загруженному, либо в элементах управления страниц). Если используется другой браузер, он скорее всего не будет поддерживать код .NET и поэтому не будет параметров для управления ассоциированными зонами.

    Любой пользователь на машине может изменить настройки зон, однако, настройки системы безопасности для зон, которые они определяют, применимы только для его учетной записи, т. е. один пользователь не может изменить у другого пользователя настройки зон. Это говорит о существовании риска, что пользователь может изменить настройки зон, не понимая, что делает, и невольно открыть свою машину для атаки.

    Чтобы изменить настройки, связанные с каждой зоной, откройте Internet Explorer, а затем диалоговое окно Options из меню Tools. В окне Options перейдите на вкладку Security:

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

    LocalIntranet
    , воспользуйтесь следующим диалоговым окном.

    Присутствующие здесь параметры предоставляют достаточно возможностей, чтобы аккуратно определить, что составляет 'интранет' в организации пользователя. Кроме того, кнопка Advanced позволяет открыть диалоговое окно, где задается URI для сайтов, которые мы хотим включить в зону

    LocalIntranet
    .

    Отметим параметр в нижней части этого диалогового окна, который предоставляется для каждой из зон, за исключением зоны Internet. Он задает, что сайты в этой зоне будут считаться надежными, если соединение с ними происходит через защищенный HTTP с помощью шифрования Secure Sockets Layer(SSL). Если считать надежным сайт, который доступен через незашифрованное соединение, возникает потенциальный риск атаки, так как трафик может быть перехвачен. Если желательно проверить, находится ли сайт в определенной зоне, посетите сайт и посмотрите на нижний правый угол окна Internet Explorer, в котором будет выводиться имя зоны для текущего адреса Web.

    Помимо возможности найти область действия зоны, указывая надежные и ненадежные сайты, можно также определить, какие действия допускаются в каждой зоне с помощью настроек уровня безопасности. В их компетенции находятся такие вещи, как предупреждение об элементах управления ActiveX и разрешение принимать cookie.

    Заключение

    В этой главе мы рассмотрели, как сборки входят в группы кода, как этим группам кода присваивают полномочия на основе политики безопасности на уровнях пользователя, предприятия и машины, и как можно использовать утилиты для управления этой политикой. Мы также увидели, что для реализации сборки должны быть соответствующие полномочия на трех уровнях политики, а также правильные полномочия на основе ролей и соответствующие полномочия учетных записей Windows. Кроме того, здесь описаны имеющиеся возможности для распространения кода с помощью устойчивых имен и цифровых сертификатов.

    Легко видеть, что в .NET разработан более высокий уровень контроля безопасности, чем существовало раньше в Windows, при этом большая часть системы безопасности поставляется автоматически, так как не требуется никаких усилий, чтобы использовать ее на базовом уровне. И когда необходимо расширить ее, нам предоставляются классы и инфраструктуры.

    Безопасность постоянно находится в поле зрения Microsoft, и хотя компания пока не решила все проблемы, управляемая система безопасности .NET, является существенным шагом вперед, так как предоставляет среду, в которой код проверяется прежде, чем начинается его выполнение.

    Конечно, не случайно эти разработки происходят в то время, когда Microsoft все больше склоняется в сторону распространения своих продуктов через Web, так как безопасность при этом является существенным фактором.







     

    Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх