特集:.NET 4の新セキュリティ・モデル解説

CASが廃止。.NET 4のセキュリティはどうなるのか?

デジタルアドバンテージ 一色 政彦
2010/01/26
Page1 Page2

 4月12日に米国でのローンチが予定されている.NET Framework 4(以降、.NET 4)では、さまざまな新機能の追加や機能拡張が行われる一方で、廃止されるものもある。その中で最も驚くべきものの1つが、「コード・アクセス・セキュリティ(以降、CAS)を利用したセキュリティ・ポリシー設定の廃止(=デフォルト無効化)」だ。

 CASといえば、.NETのランタイム・エンジン「CLR」のセキュリティ機構そのものであり、CLRとは切っても切り離せない機能だ(CASについて詳しくは「解説 インサイド .NET Framework [改訂版]」を参照)。.NET開発をしている人なら、ほとんどの人がCASを知っているだろう。

 そんな大事なものが廃止される?! これはいったいどういうことなのか?

CASが廃止される理由とは?

 疑いようもなくCASは、.NET 3.5 SP1までのCLRのセキュリティ機能として重要な役割を担ってきた。しかしその一方で、現実的にはCASは適切に使われてこなかった。システム管理者が、CASによりアプリケーションに最適なセキュリティ設定をしようとしても、そのセキュリティ設定作業がかなり難しかったからだ。

 セキュリティを強めすぎると、思いもよらないところでセキュリティ例外が発生してしまうし、だからといってすべてのコードへのアクセスを許可してはセキュリティを保てない。また、アプリケーションをバージョンアップして新機能を追加すれば、既存のセキュリティ設定を変更する必要性が発生することもある。こんなに難しく手間の掛かるものを、ましてやエンド・ユーザーが設定するというのは不可能だったに違いない。

 問題はそれだけではない。そもそもプログラム実行のセキュリティはマネージ・コード(=.NETアプリケーション)だけを防げばよいわけではない。C++で開発されたネイティブ・アプリケーションにはCASを適用できないため、システム管理者が頑張ってCASを適切に設定したとしても、誰かがネイティブ・アプリケーションを使うだけで、セキュリティは簡単に破られてしまうのだ。

 つまり、CASはセキュリティ機構として多機能で優秀なのは間違いないが、Windows OSレベルで見たときの実際の効力には疑問符が付くのである。

 結局、セキュリティを高めるには、例えばソフトウェアの制限のポリシー(以降、SRP)のようなOSレベルのソリューションを活用して、OS全体を保護すべきである。SRPであれば、マネージ・コードだけでなく、ネイティブ・コードに対してもセキュリティ・ポリシーを適用できるため、現実的に見て、CASよりもシンプルで、かつセキュリティ保証もより良いといえる。

 このような理由から、CASのセキュリティ・ポリシー(および、そのポリシーを決定するエビデンス)は廃止された。

 ただしここで注意してほしいのは、廃止されたのはあくまで、「[.NET Framework 構成]GUIツール(Mscorcfg.msc)Caspolコマンドライン・ツールを用いた、システム管理者やエンド・ユーザーによるマシン全体へのセキュリティ・ポリシーの設定である。アプリケーション内部におけるマネージ・コードへのアクセス許可(=パーミッション)の仕組み*1はそのまま残り、特定のセキュリティ環境下では、これまでどおりセキュリティ例外が発生するので、注意してほしい(詳細後述)。

*1 CASは、「エビデンス」(=出自情報)という入力、「ポリシー」というセキュリティ設定、「パーミッション」(=アクセス許可)という出力により成り立っている。詳しくは、「解説 インサイド .NET Framework [改訂版]」を参照されたい。

 また、CASの廃止に伴い、新しいセキュリティ・モデルも導入されることになった。そこで以下では、.NET 4の新しいセキュリティ・モデルについて詳しく説明していこう。

新しいセキュリティ・モデルを理解する

.NET 4の新しいセキュリティ・モデル

 .NET 4では、CASがデフォルトで無効になる代わりに、「レベル2のセキュリティ透過性モデル(Level 2 Security Transparency model)」と呼ばれるシンプルなセキュリティ・モデルが採用される。

 実はこれ、Silverlight 2以降で導入され、すでに実績のあるセキュリティ・モデルなのである(ちなみに「レベル1」のそれは、.NET 2.0のときに導入され、以降.NET 3.5まで、CLR内部でセキュリティ監査されるコード量を減らして処理の実行を効率化する目的で活用されてきた。つまり正確には、.NET 4では、既存のセキュリティ透過性モデルが強化され、デフォルトの実施機構に拡張されたということになる)。

 この説明だけだとよく分からないと思われるので、以下では、少し長くなるが、.NET 4のセキュリティ・モデル全体を含めて、基礎部分からセキュリティ透過性モデル(レベル2)について説明する。

