私のコードが逆シリアル化されたオブジェクトの状態またはクラスについて仮定を行わない場合、信頼できないデータを逆シリアル化しても安全ですか? または逆シリアル化の単なる行為が望ましくない操作を引き起こす可能性がありますか?
(脅威モデル: 攻撃者はシリアル化されたデータを自由に変更できますが、それしかできません)
私のコードが逆シリアル化されたオブジェクトの状態またはクラスについて仮定を行わない場合、信頼できないデータを逆シリアル化しても安全ですか? または逆シリアル化の単なる行為が望ましくない操作を引き起こす可能性がありますか?
(脅威モデル: 攻撃者はシリアル化されたデータを自由に変更できますが、それしかできません)
逆シリアル化自体はすでに安全ではない可能性があります。シリアル化可能なクラスは、このクラスのオブジェクトがストリームから逆シリアル化されるときに呼び出されるreadObject
メソッドを定義できます(仕様も参照)。攻撃者はこのコードを提供することはできませんが、巧妙に細工された入力を使用して、任意の入力でクラスパスにあるそのようなメソッドを呼び出すことができます。readObject
readObject
任意のバイトコード インジェクションへの扉を開く実装を作成することは可能です。ストリームからバイト配列を読み取って and に渡すだけですClassLoader.defineClass
(前者と後者ClassLoader.resolveClass()
については javadoc を参照してください)。そのような実装がどのように使用されるかはわかりませんが、可能です。
安全なreadObject
メソッドを書くのは難しいです。少し最近まで、readObject
メソッドにHashMap
は次の行が含まれていました。
int numBuckets = s.readInt();
table = new Entry[numBuckets];
これにより、攻撃者は数十バイトのシリアル化されたデータに数ギガバイトのメモリを割り当てることが非常に簡単になり、システムがすぐにダウンしてしまいますOutOfMemoryError
。
の現在の実装はHashtable
、同様の攻撃に対して依然として脆弱であるようです。要素の数と負荷係数に基づいて、割り当てられた配列のサイズを計算しますが、 には不当な値に対するガードがないloadFactor
ため、テーブル内の各要素に 10 億個のスロットを割り当てるように簡単に要求できます。
の脆弱性の修正は、HashMap
ハッシュベースのマップに関連する別のセキュリティ問題に対処するための変更の一部として行われました。CVE-2012-2739HashMap
は、非常に多くの衝突するキー (つまり、同じハッシュ値を持つ個別のキー) を作成することによる、CPU 消費に基づくサービス拒否攻撃について説明しています。文書化された攻撃は、URL のクエリ パラメータまたは HTTP POST データのキーに基づいていますが、の逆シリアル化HashMap
もこの攻撃に対して脆弱です。
この種の攻撃を防ぐために導入された保護手段は、キーを持つマップに重点を置いています。これは、HTTP ベースの攻撃を防ぐのに十分ですが、デシリアライゼーションで簡単に回避できます。Java 8 には、多くの衝突に直面した場合の の動作をさらに改善するための提案 ( JEP-180 ) が含まれています。これにより、 を実装するすべてのキー タイプに保護が拡張されますが、それでもキーに基づく攻撃が可能になります。HashMap
String
String
ArrayList
HashMap
Comparable
ArrayList
この結果、攻撃者はバイト ストリームを設計して、このストリームからオブジェクトを逆シリアル化するために必要な CPU の負荷がストリームのサイズに応じて二次的に増加する可能性があります。
逆シリアル化プロセスへの入力を制御することで、攻撃者は任意のreadObject
逆シリアル化メソッドの呼び出しをトリガーできます。このような方法でバイトコード インジェクションを許可することは、理論的には可能です。実際には、この方法でメモリや CPU リソースを簡単に使い果たし、サービス拒否攻撃を引き起こす可能性があります。このような脆弱性に対してシステムを監査することは非常に困難です。サードパーティ ライブラリやランタイム ライブラリを含め、のすべての実装をチェックする必要があります。readObject