解説

インサイド .NET Framework [改訂版]

第9回 コード・アクセス・セキュリティ(その4)

吉松 史彰
2003/09/03
Page1 Page2 Page3 Page4 Page5 Page6 Page7

アクセス許可を取り戻す(Assert)

 DenyやPermitOnlyを利用すると、その後でDemandが行われたときにチェックされるアクセス許可の内容が変更され、より厳しい検査を受けることになる。.NET Frameworkには、反対に、いまは与えられていないが本来与えられているアクセス許可を取り戻して、自分に適用されるアクセス許可を緩くする機能もある。それがAssertだ。Assertも、Demand、Deny、PermitOnlyと同様に、メソッドとして呼び出すことも、属性として指定することもできる。

 例えば、冒頭で示したPermTestとDBAccessのコードが、それぞれ次のようになっていたとしよう。デリゲートの設定によって、結果的に処理がPermTestクラスに戻ってくるわけだ。

using System;
using System.Reflection;

[assembly: AssemblyKeyName
    ("CspContainer"), AssemblyVersion("1.0")]

public delegate void Callback();
public class DBAccess {
  public static Callback cb;

  public static void Test() {
    cb();
  }
}
デリゲート呼び出しだけを行うように修正したDBAccess.cs
 
using System.Data.SqlClient;

class PermTest {
  static void Main() {
    DBAccess.cb = new Callback(PermTest.Callback);
    DBAccess.Test();
  }
  public static void Callback() {

    SqlConnection cn = new SqlConnection(
        "Server=.;UID=user;PWD=secret;Database=Northwind");

    SqlCommand cmd = new SqlCommand(
        "SELECT FirstName FROM Employees", cn);

    cn.Open();
    SqlDataReader reader = cmd.ExecuteReader();
    while(reader.Read()) {}
    reader.Close();
    cn.Close();
  }
}
デリゲート経由でデータベース処理が呼び出されるように修正したPermTest.cs

 この場合、DBAccessアセンブリがLocalIntranetのアクセス許可セットを持っているため、コールスタックを順にたどっていった結果、DBAccessのところでセキュリティ例外となる(図6)。

図6 セキュリティ例外となるコールスタック調査
上記のコードでは、DBAccessアセンブリがLocalIntranetのアクセス許可セットを持っているため、コールスタック調査の結果、DBAccessのところでセキュリティ例外となる。

 ところが、PermTestクラスのCallbackメソッドに次の属性が付いているか、またはメソッドの先頭で次のようなメソッド呼び出しが行われていると、話が変わってくる。

[SqlClientPermissionAttribute(SecurityAction.Assert, Unrestricted=true)]

 または

SqlClientPermission perm
    = new SqlClientPermission(PermissionState.Unrestricted);
perm.Assert();

 Assertを行うと、図7のようにコールスタックが変更され、Assertが行われた場所までしかアクセス許可のチェックが及ばなくなる。この場合はAssertの直後にSqlConnectionクラスのOpenメソッドを呼び出しているため、OpenメソッドのDemandでチェックされるのはPermTestアセンブリだけとなる。PermTestアセンブリはFullTrustを持っているため、SQL Serverへのアクセスが可能となる。つまり、DBAccessアセンブリが介在していることは無視されるのだ。

図7 Assertにより調査されないコールスタック
Assertの直後にSqlConnectionクラスのOpenメソッドを呼び出しているため、OpenメソッドのDemandでチェックされるのはPermTestアセンブリだけとなる。

 敏感な読者ならすぐに分かるとおり、Assertはそれ自体がセキュリティ・ホールであるかのような機能になっている。そのため.NET Frameworkでは、Assertを行うためには「Assertを行ってもよい」というアクセス許可が必要になる。

 具体的には、System.Security.Permissions.SecurityPermissionクラスに、フラグとしてSystem.Security.Permissions.SecurityPermissionFlag.Assertionがセットされているアクセス許可を持っていなければならない。つまりAssertを行うと、まず下の図8のようにコールスタック全体がAssertを行うアクセス許可を持っているかどうか確認され、すべてがOKとなって初めて図7のようにコールスタックが変更されるということだ。

 LocalIntranetのアクセス許可セットではAssertが許可されているため、上記のPermTestとDBAccessの組み合わせの場合はAssertが成功する。だが、インターネットからダウンロードされたアセンブリにはデフォルトではAssertが許可されていないため、Assertを呼び出して自分のアクセス許可設定を緩くすることはできない。

図8 コールスタックにおけるAssertの確認
Assertを行うと、コールスタック全体がAssertを行うアクセス許可を持っているかどうか確認され、すべてがOKとなって初めてコールスタックが変更される。LocalIntranetのアクセス許可セットではAssertが許可されているため、この図の組み合わせの場合はAssertが成功する。

 Assertは非常に強力な機能なので、何らかの理由でデフォルトのポリシーを変更した独自のポリシーを作成する場合には注意してほしい。本来不要なはずのアセンブリにAssertの許可を与えてしまうと、コード・アクセス・セキュリティの機能は台無しになってしまう。


 INDEX
  解説 インサイド .NET Framework [改訂版]
  第9回 コード・アクセス・セキュリティ(その4)
    1.アクセス許可が適用されるタイミング
    2.Demandメソッドの内部動作
    3.属性によるアクセス許可チェックの指定
    4.型のロード時におけるチェック
    5.JITコンパイル時のチェックとDemandの動作の変更
  6.アクセス許可を取り戻す
    7.アセンブリ・レベルでの宣言セキュリティ
 
インデックス・ページヘ  「解説:インサイド .NET Framework [改訂版]」


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 記事ランキング

本日 月間