リフレクション出力のセキュリティ関連事項

.NET Framework には、Microsoft Intermediate Language (MSIL) を出力する方法が 3 種類ありますが、それぞれに固有のセキュリティ問題があります。

  • 動的アセンブリ

  • 匿名でホストされる動的メソッド

  • 既存のアセンブリに関連付けられた動的メソッド

動的コードの生成方法に関係なく、生成済みコードを実行するには、生成済みコードで使用される型やメソッドに必要なすべてのアクセス許可が必要です。

メモメモ

コードでのリフレクションとコードの出力に必要なアクセス許可は、.NET Framework のバージョンによって異なります。このトピックの「バージョン情報」を参照してください。

動的アセンブリ

動的アセンブリを作成するには、AppDomain.DefineDynamicAssembly メソッドのオーバーロードを使用します。 コンピューター全体のセキュリティ ポリシーが削除されたため、このメソッドのほとんどのオーバーロードは .NET Framework Version 4 では使用されていません。 (「.NET Framework 4 におけるセキュリティの変更点」を参照)。残りのオーバーロードは、信頼レベルに関係なく、任意のコードによって実行できます。 これらのオーバーロードは 2 つのグループに分けられます。1 つは、動的アセンブリの作成時に適用する属性の一覧を指定するグループで、もう 1 つは属性の一覧を指定しないグループです。 アセンブリの透過性モデルを指定しない場合は、アセンブリの作成時に SecurityRulesAttribute 属性を適用することによって、出力アセンブリから透過性モデルが継承されます。

メモメモ

SetCustomAttribute メソッドを使用すると、動的アセンブリの作成後に適用する属性は、そのアセンブリがディスクに保存され、メモリに再び読み込まれるまでは有効になりません。

動的アセンブリのコードからは、参照できる型と他のアセンブリのメンバーのみにアクセスできます。

メモメモ

動的アセンブリでは、動的メソッドが非パブリックな型とメンバーにアクセスすることを許可する ReflectionPermissionFlag.MemberAccess フラグと ReflectionPermissionFlag.RestrictedMemberAccess フラグが使用されません。

一時動的アセンブリはメモリ内に作成され、ディスクに保存されることがないため、ファイルへのアクセス許可は不要です。 動的アセンブリをディスクに保存するには、FileIOPermission に適切なフラグを指定する必要があります。

部分信頼コードからの動的アセンブリの生成

インターネット アクセス許可が設定されたアセンブリで一時動的アセンブリを生成し、そのコードを実行するための条件を考えてみましょう。

  • 動的アセンブリで使用されるのが、パブリック型と他のアセンブリのメンバーのみである。

  • その型およびメンバーで必要なアクセス許可が、部分信頼のアセンブリの許可セットに含まれている。

  • アセンブリがディスクに保存されていない。

  • デバッグ シンボルが生成されていない (Internet および LocalIntranet のアクセス許可セットに必要なアクセス許可が指定されていない)。

匿名でホストされる動的メソッド

関連付けられる型やモジュールを指定しない 2 つの DynamicMethod コンストラクター (DynamicMethod(String, Type, Type[]) および DynamicMethod(String, Type, Type[], Boolean)) を使用して、匿名でホストされる動的メソッドを作成します。 このコンストラクターにより、システムで指定された完全に信頼される透過的セキュリティ アセンブリに動的メソッドが置かれます。 このコンストラクターの使用や動的メソッドのコード出力のために、特別なアクセス許可は必要ありません。

ただし、匿名でホストされる動的メソッドが作成されるとき、コール スタックがキャプチャされます。 メソッドの作成時に、キャプチャされたコール スタックに対してセキュリティ要求が行われます。

メモメモ

概念的には、メソッドの作成中に要求が行われます。つまり、MSIL 命令が生成されるたびに要求を実行できます。現在の実装では、DynamicMethod.CreateDelegate メソッドが呼び出されたとき (CreateDelegate を呼び出さずにこのメソッドが呼び出される場合)、または Just-In-Time (JIT) コンパイラが呼び出されたときに、すべての要求が行われます。

