Безопасность метода должна быть подмножеством типа
Обновлен: Ноябрь 2007
TypeName |
MethodSecurityShouldBeASupersetOfType |
CheckId |
CA2114 |
Категория |
Microsoft.Security |
Критическое изменение |
Критическое |
Причина
Тип имеет декларативную безопасность, один из его методов имеет декларативную безопасность для такого же действия безопасности, причем действие безопасности отлично от Требования связывания и Требования наследования, а разрешения, проверяемые типом, не являются подмножеством разрешений, проверяемых методом.
Описание правила
Метод не должен иметь декларативную безопасность и на уровне метода, и на уровне типа для одного и того же действия. Эти две проверки не объединяются, применяется только запрос на уровне метода. Например, если тип запрашивает разрешение X и один из его методов запрашивает разрешение Y, код не должен иметь разрешение X для выполнения метода.
Устранение нарушений
Проверьте код и убедитесь, что оба действия необходимы. Если оба действия необходимы, то убедитесь, что действие на уровне метода включает безопасность, определенную на уровне типа. Например, если тип запрашивает разрешение X и его метод также должен запросить разрешение Y, метод должен явным образом запрашивать X и Y.
Отключение предупреждений
Можно безопасно отключать предупреждения этого правила, если для метода не требуется безопасность, указанная типом. Однако такие сценарии не являются общепринятыми; возможно, следует пересмотреть структуру программы.
Пример
В следующем примере показано применение разрешений среды для демонстрации опасности нарушения этого правила. В данном примере код приложения создает экземпляр безопасного типа перед отказом в разрешении, необходимом для этого типа. В обычном сценарии приложению потребуется другой способ получения экземпляра объекта.
В следующем примере библиотека запрашивает разрешение на запись для типа и разрешение на чтение для метода.
using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
namespace SecurityRulesLibrary
{
[EnvironmentPermissionAttribute(SecurityAction.Demand, Write="PersonalInfo")]
public class MyClassWithTypeSecurity
{
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
[return:MarshalAs(UnmanagedType.Bool)]
public static extern bool SetEnvironmentVariable(
string lpName,
string lpValue);
// Constructor.
public MyClassWithTypeSecurity(int year, int month, int day)
{
DateTime birthday = new DateTime(year, month, day);
// Write out PersonalInfo environment variable.
SetEnvironmentVariable("PersonalInfo",birthday.ToString());
}
[EnvironmentPermissionAttribute(SecurityAction.Demand, Read="PersonalInfo")]
public string PersonalInformation ()
{
// Read the variable.
return Environment.GetEnvironmentVariable("PersonalInfo");
}
}
}
В следующем фрагменте кода демонстрируется уязвимость библиотеки из-за вызова метода, несмотря на то, что он не соответствует требованиям по безопасности на уровне типа.
using System;
using System.Security;
using System.Security.Permissions;
using SecurityRulesLibrary;
namespace TestSecRulesLibrary
{
public class TestMethodLevelSecurity
{
MyClassWithTypeSecurity dataHolder;
void RetrievePersonalInformation(string description)
{
try
{
Console.WriteLine(
"{0} Personal information: {1}",
description, dataHolder.PersonalInformation());
}
catch (SecurityException e)
{
Console.WriteLine(
"{0} Could not access personal information: {1}",
description, e.Message);
}
}
[STAThread]
public static void Main()
{
TestMethodLevelSecurity me = new TestMethodLevelSecurity();
me.dataHolder = new MyClassWithTypeSecurity(1964,06,16);
// Local computer zone starts with all environment permissions.
me.RetrievePersonalInformation("[All permissions]");
// Deny the write permission required by the type.
EnvironmentPermission epw = new EnvironmentPermission(
EnvironmentPermissionAccess.Write,"PersonalInfo");
epw.Deny();
// Even though the type requires write permission,
// and you do not have it; you can get the data.
me.RetrievePersonalInformation(
"[No write permission (demanded by type)]");
// Reset the permissions and try to get
// data without read permission.
CodeAccessPermission.RevertAll();
// Deny the read permission required by the method.
EnvironmentPermission epr = new EnvironmentPermission(
EnvironmentPermissionAccess.Read,"PersonalInfo");
epr.Deny();
// The method requires read permission, and you
// do not have it; you cannot get the data.
me.RetrievePersonalInformation(
"[No read permission (demanded by method)]");
}
}
}
В результате выполнения примера получается следующий результат:
[All permissions] Personal information: 6/16/1964 12:00:00 AM
[No write permission (demanded by type)] Personal information: 6/16/1964 12:00:00 AM
[No read permission (demanded by method)] Could not access personal information: Request failed.