次の方法で共有


リフレクションのセキュリティに関する考慮事項

リフレクションは、型とメンバーに関する情報を取得し、メンバーにアクセスする機能を提供します (つまり、メソッドとコンストラクターを呼び出す、プロパティ値を取得および設定する、イベント ハンドラーを追加および削除する、など)。 リフレクションを使用して型とメンバーに関する情報を取得することは制限されません。 すべてのコードでリフレクションを使用して、次のタスクを実行できます。

  • 型とメンバーを列挙し、そのメタデータを調べます。
  • アセンブリとモジュールを列挙して調べます。

これに対し、リフレクションを使用してメンバーにアクセスする場合は、制限が適用されます。 .NET Framework 4 以降では、セキュリティ クリティカルなメンバーにアクセスするためにリフレクションを使用できるのは信頼できるコードだけです。 さらに、リフレクションを使用して、コンパイル済みコードに直接アクセスできない非パブリック メンバーにアクセスできるのは、信頼されたコードだけです。 最後に、リフレクションを使用してセーフ クリティカルなメンバーにアクセスするコードは、コンパイル済みコードと同様に、セーフ クリティカル メンバーが要求するアクセス許可を持っている必要があります。

必要なアクセス許可に従って、コードはリフレクションを使用して次の種類のアクセスを実行できます。

  • セキュリティクリティカルではないパブリック メンバーにアクセスします。

  • コンパイル済みコードからアクセスできる非パブリック メンバーにアクセスします (それらのメンバーがセキュリティクリティカルでない場合)。 このような非パブリック メンバーの例を次に示します。

    • 呼び出し元コードの基底クラスの保護されたメンバー。 (リフレクションでは、これはファミリ レベルのアクセスと呼ばれます)。

    • internal 呼び出し元のコードのアセンブリ内のメンバー (Visual Basic のメンバーFriend )。 (リフレクションでは、これはアセンブリ レベルのアクセスと呼ばれます)。

    • 呼び出し元のコードを含むクラスの他のインスタンスのプライベート メンバー。

たとえば、セキュリティで保護されたアプリケーション ドメインで実行されるコードは、アプリケーション ドメインが追加のアクセス許可を付与しない限り、この一覧で説明されているアクセスに制限されます。

.NET Framework 2.0 Service Pack 1 以降では、通常アクセスできないメンバーにアクセスしようとすると、ターゲット オブジェクトの許可セットに対する要求と、ReflectionPermissionFlag.MemberAccess フラグを持つReflectionPermissionが生成されます。 完全信頼で実行されているコード (コマンド ラインから起動されるアプリケーション内のコードなど) は、常にこれらのアクセス許可を満たすことができます。 (これは、この記事で後述するように、セキュリティ クリティカルなメンバーへのアクセスに関する制限事項に従います)。

必要に応じて、サンドボックス アプリケーション ドメインは、この記事で後述する「通常アクセスできないメンバーへのアクセス」セクションで説明するように、ReflectionPermissionFlag.MemberAccess フラグを使用してReflectionPermissionを付与できます。

Security-Critical メンバーへのアクセス

メンバーが SecurityCriticalAttributeを持っている場合、 SecurityCriticalAttributeを持つ型に属している場合、またはセキュリティ クリティカルなアセンブリ内にある場合、メンバーはセキュリティ クリティカルです。 .NET Framework 4 以降、セキュリティ クリティカルなメンバーにアクセスするための規則は次のとおりです。

  • 透過的なコードでは、コードが完全に信頼されている場合でも、リフレクションを使用してセキュリティ クリティカルなメンバーにアクセスすることはできません。 MethodAccessExceptionFieldAccessException、またはTypeAccessExceptionがスローされます。

  • 部分信頼で実行されているコードは透過的として扱われます。

これらの規則は、セキュリティ クリティカルなメンバーがコンパイル済みコードによって直接アクセスされるか、リフレクションを使用してアクセスされるかに関係なく同じです。

コマンド ラインから実行されるアプリケーション コードは、完全信頼で実行されます。 透過的としてマークされていない限り、リフレクションを使用してセキュリティ クリティカルなメンバーにアクセスできます。 部分信頼 (たとえば、サンドボックス アプリケーション ドメイン内) で同じコードを実行すると、アセンブリの信頼レベルによって、セキュリティ クリティカルなコードにアクセスできるかどうかが決まります。アセンブリに厳密な名前があり、グローバル アセンブリ キャッシュにインストールされている場合、アセンブリは信頼できるアセンブリであり、セキュリティ クリティカルなメンバーを呼び出すことができます。 信頼されていない場合は、透過的としてマークされていなくても透過的になり、セキュリティ クリティカルなメンバーにアクセスできません。

反射と透明度

.NET Framework 4 以降、共通言語ランタイムは、アセンブリの信頼レベルやアプリケーション ドメインの信頼レベルなど、いくつかの要因から型またはメンバーの透過性レベルを決定します。 リフレクションには、 IsSecurityCriticalIsSecuritySafeCritical、および IsSecurityTransparent のプロパティが用意されており、型の透過性レベルを検出できます。 次の表に、これらのプロパティの有効な組み合わせを示します。