アプリケーション ドメインで許可されている場合、匿名でホストされる動的メソッドでは、JIT の参照範囲チェックを省略できますが、制限があります。匿名でホストされる動的メソッドによりアクセスされる非パブリックの型とメンバーがアセンブリに含まれ、そのアセンブリの許可セットが、出力元のコール スタックの許可セットに等しいか、または、そのサブセットであることが必要です。 アプリケーション ドメインで ReflectionPermissionReflectionPermissionFlag.RestrictedMemberAccess フラグが指定されている場合は、この制限付き機能を使って JIT 参照範囲チェックを省略できます。

  • メソッドでパブリックな型とメンバーのみを使用する場合は、作成中にアクセス許可は不要です。

  • JIT 参照範囲チェックを省略するように指定した場合、メソッドの作成時に行われる要求には ReflectionPermissionFlag.RestrictedMemberAccess フラグが指定された ReflectionPermission と、アクセスされる非パブリック メンバーを含むアセンブリの許可セットが含まれます。

非パブリック メンバーの許可セットが考慮されるため、ReflectionPermissionFlag.RestrictedMemberAccess によって許可された部分信頼コードでは、信頼されるアセンブリの非パブリック メンバーを実行しても特権を昇格することができません。

通常の出力済みコードと同様に、動的メソッドを実行するには、動的メソッドで使用されるメソッドで必要なアクセス許可がすべて必要になります。

匿名でホストされる動的メソッドをホストするシステム アセンブリでは、SecurityRuleSet.Level1 透過性モデルを使用します。これは、.NET Framework 4 より前の .NET Framework で使用されていた透過性モデルです。

詳細については、DynamicMethod クラスを参照してください。

部分的に信頼されるコードによる匿名でホストされる動的メソッドの生成

インターネット アクセス許可が設定されたアセンブリで、匿名でホストされる動的メソッドを生成し、それを実行するための条件を考えてみましょう。

  • 動的メソッドで使用されるのが、パブリックな型とメンバーのみである。 許可セットに ReflectionPermissionFlag.RestrictedMemberAccess が含まれる場合、使用できる非パブリックの型とメンバーの許可セットは、出力元アセンブリの許可セットと同じか、またはそのサブセットになります。

  • 動的メソッドで使用されるすべての型およびメンバーで必要なアクセス許可が、部分信頼のアセンブリの許可セットに含まれている。

メモメモ

動的メソッドではデバッグ シンボルがサポートされていません。

既存のアセンブリに関連付けられた動的メソッド

動的メソッドに既存アセンブリの型またはモジュールを関連付けるには、関連付ける型またはモジュールを指定する DynamicMethod コンストラクターのどれかを使用します。 動的メソッドに既存の型またはモジュールを関連付けると、動的メソッドが非パブリックの型とメンバーにアクセスできるようになるため、これらのコンストラクターを呼び出すにはアクセス許可が必要です。

  • 型に関連付けられる動的メソッドは、その型のすべてのメンバー (プライベート メンバーを含む) にアクセスでき、関連付けられた型が含まれるアセンブリ内部のすべての型およびメンバーにアクセスできます。

  • モジュールに関連付けられる動的メソッドは、モジュールのすべての internal 型およびメンバー (Visual Basic では Friend、共通言語ランタイムのメタデータでは assembly) にアクセスできます。

さらに、JIT コンパイラの参照範囲チェックを省略する機能を指定するコンストラクターを使用できます。 これを使用した場合、アクセス レベルに関係なく、動的メソッドからすべてのアセンブリのすべての型およびメンバーにアクセスできます。

コンストラクターで必要なアクセス許可は、動的メソッドに与えるアクセス許可のレベルに応じて決まります。

この一覧の項目は出力アセンブリの許可セットの観点から書かれていますが、要求はコール スタック全体 (アプリケーション ドメイン境界を含む) に対して行われることに注意してください。

詳細については、DynamicMethod クラスを参照してください。

部分信頼コードからの動的メソッドの生成

メモメモ

