このコンポーネントの脆弱性はかなり前に暴露されていましたが、最近仕事中に再び遭遇しました。最近たまたま Java デシリアライゼーションについて読んでいたので、そう決めました。さらなる分析の結果、この期間中にいくつかの奇妙な問題も発生しました。
インターネット上の解析記事の多くは、ysoserial で生成された CommonsCollections2 ペイロードを使用するために、commons-collections4-4.0 の依存関係を手動で追加していますが、私が遭遇した状況では CommonsBeanutils1 が使用されていました。直接成功できるため、ここでは CommonsCollections2 のオンライン分析を繰り返しません。
デバッグ環境:
JDK 1.8.0_72
Tomcat 8.0.30
まず、Shiro のソース コードをクローンして戻し、問題のブランチにカットします。
git clone https://github.com/apache/shiro.git shiro-rootcd shiro-root git checkout 1.2.0
Shiro に付属のサンプルを実行するには、samples/web/pom.xml ファイルにいくつかの変更を加える必要があります。jstl バージョンを 1.2 に変更し、スコープ フィールドを削除する必要があります。サーブレットAPIの。 jstl-1.2.jar を WEB-INF/lib ディレクトリに置きます。その後、実行してデバッグできるようになります。
org.apache.hiro.mgt.DefaultSecurityManager のsolvePrincipals メソッドへのブレークポイントに到達し、rememberMe Cookie を使用してリクエストを送信すると、ブレークできるはずです。
引き続き getRememberedIdentity メソッドに従います:
引き続き getRememberedSerializedIdentity メソッドに従います:
この中でメソッドでは、渡した Cookie が読み取られ、base64 デコードされます:
次に、hiro は ConvertBytesToPrincipals を呼び出し、base64 デコードされたバイト配列をパラメーターとして渡します:
関数名からも推測できます。復号化と逆シリアル化という 2 つの操作が実行されます。まず復号化部分を見てみましょう。簡単なデバッグの後、AES 復号化が行われたことがわかりました。プリセットキーBase64.decode("kPH bIxk5D2deZiIxcaaaA==");。Shiro付属のサンプルではこのキーが他に設定されていないため、ここではこのプリセットキーを使用します。値を設定します。
AES 復号化で検出される IV も、渡した Cookie の最初の数バイトから取得されるため、任意のコンテンツを含む Cookie 値を簡単に構築し、プレーンテキストを復号化できます。これはシリアル化されたコンテンツであり、逆シリアル化します。逆シリアル化のために呼び出されます。
org.apache.hiro.io.DefaultSerializer#deserialize メソッドは、最終的に逆シリアル化のために呼び出されます:
プロセス全体は非常に簡単です。 「Cookie の取得 -> Base64 デコード -> AES 復号化 -> デシリアライゼーション」を読んでください。
したがって、ペイロードの構築は非常に簡単です。完全な PoC を GitHub に置きます。
デバッグ プロセス中にいくつかの問題が発生し、計算機が正常に表示されませんでした。ここに記録しておきます。
私はこの問題を長い間デバッグしていました。ペイロードの問題か、Shiro のコードが時間の経過とともに変更されたのではないかと考えていました。そのときに遭遇したケースは、ペイロードが私の魂に入ってきたというものでしたので、そして私はとても混乱しました。その後、重要な問題が見つかりました。github からクローンしたサンプルでは、commons-beanutils の依存バージョンが 1.8.3 で、ysoserial によって生成されたペイロードのバージョンが 1.9.2 であるため、デフォルトのサンプルです。そこでバージョン番号を 1.9.2 に変更したところ、ヒットしました。
つまり、私たちが遭遇したケースでは、実際の依存環境のバージョンは次のようになる可能性があるため、直接成功できます。
このプロジェクトを複製すると、commons-collections パッケージがあることがわかります:
ysoserial が提供する CommonsCollections1 を使用しようとするとスローされます。例外、成功できません
デバッグ中に、ここでスローされた例外を発見しました。なぜバイト配列を逆シリアル化できないのか非常に混乱しています
Java で Class.forName() と ClassLoader.loadClass() の違いを確認したところ、forName() は常に呼び出し元の ClassLoader() を使用するのに対し、loadClass() は使用できることがわかりました。別の ClassLoader を自分で指定してください。では、hiro の ClasssLoader はどこから来たのでしょうか?これは、Thread.currentThread().getContextClassLoader(); (WebappClassLoader) を通じて取得されます。しかし、バイト配列をロードできないというメッセージが表示されるのはなぜですか? しばらく検索した後、オレンジのブログで以下のディスカッションを見て、すべての真実を学びました:
Shiro resovleClass は ClassLoader を使用していますClass.forName() の代わりに .loadClass() を使用し、ClassLoader.loadClass は配列型クラスのロードをサポートしません。
以上がApache Taro 1.2.4 デシリアライゼーションの脆弱性分析例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。