【コラム】従来のCASポリシーを利用するには?

 場合によっては、従来のCASポリシーを利用したい場合もあるかもしれない。そのような場合は構成ファイル(App.configファイルなど)に、下記のコードを記述すれば、以前のCASポリシーの仕組みを有効化できる。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <!-- このプロセスで旧来のCASポリシーを有効にする -->
    <NetFx40_LegacySecurityPolicy enabled="true" />
  </runtime>
</configuration>
CASポリシーを有効化する構成設定

コード実行時の2つのセキュリティ環境:「完全信頼」と「部分信頼」

 まずコード実行時のセキュリティ環境を大別すると、下記の2つがある。

  • 完全信頼(Full Trust):すべてのコードが制限なく実行できる。
  • 部分信頼(Partial Trust):一部のコードが制限されて実行できない。

 .NET 4のセキュリティ・モデルでは、ネットワーク共有*2あるいはローカル・コンピュータから直接.EXEファイルを実行する場合は、常に「完全信頼」になる。完全信頼の場合は、セキュリティ制限を気にする必要はない。

*2  .NET 3.5 SP1で導入された仕様で、共有フォルダ上の.EXEファイルはフル権限で実行されるようになっている。セキュリティは、前述のSRPなどによってOSレベルで保護すべきという考え方に基づき、このような仕様になっている。

【コラム】完全信頼のときに妥当性検証をスキップするモード

 .NET 4では、実行の最適化を目的として、完全信頼のときに妥当性検証をスキップするモードが用意されている。これを利用するには、AssemblyInfo.cs/AssemblyInfo.vbファイルに、下記のコードを記述すればよい。

[assembly: SecurityRules(SecurityRuleSet.Level2,
    SkipVerificationInFullTrust = true)]
<Assembly: SecurityRules(SecurityRuleSet.Level2,
    SkipVerificationInFullTrust:=True)>
