310 likes | 515 Views
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)
E N D
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 FilePermission("myfile", "read,write"); • new FilePermission("/home/gong/", "read"); • new FilePermission("/tmp/mytmp", "read,delete"); • new FilePermission("/bin/*", "execute"); • new FilePermission("*", “read”); • new FilePermission("/-", "read,execute"); • new FilePermission("-", "read,execute"); • new 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(); r.speakUp(); } } public class RR { public R getR() { return new R(); } } public class R { public void Icantspeak() { ... } } public class R { public void speakUp() { ... } } RTのローダはRをロード。 RTのローダはRRのロードを システム・ローダに委譲。 システム・ローダはRをロード。
Tozawaのバグ(その1) class B extends A { ... } class C extends A { ... } public class D { static boolean t = true; public D() { A a; if (t) a = new B(); else a = new C(); a.speakUp(); } } バイトコード検証系は、 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; } } public class D { public D() { java.lang.B b = new java.lang.B(); java.lang.C c = (new java.lang.A()).foo(b); } } Java2のバイトコード検証系は、 システム・クラスを検証しない。
バイトコード検証 • バイトコードに対する型推論 • データフロー解析の一種 • JVMのバイトコードには、 バイトコード検証が可能なように、 型の情報が含まれている。 • aload • iload • dload
バイトコード検証の問題点 • サブルーチン • 帰り番地が変数に格納される。 • 必ずしも直接の呼び手に帰らない。 • サブルーチンによって変数の使い方が異なる。(多相性) • オブジェクトの初期化 • 初期化されていないオブジェクトの参照を 禁止しなければならない。 • ソース・コードでは保証されているが、 バイトコードでは、バイトコード検証系が 保証しなければならない。
バイトコード検証の問題点 • loading constraint schemeとの関連 • 必ずしもloading constraint schemeとの 連携がうまくいっていない。 • システム・クラスや署名付きクラスの検証 • システム・クラスや署名付きクラスは、 その正しさが保証されているので、 バイトコード検証を省略したい。しかし、 安易に省略すると、問題が生じる。
バイトコード検証の定式化 • 型システムによる定式化 • バイトコードに対する型体系 • 各命令に対する型規則 • バイトコード検証を型推論として定式化する。 • 型安全性 型推論が成功すれば実行時の型エラーは 起こらない。