Управление доступом для кода и ADO.NET

Обновлен: November 2007

Платформа .NET Framework предлагает безопасность на основе ролей, а также управление доступом для кода (CAS). Оба средства реализуются при помощи общей инфраструктуры, предоставленной средой CLR. В области неуправляемого кода большинство приложений выполняются с правами доступа пользователя или участника. В результате, когда вредоносное программное обеспечение или программы с ошибками запускаются пользователем с повышенными правами доступа, компьютерные системы могут повреждаться, а личные данные — похищаться.

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

Права доступа для кода

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

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

0x4t63kb.alert_note(ru-ru,VS.90).gifПримечание.

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

Существует три типа прав доступа для кода.

  • Code access permissions получаются из класса CodeAccessPermission. Права доступа требуются для использования защищенных ресурсов, например файлов и переменных среды, а также для выполнения защищенных операций, например для доступа к неуправляемому коду.

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

  • Role-based security permissions основаны на том, имеет ли участник указанное свидетельство или является ли членом указанной роли. Класс PrincipalPermission позволяет проводить декларативные и императивные проверки прав доступа по активному участнику.

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

Запрос прав доступа

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

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

Безопасность на основе ролей и CAS

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

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

В среде CLR для реализации своего механизма применения ограничений для управляемого кода используются права доступа. Права доступа на основе ролей предоставляют механизм для определения, имеет ли пользователь (или агент, действующий от имени пользователя) конкретное удостоверение или является ли он членом указанной роли. Дополнительные сведения см. в разделе Разрешения безопасности.

В зависимости от типа создаваемого приложения также следует рассмотреть возможность реализации в базе данных прав доступа на основе ролей. Дополнительные сведения о безопасности на основе ролей в SQL Server см. в разделе Безопасность SQL Server (ADO.NET).

Сборки

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

Назначение строгих имен сборкам

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

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

Частичный уровень доверия в ADO.NET 2.0

Теперь в ADO.NET 2.0 поставщик данных .NET Framework для SQL Server, поставщик данных .NET Framework для OLE DB, поставщик данных .NET Framework для ODBC и поставщик данных .NET Framework для Oracle могут работать в частично доверенных средах. В предыдущих версиях платформы .NET Framework в приложениях с неполным доверием поддерживался только клиент System.Data.SqlClient.

У частично доверенного приложения, использующего поставщик the SQL Server, как минимум, должно быть право доступа для выполнения и право доступа SqlClientPermission.

Свойства атрибута разрешения для частичного уровня доверия

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

0x4t63kb.alert_note(ru-ru,VS.90).gifПримечание.

Поставщику данных .NET Framework для SQL Server, чтобы открывать соединение SqlConnection с SQL Debugging, требуется, чтобы в SQL Server 2000 ему было предоставлено право доступа Full Trust Security. В SQL Debugging для SQL Server 2005 этот класс не используется. Подробные сведения см. в электронной документации по SQL Server 2005.

В следующей таблице содержится список имеющихся свойств SqlClientPermissionAttribute и их описания.

Свойство атрибута разрешения

Описание

Action

Возвращает или задает действие по обеспечению безопасности. Наследуется от SecurityAttribute.

AllowBlankPassword

Разрешает или запрещает использование пустого пароля в строке соединения. Допустимые значения — true (чтобы разрешить использование пустых паролей) и false (чтобы запретить использование пустых паролей). Наследуется от DBDataPermissionAttribute.

ConnectionString

Определяет допустимую строку соединения. Можно определить несколько строк соединения.

0x4t63kb.alert_note(ru-ru,VS.90).gifПримечание.
Не включайте в строку соединения идентификатор пользователя или пароль. В этой версии изменение ограничений строки соединения при помощи средства настройки .NET Framework невозможно.

Наследуется от DBDataPermissionAttribute.

KeyRestrictions

Определяет допустимые или недопустимые параметры строки соединения. Параметры строки соединения определяются в виде <имя параметра>=. Можно указать несколько параметров, разделив их точкой с запятой (;).

0x4t63kb.alert_note(ru-ru,VS.90).gifПримечание.
Если не указать KeyRestrictions и задать свойству KeyRestrictionBehavior значение AllowOnly или PreventUsage, то другие параметры строки соединения будут недопустимы. Наследуется от DBDataPermissionAttribute.

KeyRestrictionBehavior

Определяет единственно допустимые дополнительные параметры строки соединения (AllowOnly) или определяет недопустимые дополнительные параметры (PreventUsage). Значение по умолчанию — AllowOnly. Наследуется от DBDataPermissionAttribute.

TypeID

Возвращает уникальный идентификатор для этого атрибута при реализации в производном классе. Наследуется от Attribute.

Unrestricted