完全信頼のときに妥当性検証をスキップする構成設定(上:C#、下:VB)

 一方、(サンドボックス*3内に)ホストされたコード(例えばASP.NETClickOnceアプリケーションSQL CLRなど)、また、ユーザー・プログラムによりサンドボックス化されたアプリケーション・ドメイン内で実行されるコード(例えばユーザー・プログラム内でアプリケーション・ドメインを作成して、そこでプラグインをホストする場合など)は、それぞれのサンドボックス作成時のアクセス許可の設定内容に従って「部分信頼」もしくは「完全信頼」になる。

 ちなみに、ゾーン・エビデンス(=出自情報)に基づきセキュリティ・サンドボックスを提供していたノータッチ・デプロイメント(=Internet Explorerから.NETアプリケーションを直接実行する機能)は、エビデンスが廃止されたためか、ついに無効化されたようである(IE実行シェルであるIEExec.exeファイルが.NET 4には含まれていない)。

*3 サンドボックス(Sandbox:砂箱もしくは砂場)とは、特定のコードへのアクセスを制限する、セキュリティ的に保護された領域のことで、.NETでは実行コードの管理単位(=Windows OSのプロセスに該当)である「アプリケーション・ドメイン」をサンドボックス化できる。

部分信頼での3つのセキュリティ区分:「Transparent」「SafeCritical」「Critical」

 当然、セキュリティで課題になるのは、部分信頼の場合である。

 部分信頼のセキュリティ区分でコードを安全に実行するための最もシンプルな方法は、危険なコード(以降、Criticalコード)の実行は制限して、安全なコード(以降、Transparentコード)の実行のみ許可することである。ここでいうCriticalコードとは、例えばファイルやレジストリにアクセスするコードなどである。一方のTransparentコードとは、例えば計算やコレクション操作などである。

 しかしこの2種類のセキュリティ区別では、対処できない場面が存在する。例えば分離ストレージ(Isolated Storage)を考えてほしい。分離ストレージとは、ClickOnce配置やSilverlightのアプリケーションなどで、セキュリティ的に保護されたローカル・コンピュータ上のフォルダに、任意のファイルを保存できる機能である。この場合のセキュリティを考えると、実際のファイル入出力はCritical(=危険)ではあるが、分離ストレージを操作すること自体はTransparent(=安全)である。このような場面で、TransparentコードとCriticalコードの橋渡しをするのが“SafeCritical”(=安全化された危険)コードである。SafeCriticalコードでは、セキュリティ検証や無害化を行い、危険性をなくしたうえで、Criticalコードを呼び出せるようになっている。

 このセキュリティ区別を実現するため、.NET(やSilverlight)の基本クラス・ライブラリでは、メソッドに下記のいずれかの属性(いずれもSystem.Security名前空間の属性)が割り当てられている(割り当てられていない場合は、基本的にTransparentコードとして取り扱われる)。

  • SecurityCritical属性:危険なコードであることを示す。
  • SecuritySafeCritical属性:安全に扱えるように無害化された危険なコードであることを示す。

 このほかに、下記の属性も用意されている。

  • SecurityTransparent属性:安全な(=そのまま通り抜け可能な)コードであることを示す。

 ただしSecurityTransparent属性は、アセンブリ全体のコードをTransparentコードにするためのもので、メソッドに直接指定することはできない。SecurityTransparent属性を指定するには、AssemblyInfo.cs/AssemblyInfo.vbファイルに下記のコードを記述する。

[assembly: SecurityTransparent]
<Assembly: SecurityTransparent()>
SecurityTransparent属性の指定例(App.config)(上:C#、下:VB)

 SecurityCritical属性が付与されたCriticalコードを実行するには、完全信頼の権限が必要になる。部分信頼の権限で実行しようとすると、TargetInvocationException例外(System.Reflection名前空間)(エラー内容を要約すると「TransparentコードからCriticalコードにアクセスする試みが失敗した」)が発生する。

 属性が指定されていないTransparentコードや、SecuritySafeCritical属性が付与されたSafeCriticalコードは、完全信頼でも部分信頼でも実行できる。

 まとめると、部分信頼のアプリケーションを実行した場合、Criticalコードではセキュリティ例外が発生し、それ以外のコードはそのまま実行できる。

 これがセキュリティ透過性モデル(レベル2)の仕組みである。Silverlight 2以降や.NET 4では、このセキュリティ透過性モデル(レベル2)をセキュリティの最前線に配置することで、実行権限の検証処理を簡素化しているのである。

 注意点として、Transparentコード/SafeCriticalコード/Criticalコードは基本的に相互に呼び出せるが、例外があって、TransparentコードからCriticalコードを呼び出すことはできない。この仕様により、(理論的に)「Transparentコードを呼び出す際は、危険な処理の実行が存在しないこと」が保証される。

【コラム】.NET 4のセキュリティ透過性モデル(レベル2)に関する筆者の私見

 筆者がSilverlight 3と.NET 4の基本クラス・ライブラリにおけるそれぞれの属性指定を確認したところ、Silverlight 3は、ほとんどのコードがTransparentコードかCriticalコードであり、SafeCriticalコードはあまり存在しない。しかし.NET 4では、Criticalコードはほとんどなく、SafeCriticalコードだらけである。例えば前述したファイルやレジストリにアクセスするコードは、Silverlight 3だとCriticalコードで、.NET 4ではSafeCriticalコードである。

 次の画面は、分離ストレージを扱うIsolatedStorageFileクラスの内容である。以下のように、SecuritySafeCritical属性が多数割り当てられていることが分かる。

.NET ReflectorでIsolatedStorageFileクラスの属性設定を確認しているところ

 これは恐らく、Silverlightと.NETで求められるセキュリティ要件の違いに由来する仕様であろう。Silverlightの場合、実行環境は基本的にブラウザであり、求められるセキュリティ要件も固定的になる。そのため、アクセス許可にバリエーションを持たせる必要がない(ちなみに、ブラウザ外実行は信頼状態そのものが昇格されている。ただし.NETの完全信頼とまったく同じ機能を提供するわけではない)。

 しかし.NETの場合は、SQL CLRやASP.NETなどでさまざまなセキュリティ要件を選択できる。さらにClickOnceの部分信頼では、細かくアクセス許可の設定をカスタマイズ可能だ。広範囲なテクノロジのセキュリティ要件に対して柔軟にアクセス許可を提供するには、多くのコードを(Criticalコードではなく)SafeCriticalコードにする必要があったのだろう。Criticalコードのままだと、そのコードにはアクセス許可があってもセキュリティ例外が発生してしまう結果となるからだ。

 なおMSDNライブラリでは、一部のもの(例:Mutexクラスのコンストラクタ)において、[.NET Framework セキュリティ]欄に「SecurityCriticalAttribute」が設定されているかが明記されている。

 ここで気になるのは、SecurityTransparent属性/SecuritySafeCritical属性/SecurityCritical属性を、自分が開発しているコード(以降、ユーザー・コード)でも指定しなければならないのか、ということである。もちろん通常の開発では、これらの属性を設定する必要はない。設定が必要なのは、不特定多数の人にライブラリを提供するような場合である。これまで、アクセス許可の属性(=System.Security.Permissions名前空間のCodeAccessSecurityAttributeクラスの派生クラス)をコード中に指定してきた開発者であれば、同様にSecurityTransparent属性/SecuritySafeCritical属性/SecurityCritical属性も指定する必要があるだろう。

 ちなみに、メソッドのオーバーライドで基本クラスと派生クラスで属性の設定が異なる場合など、1つのメソッドに属性が重複して設定されている場合は、下記の力関係で最終的な属性が決定する。

  Transparent < SafeCritical < Critical

 以上で説明したセキュリティ透過性モデル(レベル2)の仕組みにより、大ざっぱなセキュリティ検証が行われるわけだが、.NET 4ではこの後にアクセス許可の検証が行われる。続いて、これについて説明しよう。

CASによるアクセス許可の仕組み

 冒頭でも説明したが、.NET 4で、CASのセキュリティ・ポリシーと、それを決定するエビデンスは廃止されるが、アクセス許可の仕組みは生き残る。つまり、ライブラリ中に記述されているアクセス許可の属性(=System.Security.Permissions名前空間のCodeAccessSecurityAttributeクラスの派生クラス。例:UIPermissionやFileDialogPermissionなど)は、.NET 4でも有効である。

 部分信頼で実行しているアプリケーションのTransparentコードとSafeCriticalコードは、アクセス許可の属性が指定されているメソッドにアクセスする際、その属性のアクセス許可を持たないと、セキュリティ例外が発生する。保有するアクセス許可を決定するのは、ホスト・アプリケーションやサンドボックス・アプリケーションのホスト(例えばClickOnceホストやASP.NETホストなど)である。ClickOnceの場合は、プロジェクト・プロパティの[セキュリティ]タブから(ゾーン・エビデンスに対応する)アクセス許可セット(=複数のアクセス許可をセットとしてまとめたもの)を選択できるので、保有するアクセス許可は分かりやすいだろう。

 プログラム内で独自にサンドボックスを作成する際にアクセス許可を指定する場合は、アクセス許可をひとまとめにするPermissionSetオブジェクト(System.Security名前空間)を利用する。アクセス許可は個別に指定することもできるが、.NETではゾーン・エビデンスに対して最適な標準的なアクセス許可セットも用意されている。筆者がプログラムにより自動収集したアクセス許可セットの内容は、次の表のようになっている。

ゾーン アクセス許可(オプション)
NoZone なし=セキュリティが必要な処理はすべて制限する
MyComputer 無制限=すべての処理を実行できる=完全信頼
Intranet ・EnvironmentPermission(Read:USERNAME)
・FileDialogPermission(Unrestricted:true)
・IsolatedStorageFilePermission(Expiry:9223372036854775807、Permanent:True、A
llowed:AssemblyIsolationByUser、UserQuota:9223372036854775807)
・ReflectionPermission(Flags:ReflectionEmit, RestrictedMemberAccess)
・SecurityPermission(Flags:Assertion, Execution, BindingRedirects)
・UIPermission(Unrestricted:true)
・PrintingPermission(Level:DefaultPrinting)
・DnsPermission(Unrestricted:true)
・TypeDescriptorPermission(Unrestricted:true)
・MediaPermission(Video:SafeVideo、Image:SafeImage、Audio:SafeAudio)
・WebBrowserPermission(Level:Safe)
Internet ・FileDialogPermission(Access:Open)
・IsolatedStorageFilePermission(Allowed:ApplicationIsolationByUser、UserQuota
:1024000)
・SecurityPermission(Flags:Execution)
・UIPermission(Window:SafeTopLevelWindows、Clipboard:OwnClipboard)
・PrintingPermission(Level:SafePrinting)
・MediaPermission(Video:SafeVideo、Image:SafeImage、Audio:SafeAudio)
・WebBrowserPermission(Level:Safe)
Trusted ・FileDialogPermission(Access:Open)
・IsolatedStorageFilePermission(Allowed:ApplicationIsolationByUser、UserQuota
:1024000)
・SecurityPermission(Flags:Execution)
・UIPermission(Window:SafeTopLevelWindows、Clipboard:OwnClipboard)
・PrintingPermission(Level:SafePrinting)
・MediaPermission(Video:SafeVideo、Image:SafeImage、Audio:SafeAudio)
・WebBrowserPermission(Level:Safe)
Untrusted なし=セキュリティが必要な処理はすべて制限する
各ゾーン標準のアクセス許可の一覧表
PrintingPermissionクラスはSystem.Drawing.Printing名前空間、DnsPermissionクラスはSystem.Net名前空間、それ以外はすべてSystem.Security.Permissions名前空間に所属する。
この表と同様の情報を取得するためのコード(C#)はこちらからダウンロードできる。

 今回のセキュリティ・ポリシーとエビデンスの廃止により、CAS関連クラスやそのメンバがいくつか廃止され、警告が出るようになっているので注意してほしい(例えばAppDomain.SetAppDomainPolicyメソッドなどや、アクセス許可の属性にアクションとして指定できるSecurityAction列挙体のDenyやRequestMinimum、RequestOptional、RequestRefuseなど)。詳しくは「MSDN:.NET Framework 4: Code Access Security Policy Compatibility and Migration(英語)」を参照してほしい。

 また、ノータッチ・デプロイメントが廃止されたことは前述したが、ゾーン・エビデンス(=出自情報)が利用できないため、パラメータに「http://...」(インターネット)や「\\server\...」(イントラネット)を指定したAssembly.LoadFromメソッドの呼び出しも、デフォルトではサポートされない。

 例えば次のコードは、デフォルトで例外が発生する。

using System.Reflection;

Assembly asm =
  Assembly.LoadFrom(
    @"\\server01\usr\masa-i\ClassLibrary1.dll"
    //@"http://www.masahiko.info/ClassLibrary1.dll"
  );

MethodInfo target =
  asm.GetType("ClassLibrary1.Class1").GetMethod("Main");
target.Invoke(null, null);
Dim asm As Assembly =
  Assembly.LoadFrom(
    "\\server01\usr\masa-i\ClassLibrary1.dll"
  )
'http://www.masahiko.info/ClassLibrary1.dll"

Dim target As MethodInfo =
  asm.GetType("ClassLibrary1.Class1").GetMethod("Main")
target.Invoke(Nothing, Nothing)
デフォルトで例外が発生するAssembly.LoadFromメソッドのサンプル・コード(上:C#、下:VB)

 .NET 4では、上記のコードを実行するための方法が用意されている。具体的には構成設定(App.configファイル)に下記のコードを記述する。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <!-- 警告:ネットワーク共有やインターネットなどの離れた場所から
         完全信頼としてアセンブリをロードする -->
    <loadFromRemoteSources enabled="true" />
  </runtime>
</configuration>
Assembly.LoadFromメソッドで離れた場所にあるアセンブリをロードするために必要な構成設定(App.config)

 この設定を行ったうえでAssembly.LoadFromメソッドを呼び出すと、ロードされたアセンブリは常に完全信頼になる。なお、Assembly.LoadFromメソッドはその内部でSecurityCritical属性が付与されているので、呼び出し元も完全信頼でなければならない。

 以上で.NET 4のセキュリティ・モデルの全体像については解説した。解説だけでは、実際のコードと結び付けてなかなか理解できないという読者もいるだろう。次のページでは、実際に自分で独自のサンドボックスを作成して、セキュリティ環境(完全信頼/部分信頼)やセキュリティ区分(Transparent/SafeCritical/Critical)の動作を、実際のコードで確認・検証する。


 INDEX
  特集:.NET 4の新セキュリティ・モデル解説
  CASが廃止。.NET 4のセキュリティはどうなるのか?
  1.新しいセキュリティ・モデルを理解する
    2.新しいセキュリティ・モデルの動作を確認・検証する


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間