32

最近、私のプロジェクトのセキュリティ チームが、コード レビューの一部として使用するように設計された安全なコード ガイドライン ドキュメントをリリースしました。最初に印象に残ったのは、「内部クラスを使用しないでください」という項目でした。これは非常に手荒で抜本的な声明のように思えました。内部クラスは正しく使用すれば良いのですが、少しグーグルで調べたところ、便宜上ここに引用されているthisを見つけました。

ルール 5: 内部クラスを使用しない

一部の Java 言語の本では、内部クラスには、それを囲んでいる外部クラスからのみアクセスできると書かれています。本当じゃない。Java バイト コードには内部クラスの概念がないため、内部クラスはコンパイラによって通常のクラスに変換され、同じパッケージ内の任意のコードにたまたまアクセスできます。また、ルール 4 は、保護のためにパッケージのスコープに依存しないことを示しています。

しかし、待ってください、それは悪化します。内部クラスは、それらのフィールドが非公開と宣言されていても、囲んでいる外部クラスのフィールドにアクセスできます。そして、内部クラスは別のクラスに変換されます。この個別のクラスが外部クラスのフィールドにアクセスできるようにするために、コンパイラはこれらのフィールドをプライベートからパッケージ スコープに暗黙のうちに変更します。内部クラスが公開されるだけでも十分ではありませんが、一部のフィールドを非公開にするという決定をコンパイラが黙って却下するのはさらに悪いことです。できる限り内部クラスを使用しないでください。(皮肉なことに、新しい Java 2 doPrivileged() API の使用ガイドラインでは、内部クラスを使用して特権コードを記述することを提案しています。これが、doPrivileged() API が気に入らない理由の 1 つです。)

私の質問は

  1. この動作は Java 5/6 でもまだ存在しますか?
  2. 外部クラスと内部クラス以外の、外部クラスのプライベート メンバーにアクセスしようとしたクラスがコンパイルされないことを考えると、これは実際にセキュリティ リスクになるのでしょうか?
  3. 「ガイドライン」「内部クラスを使用しない」を保証するのに十分なセキュリティリスクをもたらしますか?
4

10 に答える 10

19

この情報は約 10 年前のものです。での匿名内部クラスの広範な使用がAccessController.doPrivileged手がかりになるはずです。(API が気に入らない場合は、JDK に誤って欠落しているtry-ブロックの割合を考慮してください。)finally

ポリシーでは、2 つのクラスが異なるクラス ローダーによってロードされているか、異なる証明書を持っている場合、同じパッケージを共有することはできません。保護を強化するには、jar のマニフェストでパッケージを封印済みとしてマークします。したがって、セキュリティの観点からは、「ルール 4」は偽物であり、したがってこのルールも同様です。

いずれにせよ、セキュリティ ポリシーを策定する際には、何を保護しているのかを理解する必要があります。これらの種類のポリシーは、さまざまなレベルの信頼を持つ可能性があるモバイル コード (移動するコード) を処理するためのものです。モバイル コードを処理している場合や、必要なライブラリにコードを挿入する場合を除き、この種の予防措置はほとんど意味がありません。ただし、ほとんどの場合、堅牢なプログラミング スタイルを使用することをお勧めします。たとえば、引数や戻り値をコピーして検証するなどです。

于 2009-12-20T11:12:28.623 に答える
9
  1. はい、この動作はまだ存在します。
  2. rogue クラスは標準の javac 以外のもので作成される可能性があるため、セキュリティ上のリスクがあります。
  3. それはあなたがどれだけ偏執的であるかによって異なります:) JVMでエイリアンクラスを実行することを許可しない場合でも、問題はわかりません。そうした場合、より大きな問題が発生します (サンドボックスなど)。
  4. 質問が 3 つしかなかったことは知っていますが、ここにいる他の人たちと同じように、これはばかげた制限だと思います。
于 2009-12-20T10:36:30.090 に答える
6

この動作は Java 5/6 でもまだ存在しますか?

javapツールを使用して、バイナリが何をどのように公開しているかを判断できます。

package demo;
public class SyntheticAccessors {
  private boolean encapsulatedThing;

  class Inner {
    void doSomething() {
      encapsulatedThing = true;
    }
  }
}

上記のコード (Sun Java 6 でコンパイルjavac) は、次のメソッドを に作成しますSyntheticAccessors.class

Compiled from "SyntheticAccessors.java"
public class demo.SyntheticAccessors extends java.lang.Object{
    public demo.SyntheticAccessors();
    static void access$0(demo.SyntheticAccessors, boolean);
}

新しいaccess$0方法に注意してください。

于 2009-12-20T11:23:49.447 に答える
4

コード内のこの種のセキュリティのアイデアは、ちょっとばかげています。コード レベルのセキュリティが必要な場合は、難読化ツールを使用します。@skaffman が上記のコメントで述べたように、「コードの可視性はセキュリティ機能ではありませんでした。リフレクションを使用してプライベート メンバーにもアクセスできます。」.

コンパイルされたコードを難読化せずに配布する場合、内部クラスを使用することは、他の人があなたの秘密をいじるのを心配している場合の最後の心配です。

自分のコードをホストしているのなら、誰かが自分の内部クラスをいじるのを心配するのはなぜですか?

信頼できず、実行時にチェックできないサードパーティのコードをリンクする場合は、サンドボックス化してください。

上で述べたように、これが本当にあなたの会社のポリシーである場合は、あなたの会社をthedailywtf.comに速やかに報告してください。

于 2009-12-20T10:47:15.087 に答える
4

アプリケーションが提供するセキュリティの種類を検討する必要があります。安全なアーキテクチャを備えたアプリケーションは、これらの名前付きの問題に遭遇しません。

ユーザーがコードで行うことを許可されていない場合は、この機能を分離し、サーバー上で実行する必要があります (ユーザーはクラス ファイルにアクセスできません)。

Java クラス ファイルはいつでも逆コンパイルできることに注意してください。そして、「あいまいさによるセキュリティ」に頼らないでください。難読化されたコードであっても、分析、理解、変更することができます。

于 2009-12-20T10:54:27.823 に答える
4

悪意のあるコードは、Java リフレクションを使用して JVM 内の任意の情報にアクセスできますが、これを禁止するセキュリティ マネージャーが設置されている場合を除きます。これには、プライベート フィールドをパブリックに変更することなどが含まれます。

私の個人的な意見では、そうしない理由は他の可能性に圧倒されているため、必要な場合は意味があり、読みやすいので、内部クラスを使用してください。

于 2009-12-20T10:55:59.373 に答える
-1

ナンセンス!同じロジックに従います。パブリック メソッドも作成しないでください。プライベート フィールドにアクセスできるためです。

于 2009-12-20T17:59:26.010 に答える