解説インサイド .NET Framework第9回 コード・アクセス・セキュリティ(その1) インフォテリア株式会社 |
コード・グループとパーミッション・セット
ポリシーを編集するためには、入力であるエビデンスと、出力であるパーミッションとを組み合わせなければならない。しかし、デフォルトでも7つあるエビデンスと20以上あるパーミッションを1つ1つ組み合わせてポリシーを作るのは大変だ。そこで、コード・グループとパーミッション・セットの出番となる。
パーミッション・セットはパーミッションの組み合わせだ。例えば、実行可能(SecurityPermission)で、C:\Tempフォルダに対して読み取り権限を持ち(FileIOPermission)、かつDNSで名前解決を行ってもよい(DnsPermission)という組み合わせを作ることができる。
コード・グループはエビデンスの組み合わせ(メンバーシップ)とパーミッション・セットの対応付けを行う。例えば、「Siteがwww.atmarkit.co.jpで、(株)デジタルアドバンテージ社の証明書(Publisher)が付いている」という組み合わせをメンバーシップとして定義し、その条件に合うアセンブリには上記のようなパーミッション・セットを与える、というコード・グループを定義できる。コード・グループのメンバーシップは、指定されているエビデンスすべてに合致するアセンブリであることが条件となる。上記のコード・グループの場合、Siteがwww.atmarkit.co.jpだというだけではこのコード・グループには所属しないことになる。
実際にポリシーを編集するときは、まずコード・グループのメンバーシップを作成(編集)し、次にパーミッション・セットを作成(編集)し、最後にメンバーシップとパーミッション・セットを結び付けてコード・グループにする。CLRはアセンブリをロードするときにエビデンスを収集し、収集したエビデンスと合致するメンバーシップを持つコード・グループを特定し、そのコード・グループに適用されているパーミッション・セットを受け取って、中にあるパーミッションをアセンブリに割り当てるという手順でコード・アクセス・セキュリティをセットアップするわけだ。
デフォルトのポリシー
.NET Frameworkをインストールすると、デフォルトのポリシーがインストールされる。デフォルトでは、マシン・ポリシーだけに意味ある設定がなされている状態である。エンタープライズ・ポリシーとユーザー・ポリシーには、All_Codeコード・グループに対してFullTrustパーミッション・セットが割り当てられている。つまり、すべてのコードが何でもできるという状態になっているということだ。これらのポリシーには何の意味もない。実際に適用されるのは4つのレベルのポリシーの論理積であるので、結局マシン・ポリシーの設定だけが適用されるのと同じことになる。
デフォルトのマシン・ポリシーには、コード・グループが5つ定義されている。
MyComputer_Zone
LocalIntranet_Zone
Internet_Zone
Restricted_Zone
Trusted_Zone
名前を見れば一目瞭然だが、これらのコード・グループのメンバーシップには、エビデンスとしてZoneだけが設定されている。それぞれコード・グループ名に対応するZoneのエビデンスを持つアセンブリが、それぞれのコード・グループに属することになる。つまり、デフォルトではCLRが収集するエビデンスのうち、役立つのはZoneだけだということだ。
デフォルトのポリシーには、次に列挙した7つのパーミッション・セットが定義されている。これらは名前付きパーミッション・セット(NamedPermissionSet)と呼ばれている。
FullTrust
すべてのパーミッション。「すべて」という言葉には(おそらく読者の)想像以上の意味が含まれている。この先どんなパーミッションが新しく作成されようとも、文字どおりすべてのパーミッションがこの中に含まれる。
SkipVerification
CLRの中心的機能であるコードの安全性の検証機能をバイパスできるパーミッション。非常に強力なので利用には注意が必要だ。
Everything
既存のすべてのパーミッション(コードの安全性の検証機能をバイパスするパーミッションだけを除く)が許可されている。FullTrustとは異なるので注意してほしい。
LocalIntranet
特定の環境変数へのアクセス、System.Windows.Forms.FileDialogクラスを利用したファイルへの読み書き、System.IO.IsolatedStorage.IsolatedStorageクラスを利用したIsolatedStorageサービスへのアクセス、System.Reflection.Emit名前空間を利用したコードの生成と実行、実行とアサート(後述)、無制限のユーザー・インターフェイス(Windowsフォーム)へのアクセス、DNSによる名前解決、デフォルト・プリンタを利用した印刷、ローカル・マシンのイベント・ログの読み書きが許可されている。
Internet
System.Windows.Forms.OpenFileDialogクラスを利用したファイルの読み取り、System.IO.IsolatedStorage.IsolatedStorageクラスを利用したIsolatedStorageサービスへのアクセス、実行、トップレベル・ウィンドウと自分で作成したクリップボード・データへのアクセス、ダイアログ・ボックスからのみアクセスできる印刷が許可されている。
Execution
コードの実行を許可するパーミッションだけが含まれる。
Nothing
無許可。一切のパーミッションを与えない。
デフォルトのマシン・ポリシーでは、コード・グループとパーミッション・セットは次のような組み合わせになっている。
コード・グループ | パーミッション・セット |
MyComputer_Zone | FullTrust |
LocalIntranet_Zone | LocalIntranet |
Internet_Zone | Internet(RTM版)/Nothing(SP1、SP2) |
Restricted_Zone | Nothing |
Trusted_Zone | Internet |
デフォルトのマシン・ポリシーにおける、コード・グループとパーミッション・セット |
Internet_Zoneコード・グループに注意してほしい。Microsoftは製品のセキュリティ強化プログラムの一環として、.NET Frameworkのサービス・パック1(SP1)以降でInternet_Zoneのパーミッション・セットを変更した。最初のRTM版ではインターネットからダウンロードしたアセンブリが、最低の権限ながら実行だけはできていたが、SP1、SP2を適用したマシンではインターネットから来たアセンブリには一切何の権限も与えられず、実行もできなくなった。
コード・アクセス・セキュリティの動作(再確認)
ここまでの解説で、冒頭のプログラムがどうして動いたり動かなくなったりしたのかが説明できるようになったはずだ。
まず普通に実行できた方を確認してみよう。MainClass.exeを実行すると、すぐにFileReaderアセンブリが呼び出される。このタイミングでCLRはFileReaderアセンブリに適用されるパーミッションを特定するため、エビデンスの収集を行う。上記のとおり、デフォルトのポリシーではZoneのエビデンスだけが考慮される。つまり、サンプル・アプリケーションFileReaderはC:\Temp(筆者の場合)からロードされたため、MyComputerのZoneエビデンスを持つことになり、MyComputer_Zoneコード・グループに合致することになる。MyComputer_Zoneコード・グループにはFullTrustパーミッション・セットが与えられているため、何でもできるのでファイルの読み取りもできるわけだ。
一方、共有フォルダから同じファイルにアクセスした場合は、FileReaderアセンブリが\\crystalriver\SHARED\という共有フォルダ(筆者の場合)からロードされたことになるため、IntranetのZoneエビデンスを持つことになり、LocalIntranet_Zoneコード・グループに合致することになる。LocalIntranet_Zoneコード・グループにはLocalIntranetパーミッション・セットが与えられているため、上記のとおり無制限のファイルI/Oは許されていない。そのためにC:\Boot.iniに対する読み取りアクセスが拒否され、冒頭の例外になったのだ。
今回のまとめ
コード・アクセス・セキュリティは地味ながらもCLRの中心的機能だ。セキュリティ、しかもプログラムのセキュリティとくればプログラマーにはもっとも苦手な分野であり、その分敬遠されているのか、情報も少ない。しかし、この機能をきっちり把握しておかないと、「開発中は動いたのに運用先で急に動かなくなった……」などと泣く羽目になりかねない。セキュリティはいまやソフトウェア開発において最優先事項の1つになっている。コード・アクセス・セキュリティの理解はすべての.NET Framework開発者にとって絶対に必要な知識であると断言しよう。
次回はコードの書き方を含めて、よりコード・アクセス・セキュリティの詳細に迫ってみたい。
INDEX | ||
解説 インサイド .NET Framework | ||
第9回 コード・アクセス・セキュリティ(その1) | ||
1.コード・アクセス・セキュリティの動機と動作 | ||
2.エビデンス、ポリシー、パーミッション | ||
3.コード・グループとパーミッション・セット | ||
「解説:インサイド .NET Framework 」 |
- 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|