CA2114: 메서드 보안은 형식의 상위 집합이어야 합니다.

항목
RuleId CA2114
범주 Microsoft.Security
주요 변경 내용 주요 변경

원인

형식에 선언적 보안이 있고, 해당 메서드 중 하나에 동일한 보안 작업을 위한 선언적 보안이 있으며, 보안 작업이 링크 요청이 아니고, 형식으로 검사된 권한이 메서드로 검사된 권한의 하위 집합이 아닙니다.

참고 항목

이 규칙은 더 이상 사용되지 않습니다. 자세한 내용은 사용되지 않는 규칙을 참조하세요.

규칙 설명

메서드에 동일한 작업을 위한 메서드 수준의 선언적 보안과 형식 수준의 선언적 보안이 둘 다 있으면 안 됩니다. 두 검사는 결합되지 않고 메서드 수준의 요청만 적용됩니다. 예를 들어 형식이 X 권한을 요청하고 해당 메서드 중 하나가 Y 권한을 요청하는 경우 코드에 X 권한이 없어도 메서드를 실행할 수 있습니다.

위반 문제를 해결하는 방법

코드를 검토하여 두 작업이 모두 필요한지 확인합니다. 두 작업을 모두 필요한 경우 메서드 수준의 작업에 형식 수준에서 지정된 보안이 포함되어 있는지 확인합니다. 예를 들어 형식이 X 권한을 요청하고 해당 메서드도 Y 권한을 요청해야 하는 경우 메서드에서 XY를 명시적으로 요청해야 합니다.

경고를 표시하지 않는 경우

형식에서 지정된 보안이 메서드에 필요하지 않은 경우 이 규칙의 경고를 표시하지 않아도 됩니다. 그러나 일반적인 경우는 아니므로 신중하게 디자인을 검토해야 할 수 있습니다.

예 1

다음 예제에서는 환경 권한을 사용하여 이 규칙을 위반하는 경우의 위험을 보여 줍니다. 이 예제에서 애플리케이션 코드는 형식에 필요한 권한을 거부하기 전에 보안 형식의 인스턴스를 만듭니다. 실제 위협 시나리오에서는 애플리케이션이 개체 인스턴스를 얻을 수 있는 또 다른 방법이 필요합니다.

다음 예제에서 라이브러리는 형식에 대한 쓰기 권한과 메서드에 대한 읽기 권한을 요청합니다.

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"); 
      }
   }
}

예제 2

다음 애플리케이션 코드는 형식 수준의 보안 요구 사항을 충족하지 않는 경우에도 메서드를 호출하여 라이브러리의 취약성을 보여 줍니다.

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.

참고 항목