セキュリティ レベル IsSecurityCritical IsSecuritySafeCritical IsSecurityTransparent
危うい true false false
セーフ クリティカル true true false
透明 false false true

これらのプロパティの使用は、アセンブリとその型のセキュリティ注釈を調べたり、現在の信頼レベルを確認したり、ランタイムの規則を複製したりするよりもはるかに簡単です。 たとえば、コマンド ラインから実行する場合は同じ型をセキュリティクリティカルにしたり、セキュリティで保護されたアプリケーション ドメインで実行する場合はセキュリティ透過的にすることができます。

MethodBaseFieldInfoTypeBuilderMethodBuilderDynamicMethod クラスにも同様のプロパティがあります。 (その他のリフレクションおよびリフレクション出力の抽象化の場合、セキュリティ属性は関連付けられているメソッドに適用されます。たとえば、プロパティの場合は、プロパティ アクセサーに適用されます)。

通常アクセスできないメンバーへのアクセス

リフレクションを使用して、共通言語ランタイムのアクセシビリティ規則に従ってアクセスできないメンバーを呼び出すには、次の 2 つのアクセス許可のいずれかをコードに付与する必要があります。

  • コードがパブリックでないメンバーを呼び出せるようにするには、コードに ReflectionPermissionFlag.MemberAccess フラグを付けてReflectionPermissionを付与する必要があります。

    既定では、セキュリティ ポリシーは、インターネットから送信されたコードに対するこのアクセス許可を拒否します。 このアクセス許可は、インターネットから生成されたコードに付与しないでください。

  • 呼び出されたメンバーを含むアセンブリの許可セットが呼び出し元のコードを含むアセンブリの許可セットと同じか、またはそのサブセットである限り、コードが非パブリック メンバーを呼び出せるようにするには、呼び出し元のコードを含むアセンブリの許可セットを指定する必要があります。コードには、ReflectionPermissionFlag.RestrictedMemberAccess フラグを使用してReflectionPermissionを付与する必要があります。

たとえば、アプリケーション ドメインのインターネットアクセス許可に加えて、ReflectionPermissionFlag.RestrictedMemberAccess フラグを持つReflectionPermissionを付与し、A と B の 2 つのアセンブリを使用してインターネット アプリケーションを実行するとします。

  • アセンブリ B の許可セットには、A に付与されていない権限が含まれていないため、アセンブリ A はリフレクションを使用してアセンブリ B のプライベート メンバーにアクセスできます。

  • アセンブリ A は、mscorlib.dllなどの .NET Framework アセンブリのプライベート メンバーにアクセスするためにリフレクションを使用できません。mscorlib.dll は完全に信頼されているため、アセンブリ A に付与されていないアクセス許可を持っています。コード アクセス セキュリティが実行時にスタックをウォークすると、 MemberAccessException がスローされます。

シリアル化

シリアル化の場合、SecurityPermissionAttribute.SerializationFormatter フラグを使用してSecurityPermissionすると、アクセシビリティに関係なく、シリアル化可能な型のメンバーを取得および設定できます。 このアクセス許可により、コードはインスタンスのプライベート状態を検出して変更できます。 (適切なアクセス許可が付与されるだけでなく、型はメタデータでシリアル化可能として マーク されている必要があります)。

MethodInfo 型のパラメーター

特に信頼できるコードの場合は、 MethodInfo パラメーターを受け取るパブリック メンバーを記述しないでください。 このようなメンバーは、悪意のあるコードに対して脆弱になる可能性があります。 たとえば、 MethodInfo パラメーターを受け取る高信頼コードのパブリック メンバーについて考えてみます。 パブリック メンバーが、指定されたパラメーターに対して Invoke メソッドを間接的に呼び出しているとします。 パブリック メンバーが必要なアクセス許可チェックを実行しない場合、セキュリティ システムは呼び出し元が高信頼であると判断するため、 Invoke メソッドの呼び出しは常に成功します。 悪意のあるコードにメソッドを直接呼び出すアクセス許可がない場合でも、パブリック メンバーを呼び出すことによって間接的に行うことができます。

バージョン情報

  • .NET Framework 4 以降では、透過的なコードではリフレクションを使用してセキュリティ クリティカルなメンバーにアクセスすることはできません。

  • ReflectionPermissionFlag.RestrictedMemberAccess フラグは、.NET Framework 2.0 Service Pack 1 で導入されています。 以前のバージョンの .NET Framework では、リフレクションを使用して非パブリック メンバーにアクセスするコードに ReflectionPermissionFlag.MemberAccess フラグが必要です。 これは、部分的に信頼されたコードに付与すべきでないアクセス許可です。

  • .NET Framework 2.0 以降では、リフレクションを使用して非パブリック型とメンバーに関する情報を取得する場合、アクセス許可は必要ありません。 以前のバージョンでは、ReflectionPermissionFlag.TypeInformation フラグを使用したReflectionPermissionが必要です。

こちらも参照ください