Указывает, объявлено ли неограниченное право доступа к ресурсу. Наследуется от SecurityAttribute.

Синтаксис ConnectionString

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

<connectionStrings>
  <add name="DatabaseConnection" 
    connectionString="Data Source=(local);Initial 
    Catalog=Northwind;Integrated Security=true;" />
</connectionStrings>

Синтаксис KeyRestrictions

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

<connectionStrings>
  <add name="DatabaseConnection" 
    connectionString="Data Source=(local);Initial 
    Catalog=Northwind;Integrated Security=true;"
    KeyRestrictions="Encrypt=;Packet Size=;"
    KeyRestrictionBehavior="AllowOnly" />
</connectionStrings>

Синтаксис KeyRestrictionBehavior с PreventUsage

В следующем примере включается та же строка соединения и разрешается использование всех остальных параметров строки соединения, за исключением User Id, Password и Persist Security Info.

<connectionStrings>
  <add name="DatabaseConnection" 
    connectionString="Data Source=(local);Initial 
    Catalog=Northwind;Integrated Security=true;"
    KeyRestrictions="User Id=;Password=;Persist Security Info=;"
    KeyRestrictionBehavior="PreventUsage" />
</connectionStrings>

Синтаксис KeyRestrictionBehavior с AllowOnly

В следующем примере включаются две строки соединения, которые также содержат параметры Initial Catalog, Connection Timeout, Encrypt и Packet Size. Использование всех остальных параметров строки соединения запрещено.

<connectionStrings>
  <add name="DatabaseConnection" 
    connectionString="Data Source=(local);Initial 
    Catalog=Northwind;Integrated Security=true;"
    KeyRestrictions="Initial Catalog;Connection Timeout=;
       Encrypt=;Packet Size=;" 
    KeyRestrictionBehavior="AllowOnly" />

  <add name="DatabaseConnection2" 
    connectionString="Data Source=SqlServer2;Initial 
    Catalog=Northwind2;Integrated Security=true;"
    KeyRestrictions="Initial Catalog;Connection Timeout=;
       Encrypt=;Packet Size=;" 
    KeyRestrictionBehavior="AllowOnly" />
</connectionStrings>

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

Чтобы включить использование прав доступа System.Data.SqlClient для определенной зоны, системный администратор должен создать пользовательский набор прав доступа и задать его в качестве набора прав доступа для конкретной зоны. Наборы прав доступа по умолчанию, например LocalIntranet, изменять нельзя. Например, чтобы включить права доступа System.Data.SqlClient для кода, имеющего зону Zone, равную LocalIntranet, системный администратор может скопировать набор прав доступа для LocalIntranet, переименовать его в «CustomLocalIntranet», добавить права доступа System.Data.SqlClient, импортировать набор прав доступа с помощью Средство настройки политики управления доступом для кода (Caspol.exe) и установить CustomLocalIntranet в качестве набора прав доступа для зоны LocalIntranet_Zone.

Образец набора прав доступа

Далее приведен образец набора прав доступа для поставщика данных .NET Framework для SQL Server в частично доверенном сценарии. Сведения о создании пользовательских наборов прав доступа см. в разделе Настройка наборов разрешений с помощью Caspol.exe.

<PermissionSet class="System.Security.NamedPermissionSet"
  version="1"
  Name="CustomLocalIntranet"
  Description="Custom permission set given to applications on
    the local intranet">

<IPermission class="System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
AllowBlankPassword="False">
<add ConnectionString="Data Source=(local);Integrated Security=true;"
 KeyRestrictions="Initial Catalog=;Connection Timeout=;
   Encrypt=;Packet Size=;" 
 KeyRestrictionBehavior="AllowOnly" />
 </IPermission>
</PermissionSet>

Проверка доступа к коду ADO.NET при помощи прав доступа Security Permissions

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

Пример

В следующем примере демонстрируется, как написать код, в котором требуется определенная строка соединения. В нем имитируется запрет на неограниченные права доступа для System.Data.SqlClient, который в реальной среде реализуется системным администратором при помощи политики CAS.

0x4t63kb.alert_security(ru-ru,VS.90).gifПримечание о безопасности.

При разработке прав доступа CAS для ADO.NET рекомендуется начинать с наиболее жестких ограничений (полное отсутствие прав доступа), а затем добавлять определенные права доступа, необходимые конкретной задаче, которую требуется выполнить коду. Противоположный подход, когда начинают с предоставления всех прав доступа, а затем удаляют определенные права, не является безопасным, поскольку существует много способов выражения одинаковой строки соединения. Например, если начать с предоставления всех прав доступа, а затем попытаться запретить использование строки соединения «server=someserver», то строка «server=someserver.mycompany.com» останется допустимой. Начиная с отсутствия предоставленных прав, можно сократить вероятность появления уязвимостей, связанных с набором прав доступа.

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

