Javaセキュリティ(その1) 萩谷 昌己 (東京大学) with the help of 戸沢 晶彦 (東京大学) Javaセキュリティの階層 • バイトコード検証系(bytecode verifier) → JDK1.2 ローダ制約(loader constraint)の導入 • クラスローダ(class loader) → JDK1.2 安全なクラスローダ(secure class loader) • セキュリティ・マネージャ(security manager) → JDK1.2 アクセス・コントローラ(access controller) • RMIセキュリティ拡張(RMI security extension) • JINIセキュリティ Javaアタックの歴史 http://java.sun.com/sfaq/chronology.html Javaセキュリティ・アーキテクチャ • JDK1.0 砂場モデル(sandbox model) リモート・コード(信頼できないコード)は、 システム・リソースにアクセスできない (砂場の中でしか遊べない)。 • JDK1.1 署名付きアプレット(signed applet) 信頼できる署名の付いたコードは、 ローカル・コードと同様に扱われる。 • JDK1.2 保護ドメイン(protection domain) 保護ドメインを単位とした精密なアクセス制御 保護ドメイン(protection domain) • コードベース + 署名者名 – コードベース(codebase) … URL – 署名者名(signer name) … 複数指定可(andが取られる) セキュリティ・ポリシー(security policy) • どの保護ドメインに どのような許可(permission)を与えるか。 • ポリシー・ファイル(policy file)による簡潔な記述 grant [SignedBy "signer_names"] [, CodeBase "URL"] { permission permission_class_name [ "target_name" ] [, "action"] [, SignedBy "signer_names"]; permission … }; アクセス制御 • AccessControllerクラスの checkPermissionメソッド • その呼び出し方: FilePermission perm = new FilePermission("path/file", "read"); AccessController.checkPermission(perm); • 現在の実行コンテキストのもとで、 アクセスの許可を調べる。 アクセス制御 • アルゴリズム: i = m; while (i > 0) { if (caller i's domain does not have the permission) throw AccessControlException; else if (caller i is marked as privileged) return; i = i - 1; }; inheritedContext.checkPermission(permission); • inheritedContext … 親スレッドのコンテキスト 特権(previlege) • 実行コンテキストに特権を与える。 class A implements PrivilegedAction { Object run() { ... } } A a = new A(); Object o = AccessController.doPrivileged(a); • 実行コンテキストにprivilegedのマークが付いて、 runメソッドが実行される。 • runメソッドの実行中は、 doPrivilegedの呼び手のところで、 アクセスのチェックが終了する。 アクセス制御コンテキスト • コンテキストの取得: AccessControlContext acc = AccessController.getContext(); • コンテキストを指定した制御: acc.checkPermission(permission); • コンテキストを指定した特権の付与: Object o = AccessController.doPrivileged(a, acc); アクセス制御 • アルゴリズム(コンテキストの指定がある場合): i = m; while (i > 0) { if (caller i's domain does not have the permission) throw AccessControlException; else if (caller i is marked as privileged) if (a context was specified in the call to doPrivileged) context.checkPermission(permission); return; i = i - 1; }; inheritedContext.checkPermission(permission); Permissionクラス • 抽象クラス abstract boolean implies(Permission permission) – a.implies(b)は、許可aが許可bを 包含することを意味する。 • サブクラス: – AllPermission, BasicPermission, – FilePermission, SocketPermission, – UnresolvedPermission FilePermissionクラス • • • • • • • • new new new new new new new new FilePermission("myfile", "read,write"); FilePermission("/home/gong/", "read"); FilePermission("/tmp/mytmp", "read,delete"); FilePermission("/bin/*", "execute"); FilePermission("*", “read”); FilePermission("/-", "read,execute"); FilePermission("-", "read,execute"); FilePermission("<<ALL FILES>>", "read"); クラスローダ • クラス・ファイルをロードするオブジェクト • ClassLoaderクラスのサブクラスの インスタンス • クラスの名前空間を作る働きも担っている。 クラス解消アルゴリズム (class resolution algorithm) --- SecureClassLoaderの場合 • クラスが既にロードされていないかチェック。 • 現在のクラスローダに委譲関係の親があれば、 親にクラスのロードを委譲。 – SecureClassLoaderは親を指定して作成できる。 – 親が指定されていない場合は、 primordial class loaderに委譲する。 • 親が解消できなければfindClassを呼び出す。 Saraswatのバグ public class RT { public static void main(String arg[]) { RR rr = new RR(); R r = rr.getR(); RTのローダはRをロード。 r.speakUp(); RTのローダはRRのロードを } システム・ローダに委譲。 } システム・ローダはRをロード。 public class RR { public R getR() { return new R(); } } public class R { public void Icantspeak() { ... } } public class R { public void speakUp() { ... } } Tozawaのバグ(その1) class B extends A { ... } class C extends A { ... } public class D { static boolean t public D() { A a; if (t) a = new B(); else a = new C(); a.speakUp(); } } = true; バイトコード検証系は、 BとCのスーパークラス(の名前)を Aと計算するが、Aをロードしない。 名前だけでAとAを等しいとみなす。 Tozawaのバグ(その2) Package java.lang; public class A { pulic java.lang.C foo(java.lang.B x) { return x; } Java2のバイトコード検証系は、 } システム・クラスを検証しない。 public class D { public D() { java.lang.B b = new java.lang.B(); java.lang.C c = (new java.lang.A()).foo(b); } } バイトコード検証 • バイトコードに対する型推論 • データフロー解析の一種 • JVMのバイトコードには、 バイトコード検証が可能なように、 型の情報が含まれている。 – aload – iload – dload バイトコード検証の問題点 • サブルーチン – 帰り番地が変数に格納される。 – 必ずしも直接の呼び手に帰らない。 – サブルーチンによって変数の使い方が異なる。(多相性) • オブジェクトの初期化 – 初期化されていないオブジェクトの参照を 禁止しなければならない。 – ソース・コードでは保証されているが、 バイトコードでは、バイトコード検証系が 保証しなければならない。 バイトコード検証の問題点 • loading constraint schemeとの関連 – 必ずしもloading constraint schemeとの 連携がうまくいっていない。 • システム・クラスや署名付きクラスの検証 – システム・クラスや署名付きクラスは、 その正しさが保証されているので、 バイトコード検証を省略したい。しかし、 安易に省略すると、問題が生じる。 バイトコード検証の定式化 • 型システムによる定式化 – – – – バイトコードに対する型体系 各命令に対する型規則 バイトコード検証を型推論として定式化する。 型安全性 型推論が成功すれば実行時の型エラーは 起こらない。
© Copyright 2024 ExpyDoc