41

効果的なjavaは言う:

//潜在的なセキュリティホール!

static public final Thing [] VALUES = {...};

誰かがセキュリティホールとは何か教えてもらえますか?

4

8 に答える 8

57

フィールドの宣言static final publicは通常、クラス定数の特徴です。プリミティブ型(ints、doublesなど)や、文字列や。などの不変クラスにはまったく問題ありませんjava.awt.Color。配列の場合、問題は、配列参照が一定であっても、配列の要素を変更できることです。また、フィールドであるため、変更は保護されておらず、制御されておらず、通常は歓迎されません。

これに対抗するために、配列フィールドの可視性をプライベートまたはパッケージプライベートに制限できるため、疑わしい変更を探すときに考慮すべきコードの本体が少なくなります。あるいは、多くの場合、配列を一緒に廃止して、「リスト」または他の適切なコレクションタイプを使用することをお勧めします。コレクションを使用すると、すべての更新がメソッドを経由するため、更新を許可するかどうかを制御できます。を使用してコレクションをラップすることにより、更新を防ぐことができますCollections.unmodifiableList()。ただし、コレクションが不変であっても、コレクションに格納されている型も不変であることを確認する必要があります。そうしないと、想定される定数に対する一方的な変更のリスクが再び発生します。

于 2010-05-16T00:18:39.577 に答える
46

これが潜在的なセキュリティホールであり、カプセル化が不十分であるだけではない理由を理解するには、次の例を検討してください。

public class SafeSites {
    // a trusted class with permission to create network connections
    public static final String[] ALLOWED_URLS = new String[] {
        "http://amazon.com", "http://cnn.com"};

    // this method allows untrusted code to connect to allowed sites (only)
    public static void doRequest(String url) {
        for (String allowed : ALLOWED_URLS) {
            if (url.equals(allowed)) {
                 // send a request ...
            }
        }
    }
}

public class Untrusted {
     // An untrusted class that is executed in a security sandbox.

     public void naughtyBoy() {
         SafeSites.ALLOWED_URLS[0] = "http://myporn.com";
         SafeSites.doRequest("http://myporn.com");
     }
}

ご覧のとおり、final配列を誤って使用すると、信頼できないコードが、信頼できるコード/サンドボックスが課そうとしている制限を覆す可能性があります。この場合、これは明らかにセキュリティの問題です。

コードがセキュリティクリティカルなアプリケーションの一部でない場合は、この問題を無視できます。しかし、IMOこれは悪い考えです。将来のある時点で、あなた(または他の誰か)がセキュリティが懸念される状況でコードを再利用する可能性があります。とにかく、これが作者がパブリックファイナルアレイをセキュリティ問題と呼ぶ理由です。


琥珀はコメントでこれを言いました:

ソースコードやバイトコードをどちらの方法でも読み取ることができれば、プライベート以上のセキュリティホールはありません...

本当じゃない。

「悪者」がソースコード/バイトコードを使用して、privateが存在し、配列を参照していると判断できるという事実は、セキュリティを破るのに十分ではありません。悪者はまた、リフレクションを使用するために必要な権限を持つJVMにコードを挿入する必要があります。この権限は、(適切に実装された)セキュリティサンドボックスで実行されている信頼できないコードには使用できません。

于 2010-05-16T02:46:01.643 に答える
16

ゼロ以外の長さの配列は常に可変であるため、クラスがパブリック静的最終配列フィールド、またはそのようなフィールドを返すアクセサーを持つことは誤りであることに注意してください。 クラスにそのようなフィールドまたはアクセサーがある場合、クライアントは配列の内容を変更できます。

-効果的なJava、第2版。(70ページ)

于 2010-05-16T00:19:58.767 に答える
2

外部クラスは配列の内容を変更できますが、これはおそらくクラスのユーザーに実行させたいことではありません(メソッドを介して実行させたい)。作者がセキュリティではなくカプセル化に違反していることを意味しているようです。

この行を宣言している人は、finalとしてマークされているため、他のクラスは配列の内容を変更できないと思うかもしれませんが、これは正しくありません。finalは、属性の再割り当てを停止するだけです。

于 2010-05-16T00:23:18.313 に答える
1

この宣言では、クライアントはThing [0]、Thing [1]など(つまり、配列内の要素)を変更できます。

于 2010-05-16T00:21:49.137 に答える
0

それは単に公的ものと私的なもの全体を意味すると考えてください。ローカル変数をプライベートとして宣言してから、直接アクセスするのではなく、getメソッドとsetメソッドを使用することをお勧めします。プログラムの外部でそれらを混乱させるのを少し難しくします。私の知る限りそれについて。

于 2010-05-16T00:17:07.063 に答える
0

なぜなら、finalキーワードは参照値のみを保証し(たとえば、メモリの場所として想定)、その中のコンテンツは保証しないからです。

于 2010-05-16T01:44:58.017 に答える