そのため、Google App Engine で現在無効になっているリフレクションの制限を数時間回避した後、オブジェクト リフレクションが脅威になり得る理由を誰かが理解するのを手伝ってくれないかと考えていました。クラスのプライベート変数を検査できるからですか、それとももっと深い理由がありますか?
5 に答える
1 - (概念としての) リフレクションは、安全性/セキュリティとは正反対です。
安全なプラットフォームにするための Java の設計には大きな重点が置かれ、静的型付け、セキュリティ マネージャー、クラス ローダーの規律ある使用法、およびポインター/メモリを台無しにする方法はありません。その点について興味深いJames Gosling のインタビューがMasterminds of programmingで読むことができます。
しかし、内省力が強ければ強いほど、物事が本来あるべき安全であることを保証することが難しくなります。リフレクションは特に静的型付けを無効にし、実行時エラーにつながる可能性があります。
しかし、もっと微妙なことが起こる可能性もあります。たとえば、システムのリフレクションフックと見なすことができるクラス ローダーは、初期バージョンの Java では適切に設計されておらず、型の置き換えが発生する可能性がありました。このような問題については、Gilad Bracha による記事「JVM での動的クラスの読み込み」が参考になります。
反射を完全にオフにすることはできません。独自のパブリック フィールド/メソッドを反映することは常に可能です。ただし、カプセル化が壊れるため、プライベート構造へのリフレクションはAccessibleObject.setAccessible
無効にすることができます。プライベートフィールド等へのアクセスにより、内部データの閲覧・修正が可能です。さまざまな悪意のある悪用につながる可能性があります。
strings
もはや不変ではなく、変更することができます (この質問を参照してください)- あなたが所有していないオブジェクトの賢明な情報を明らかにすることができます
- ... その他のエクスプロイト ...
最後に、セキュリティを危険にさらすメカニズムが他にもあります。特にsun.misc.Unsafe
、メモリへの直接アクセスを可能にするものです。ポインタが戻ってきました。
2 - さて、問題は、(実際に)反省がそれほど多くのリスクにつながるかどうかです。
@dpyrneが指すリンクを読みましたが、ほとんどが .net に関するものです。また、Google アプリで何が無効になっているのか正確にはわかりません。それはReflectPermission
セキュリティ マネージャの唯一の許可ですか、それとも他の許可ですか? 1 つの危険は、明らかにファイル システムにアクセスして、いじり回すことです。
プライベート データへのアクセスとカプセル化の解除の問題は、実際に議論することができます。安全なコードを書くことは確かに非常に困難であり、アクセス修飾子を変更しなくても、不適切な方法でクラスをサブクラス化することができますfinal
。これは、たとえば防御コピーが防御しようとするものです。
いずれにせよ、型安全性はダウンキャストによる実行時エラーによって脅かされるため、この点についても議論することができます。
共有/ホスト環境では、セキュリティは相対的です。言語レベルでは、たとえば、モジュール形式が CPU を 100% 消費したり、OutOfMemoryException
. このような問題は、通常は仮想化とクォータを使用して、OS レベルで別の手段で対処する必要があります。
したがって、私の個人的な答えは次のとおりです。リフレクションはセキュリティ上のリスクですが、他の潜在的な攻撃ベクトルと比較すると、実際にはそれほど大きくはありません。
GAE は共有ホスティング環境であり、複数のユーザーからの WAR ファイルをホストします。複数の WAR ファイルが同じ JVM でホストされている可能性が高いです。WAR ごとにプロセスを生成するのはばかげているからです。したがって、各 war ファイルをサンドボックス化する唯一の方法は、各 WAR ファイルのカスタム クラスローダーを使用することです。
ここで、反射が許可されたとします。次に、クラスローダー階層をたどって、さまざまなユーザーに属する WAR ファイルからクラス/メソッドを列挙できます。明らかに、それは大きな懸念事項です。
アプリケーションは Java リフレクション API を使用して、フィールドにアクセスして更新し、通常の Java アクセス/可視性ルールでは禁止されているメソッドを実行できます。少し工夫すれば、これで十分です。
- 隠されているはずの情報にアクセスし、
- Java セキュリティ サンドボックスを破壊して、JVM で実行されている他のものを妨害したり、ローカル マシン上のファイルにアクセスしたりできるようにします。
特定の状況下では、悪意のあるネイティブ コードの挿入を許可することさえあります。
まず、をインストールしていない場合は、SecurityManager
とにかく安全ではありません。
第 2 に、リフレクションが有効にされていない限り、重大な穴を開けることはなくsetAccessible()
、それ自体がセキュリティ チェックの対象となります (setAccessChecks
リフレクション許可によって管理されます)。それがなければ、private フィールドまたはメソッドが存在することを知ることができるかもしれませんが (それ自体にはaccessDeclaredMembers
runtime パーミッションが必要ですが)、その知識では何もできません。攻撃するための最善の策は、シリアル化されたオブジェクトを操作することかもしれませんが、それはまったくの「ろうの玉」です。
また、安全なセキュリティ マネージャとクラス ローダーを作成するのは簡単ではないことにも注意してください。あなたがメガグルダムを熱望していない場合(または、恥ずかしいレベルの失敗の可能性が高い場合)、それらを他の人に任せるのが最善です。
私の理論では、Google は何かを隠そうとしているというものです。Reflectionを無効にすること で、Google は変数名、関数呼び出し、さらには完全な API を隠すことができました。Google が API のようなものを隠している場合、Google は確実にそれについて教えてくれません。
リフレクションがセキュリティ テストで非常に重要な役割を果たしているという事実を私は知っています。たとえば、リフレクションを使用して Fuzz テストを自動的に生成できます。AxManは TypeLib を使用して、COM オブジェクトを構成するすべてのクラスとそのメソッド呼び出しを識別します。この情報を使用して、AxMan は各クラスをインスタンス化し、長い文字列と大きな数値の順列ですべてのメソッドを呼び出します。リフレクションに WSDL ファイルを使用して、SOAP Fuzzerによって同様のテストが行われます。