部分的に信頼されるコードから動的メソッドを生成する方法として推奨されるのは、匿名でホストされる動的メソッドを使用する方法です。

インターネット アクセス許可が設定されたアセンブリで、動的メソッドを生成し、それを実行するための条件を考えてみましょう。

  • 動的メソッドにそれを出力するモジュールまたは型が関連付けられているか、その許可セットに ReflectionPermissionFlag.RestrictedMemberAccess が含まれている。さらに、関連付けられているモジュールが含まれているアセンブリの許可セットが出力アセンブリの許可セットと等しいか、そのサブセットである。

  • 動的メソッドで使用されるのが、パブリックな型とメンバーのみである。 許可セットに ReflectionPermissionFlag.RestrictedMemberAccess が含まれ、関連付けられているモジュールが含まれているアセンブリの許可セットが出力アセンブリの許可セットと等しいか、そのサブセットである場合、internal と指定されている (Visual Basic では Friend、共通言語ランタイム メタデータでは assembly) 型とメンバーを使用できます。

  • 動的メソッドで使用されるすべての型およびメンバーで必要なアクセス許可が、部分信頼のアセンブリの許可セットに含まれている。

  • 動的メソッドで JIT 参照範囲チェックを省略しない。

メモメモ

動的メソッドではデバッグ シンボルがサポートされていません。

バージョン情報

.NET Framework 4 以降では、コンピューター全体のセキュリティ ポリシーが削除され、透過的セキュリティが既定の適用機構になりました。 「.NET Framework 4 におけるセキュリティの変更点」を参照してください。

.NET Framework version 2.0 Service Pack 1 以降では、動的アセンブリと動的メソッドを出力する際に、ReflectionPermissionReflectionPermissionFlag.ReflectionEmit フラグを指定する必要がなくなりました。 このフラグは、それ以前のすべてのバージョンの .NET Framework では必要となります。

メモメモ

FullTrust および LocalIntranet の名前付きアクセス許可セットでは、既定で ReflectionPermissionReflectionPermissionFlag.ReflectionEmit フラグが指定されますが、Internet アクセス許可セットでは指定されません。そのため、以前のバージョンの .NET Framework では、ReflectionEmit に対して Assert を実行する場合にのみ、インターネット アクセス許可でライブラリを使用できます。このようなライブラリでは、コーディング エラーがあるとセキュリティ ホールが発生するおそれがあるため、セキュリティを慎重に確認する必要があります。コードの生成は本質的に特権を必要とする操作ではないため、.NET Framework 2.0 SP1 はセキュリティ確認要求を発行せずに部分信頼シナリオでコードを出力できます。これは、生成されたコードには、コードを出力したアセンブリと同等以下のアクセス許可しかないことを意味します。これにより、コードを出力するライブラリは透過的セキュリティになるため、ReflectionEmit を要求する必要がなくなります。そのため、安全なライブラリを簡単に作成できるようになります。

さらに、.NET Framework 2.0 SP1 では部分的に信頼される動的メソッドの非パブリックの型およびメンバーにアクセスできるように、ReflectionPermissionFlag.RestrictedMemberAccess フラグが導入されています。 以前のバージョンの .NET Framework では、動的メソッドで非パブリックの型およびメンバーにアクセスするには ReflectionPermissionFlag.MemberAccess フラグが必要でした。これは、部分信頼のコードには付与されないアクセス許可です。

最終的に、.NET Framework 2.0 SP1 では、匿名でホストされるメソッドが導入されました。

型およびメンバーの情報の取得

.NET Framework 2.0 以降から、非パブリックな型とメンバーに関する情報を取得する際にアクセス許可は不要になりました。 動的メソッドを出力するために必要な情報を取得するには、リフレクションを使用します。 たとえば、MethodInfo オブジェクトを使用してメソッド呼び出しを出力します。 以前のバージョンの .NET Framework では、ReflectionPermissionReflectionPermissionFlag.TypeInformation フラグを指定する必要があります。 詳細については、「リフレクションに関するセキュリティ上の考慮事項」を参照してください。

参照

概念

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

その他の技術情報

動的メソッドおよびアセンブリの出力