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

.NET Framework には、共通中間言語 (CIL) を出力する方法が 3 つありますが、それぞれに固有のセキュリティ問題があります。

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

Note

コードでのリフレクションとコードの出力に必要なアクセス許可は、その後の .NET Framework のリリースごとに変更されています。 この記事の「バージョン情報」をご覧ください。

動的アセンブリ

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

Note

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

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

Note

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

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

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

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

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

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

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

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

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

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

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

Note

概念的には、メソッドの作成中に要求がなされます。 つまり、CIL 命令が生成されるたびに要求を実行できます。 現在の実装では、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 が含まれる場合、許可セットが出力元アセンブリの許可セットと同じか、またはそのサブセットであるアセンブリの非パブリックの型とメンバーを使用できます。

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

Note

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

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

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

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

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

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

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

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

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

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

Note

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

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

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

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

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

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

Note

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

バージョン情報

.NET Framework 4 以降では、コンピューター全体のセキュリティ ポリシーが削除され、セキュリティ透過性が既定の適用機構になっています。

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

Note

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 フラグを指定する必要があります。 詳しくは、「リフレクションに関するセキュリティ上の考慮事項」をご覧ください。

関連項目