トップ «前の日記(2013-06-30) 最新 次の日記(2013-07-02)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2013-07-01

_ トリッキーなJava

本棚を整理していたら、えらく以前にアスキーの鈴木さんにもらった、Javaセキュアコーディングスタンダードを見つけた。

正直、もうJavaはいらないかなぁと思ったが、何気なくぱらぱら見ていたら結構おもしろくて、つい読みふけってしまった。

この本はJava6を前提として(一部Java7についても取り込んでいる。いずれにしても、concurrentはJava6からなので一番おもしろい箇所はちゃんと取り込まれている)、CERTが標準と定めるセキュアなコーディングスタンダードについて説明した本で、書いてあることの1/3は普通にJavaをプログラミングしていれば知っていて当然のことばかりが書いてあるし、そのうちさらに半分は、正直なところどうでも良いことだ。

が、volatileの説明について、ここまでわかりやすく説明しているのは初めて読んだ。「わかりやすい説明」というのは、ここでは簡単な言葉を使ってなんとなく気分的にわかったような気に短時間でさせるという意味ではなく、条件とその条件に合致する例を示し、その例において具体的に何が起きるかを正確に示すような書き方をしているという意味だ。

さらに、先頭に入出力についての絵がかいてあるが、1)正規化/標準化、2)無害化(ここは議論が分かれる点と思う。1)と3)のみで良いのではなかろうか)、3)検証 という入力のステップと、出力の無害化を分けて説明してある。最初に正規化/標準化を置くというのは、データがアプリケーションへ到達するまで多層化している現状においては、すごく重要なことだと思うが、検証については誰でも語るが(もちろん語らなければならないが)、正規化/標準化としてステップを置いてあるのはなるほど、それはその通りだとあらためて思った。

ただし、2)は何かの間違いのような気がする(入出力の絵の説明で入力無害化の参照項目と示した箇所でも説明されているのは正規化だ)。

この本が本当におもしろくなるのは、攻撃からの防御について書いてある(全体がそうだと言えばそうなのだが)項目だ。

例を示す。

public class Secret {
    private int sec1;
    private int sec2;
    public int getSec1() { return sec1; }
    public int getSec2() { return sec2; }
    public Secret() {
        sec1 = 30;
        throw new IllegalStateException(); // 良からぬ状態を検出
    }
}

この秘密のクラスには、getSec1を初めとした非常に便利なメソッド群が用意されていると仮定する。

攻撃者は、このクラスのインスタンスを利用してメソッドを呼び出し、可能な限り秘密の情報なり操作なりを実行したい。しかし、このクラスは安全あるいは信頼がおける実行環境または生成クラスかどうかをコンストラクタでチェックし、異常を検出すると生成を途中でやめて例外をスローする。

どうやって攻撃すれば良いか?

public class SecretBreaker extends Secret {
    protected void finalize() {
        System.out.println("sec1 = " + getSecret1()); // # 30(情報が取れた)
        System.out.println("sec2 = " + getSecret2()); // # 0(この情報は取れなかった)
    }
    public static void main(String args[]) {
        try {
            Secret s = new SecretBreaker();
        } catch (Exception e) {
            // 想定内
        }
        System.gc();
        System.runFinalization(); // 情報の取得
    }
}

なるほど。こんな方法があったのか(本の例はもっと複雑なものとなっている)。

したがって、Secretクラスは設計ミスであり、情報漏えいを防ぐのであればfinal classにするか、それがだめならばfinal void finalize()を定義する必要があるか、またはコンストラクタをprivateとpublicの2段階にする(コンストラクタによる防御はJDK1.6が必須らしいが、これはちょっと理由がわからなかった。1.5でも問題ないように思えるのだが、1.6で実行順序がそれまでと変わって規定されたとかかな)。

この本の「CERT/Oralce」というタイトルはわかりにくく、しかも一通り読んでもどういう意味かわからない(少なくとも説明を見つけられなかった)。そのくせ、帯に相当する表紙の一部に『Androidアプリ開発者必携』とか書いてあって、Oracleという名前とDALVIKがどうからみあうのかまったくわからない。そこはわからないが、Javaのどういうコードにはどういう問題があるかということは、ほぼわかる。ただ、上の2重コンストラクタによるJDK1.6以降限定防御のように、JVMの実装によって動作が変わるか、あるいは定義が異なる可能性があるものについては、DALVIKには通用しないと思う(が、そういうJDK特定しているのは例外的だ)。

Javaセキュアコーディングスタンダード CERT/ Oracle版(Fred Long/Dhruv Mohindra/Robert C. Seacord/Dean F. Sutherland/David Svoboda/歌代和正/久保正樹/戸田洋三)

おそらく、CERTという点からは本書の読者は普通のサーバーサイドJ2EE開発者ではないと思う。むしろ、デバイス上の……だからAndroidか。

しかし、読みやすさと簡潔さ、例示の妙もあって、Effective Javaよりも、こちらのほうが得るものは多かった。何より、簡潔で要点を絞った解説が実に読みやすい。セキュアなコードというのは、逆の見方をすれば冗長なコードでもある。本書の書き方からは、3種類の技術を学べる。セキュアなコード、セキュアではないコードを攻撃するためのコード、デバッグやテストのためのコード(2番目と同じ意味だが帽子の色が異なる)だ。相当、お勧めできる。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|

ジェズイットを見習え