CA2118: SuppressUnmanagedCodeSecurityAttribute の使用法をレビューします

Item [値]
規則 ID CA2118
カテゴリ Microsoft.Security
互換性に影響する変更点 あり

原因

パブリックまたは保護されている型またはメンバーに System.Security.SuppressUnmanagedCodeSecurityAttribute 属性があります。

Note

このルールは非推奨とされました。 詳細については、「非推奨の規則」を参照してください。

規則の説明

COM 相互運用またはプラットフォーム呼び出しを使用しているアンマネージド コードを実行するメンバーの場合、SuppressUnmanagedCodeSecurityAttribute によって、既定のセキュリティ システムの動作が変化します。 一般に、システムでは、アンマネージド コードのアクセス許可についてデータとモデリングの作成を行います。 この要求は、実行時にメンバーが呼び出されるたびに発生し、アクセス許可があるか、呼び出し履歴内のすべての呼び出し元がチェックされます。 この属性が存在する場合は、システムにより、アクセス許可のリンク確認要求が作成されます。そして呼び出し元が JIT でコンパイルされるときに、直前の呼び出し元のアクセス許可がチェックされます。

この属性は、主にパフォーマンスを向上するために使用されますが、パフォーマンスが向上するとセキュリティ上のリスクも高くなります。 ネイティブ メソッドを呼び出すパブリック メンバーに対して属性を設定すると、呼び出し履歴内の呼び出し元 (直前の呼び出し元を除く) は、アンマネージド コードを実行するために、アンマネージド コードのアクセス許可を必要としません。 パブリック メンバーのアクションや入力処理によっては、信頼できない呼び出し元に、通常は信頼できるコードに制限されている機能へのアクセスが許可される可能性があります。

.NET では、呼び出し元が現在のプロセスのアドレス空間に直接アクセスできないようにするため、セキュリティ チェックに依存しています。 この属性により、通常のセキュリティがバイパスされるため、プロセスのメモリの読み取りや書き込みにコードを使用できる場合は、そのコードから深刻な脅威が生じます。 リスクは、プロセス メモリへのアクセスを意図的に提供するメソッドに限定されないことに注意してください。このリスクは、悪意のあるコードが、たとえば、予期しない入力、形式が正しくない入力、無効な入力を提供するなど、何らかの方法でアクセスを獲得できるどのシナリオにも存在します。

既定のセキュリティ ポリシーでは、アセンブリがローカル コンピューターから実行されているか、次のいずれかのグループのメンバーでない限り、アセンブリにアンマネージド コードのアクセス許可は付与されません。

  • マイ コンピューター ゾーン コード グループ

  • Microsoft の厳密な名前コード グループ

  • ECMA の厳密な名前コード グループ

違反の修正方法

コードを慎重にレビューして、この属性が絶対に必要であることを確認します。 マネージド コード セキュリティについて熟知していない場合や、この属性を使用した場合のセキュリティへの影響を理解していない場合は、コードから削除してください。 属性が必要な場合は、呼び出し元が悪意を持ってコードを使用できないようにする必要があります。 コードにアンマネージド コードを実行するためのアクセス許可がない場合、この属性は無効なので削除する必要があります。

どのようなときに警告を抑制するか

この規則による警告を安全に抑制するには、破壊的な方法で使用される可能性のあるネイティブの操作またはリソースへのアクセスを、コードで呼び出し元に提供しないようにする必要があります。

例 1

次の例は規則に違反しています。

using System.Security;

// These two classes are identical
// except for the location of the attribute.

namespace SecurityRulesLibrary
{
    public class MyBadMemberClass
   {
      [SuppressUnmanagedCodeSecurityAttribute()]
      public void DoWork()
      {
         FormatHardDisk();
      }

      void FormatHardDisk()
      {
         // Code that calls unmanaged code.
      }
   }

   [SuppressUnmanagedCodeSecurityAttribute()]
   public class MyBadTypeClass
   {
      public void DoWork()
      {
         FormatHardDisk();
      }

      void FormatHardDisk()
      {
         // Code that calls unmanaged code.
      }
   }
}

例 2

次の例では、DoWork メソッドによって、プラットフォーム呼び出しメソッド FormatHardDisk にパブリックにアクセスできるコード パスが提供されています。

using System.Security;
using System.Runtime.InteropServices;

namespace SecurityRulesLibrary
{
   public class SuppressIsOnPlatformInvoke
   {
      // The DoWork method is public and provides unsecured access
      // to the platform invoke method FormatHardDisk.
      [SuppressUnmanagedCodeSecurityAttribute()]
      [DllImport("native.dll")]

      private static extern void FormatHardDisk();
      public void DoWork()
      {
         FormatHardDisk();
      }
   }

   // Having the attribute on the type also violates the rule.
   [SuppressUnmanagedCodeSecurityAttribute()]
   public class SuppressIsOnType
   {
      [DllImport("native.dll")]

      private static extern void FormatHardDisk();
      public void DoWork()
      {
         FormatHardDisk();
      }
   }
}

例 3

次の例では、パブリック メソッド DoDangerousThing によって違反が発生します。 違反を解決するには、DoDangerousThing をプライベートにする必要があり、また、それに対するアクセスは、DoWork メソッドで示したように、セキュリティ要求によってセキュリティで保護されるパブリック メソッドを通して行う必要があります。

using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;

namespace SecurityRulesLibrary
{
   [SuppressUnmanagedCodeSecurityAttribute()]
   public class BadTypeWithPublicPInvokeAndSuppress
   {
      [DllImport("native.dll")]

      public static extern void DoDangerousThing();
      public void DoWork()
      {
         // Note that because DoDangerousThing is public, this 
         // security check does not resolve the violation.
         // This only checks callers that go through DoWork().
         SecurityPermission secPerm = new SecurityPermission(
            SecurityPermissionFlag.ControlPolicy | 
            SecurityPermissionFlag.ControlEvidence
         );
         secPerm.Demand();
         DoDangerousThing();
      }
   }
}

関連項目