Private Sub TestCAS(ByVal connectString1 As String, ByVal connectString2 As String)
    ' Simulate removing SqlClient permissions.
    Dim permission As New SqlClientPermission(PermissionState.Unrestricted)
    permission.Deny()

    ' Try to open a connection.
    Try
        Using connection As New SqlConnection(connectString1)
            connection.Open()
            Console.WriteLine("Connection opened, unexpected.")
        End Using

    Catch ex As System.Security.SecurityException
        Console.WriteLine("Failed, as expected: {0}", _
            ex.FirstPermissionThatFailed)

        ' Uncomment the following line to see Exception details.
        ' Console.WriteLine("BaseException: {0}", ex.GetBaseException())
    End Try

    SqlClientPermission.RevertAll()

    ' Add permission for a specific connection string.
    ' This would typically be achieved by the administrator  
    ' deploying a CAS policy, not in your code.
    permission = New SqlClientPermission(PermissionState.None)
    permission.Add(connectString1, "", KeyRestrictionBehavior.AllowOnly)

    permission.PermitOnly()

    ' Try again, it should succeed now.
    Try
        Using connection As New SqlConnection(connectString1)
            connection.Open()
            Console.WriteLine("Connection opened, as expected.")
        End Using

    Catch ex As System.Security.SecurityException
        Console.WriteLine("Unexpected failure: {0}", ex.Message)
    End Try

    ' Try a different connection string. This should fail.
    Try
        Using connection As New SqlConnection(connectString2)
            connection.Open()
            Console.WriteLine("Connection opened, unexpected.")
        End Using

    Catch ex As System.Security.SecurityException
        Console.WriteLine("Failed, as expected: {0}", ex.Message)
    End Try
End Sub
static void TestCAS(string connectString1, string connectString2)
{
    // Simulate removing SqlClient permissions.
    SqlClientPermission permission = new 
        SqlClientPermission(PermissionState.Unrestricted);
    permission.Deny();

    // Try to open a connection.
    try
    {
        using (SqlConnection connection = new 
                   SqlConnection(connectString1))
        {
            connection.Open();
            Console.WriteLine("Connection opened, unexpected.");
        }
    }
    catch (System.Security.SecurityException ex)
    {
        Console.WriteLine("Failed, as expected: {0}", 
            ex.FirstPermissionThatFailed);

        // Uncomment the following line to see Exception details.
        //Console.WriteLine("BaseException: " + ex.GetBaseException());
    }

    SqlClientPermission.RevertAll();

    // Add permission for a specific connection string.
    // This would typically be achieved by the administrator deploying 
    // a CAS policy, not in your code.
    permission = new SqlClientPermission(PermissionState.None);
    permission.Add(connectString1,"", KeyRestrictionBehavior.AllowOnly);

    permission.PermitOnly();

    // Try again, it should succeed now.
    try
    {
        using (SqlConnection connection = new SqlConnection(connectString1))
        {
            connection.Open();
        }
        Console.WriteLine("Connection opened, as expected.");
    }
    catch (System.Security.SecurityException ex)
    {
        Console.WriteLine("Unexpected failure: {0}", ex.Message);
    }

    // Try a different connection string. This should fail.
    try
    {
        using (SqlConnection connection = new SqlConnection(connectString2))
        {
            connection.Open();
        }
        Console.WriteLine("Connection opened, unexpected.");
    }
    catch (System.Security.SecurityException ex)
    {
        Console.WriteLine("Failed, as expected: {0}", ex.Message);
    }
}

Вот что должно отобразиться в консольном окне:

Failed, as expected: <IPermission class="System.Data.SqlClient.
SqlClientPermission, System.Data, Version=2.0.0.0, 
  Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1"
  AllowBlankPassword="False">
<add ConnectionString="Data Source=(local);Initial Catalog=
  Northwind;Integrated Security=SSPI" KeyRestrictions=""
KeyRestrictionBehavior="AllowOnly"/>
</IPermission>

Connection opened, as expected.
Failed, as expected: Request failed.

Совместимость с неуправляемым кодом

Код, который выполняется вне среды CLR, называется неуправляемым. Поэтому применять к неуправляемому коду такие механизмы безопасности, как CAS, нельзя. Примерами неуправляемого кода являются компоненты COM, интерфейсы ActiveX и функции Win32 API. При выполнении неуправляемого кода возникают особые вопросы безопасности, с тем чтобы не подвергать риску общую безопасность приложения. Дополнительные сведения см. в разделе Взаимодействие с неуправляемым кодом.

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

См. также

Другие ресурсы

Защита приложений ADO.NET

Безопасность в машинном коде и коде .NET Framework

Управление доступом для кода

Безопасность на основе ролей