本プロジェクトは、Spring Framework CVE-2022-22965、すなわち Spring4Shell 脆弱性の影響条件、リスクの顕在化、修正方法、修正後の再テスト手順を学習・検証するためのものです。
プロジェクトは個人が構築したローカルの許可環境で実施しました。プロジェクトの重点は実際の標的への攻撃ではなく、修正前・修正後の Spring MVC テスト環境を構築し、脆弱性に関する影響条件を項目ごとに確認し、安全かつ制御可能な読み取り専用の方法で、Spring データバインディングの内部プロパティパスがバージョンアップグレード前後でどのように異なるかを観察することです。
本プロジェクトでは以下のプロセスを実施しました。
本プロジェクトは、個人のローカル自前環境、または明確に許可されたセキュリティテスト環境のみを対象としています。
本プロジェクトは、いかなる公開ウェブサイト、サーバー、第三者業務システムに対するスキャン、プロービング、脆弱性悪用も行わず、実在のユーザーデータや実在の業務データも含みません。
テスト中に以下の操作は実行していません。
本プロジェクトのテスト手法を、許可されていない対象に対して使用することを禁止します。
CVE-2022-22965 は一般に Spring4Shell と呼ばれ、Spring Framework のリクエストパラメータデータバインディング機構に関連するリモートコード実行脆弱性です。
Spring MVC は、HTTP リクエストパラメータを Java オブジェクトのプロパティに自動的にバインドすることをサポートしています。例えば、本プロジェクトでは以下の方法で名前とメールアドレスのパラメータを受け取ります。
@ModelAttribute("profile") UserProfile profile
通常、リクエストパラメータ name と email は、プロパティ名に従って UserProfile オブジェクトにバインドされます。
影響を受けるバージョンでは、一部の内部プロパティパスへのアクセス制限が十分に厳格ではありません。JDK 9 以降を使用し、特定の Servlet コンテナ、デプロイ方式、データバインディングの条件を満たす場合、外部リクエストパラメータが通常のビジネスオブジェクトから、Java Class、モジュール、クラスローダー、またはコンテナ関連の内部オブジェクトへとアクセスを続行する可能性があります。
特定の悪用可能な環境では、攻撃者がサーバー設定をさらに変更したり、サーバーファイルに書き込んだりして、リモートコード実行のリスクを生じさせる可能性があります。
本プロジェクトでは完全なリモートコード悪用は実行せず、以下のプロパティパスを用いて安全で読み取り専用の差分診断を行います。
class.module.name
本プロジェクトは、個人のローカル VMware 分離実験環境で実施しました。
127.0.0.1通常機能のテストデータ:
Alice[email protected]セキュリティ診断プロパティパス:
class.module.name
spring4shell-local-verification-lab/
README.md:プロジェクト紹介、テスト方針、検証結果、修正説明docs/:Spring4Shell ローカル影響条件検証・修正・再テストレポートimages/:プロジェクト環境、テストプロセス、再テストのスクリーンショットvulnerable-demo/:Spring Framework 5.3.17 を使用した修正前プロジェクトfixed-demo/:Spring Framework 5.3.18 を使用した修正後プロジェクトnotes/:学習ノートとプロセス記録主なソースコード構成:
config/:Spring MVC 設定クラスとアプリケーション初期化クラスcontroller/:フォーム処理とプロパティパス診断コントローラーmodel/:名前とメールアドレスのパラメータを受け取るための UserProfile クラスWEB-INF/views/:ホームページ、送信結果、診断結果の JSP ページ本プロジェクトでは、修正前と修正後の 2 つの Spring MVC アプリケーションをそれぞれ構築しました。
プロジェクトディレクトリ:
vulnerable-demo
使用バージョン:
Spring Framework 5.3.17
生成される WAR ファイル:
spring4shell-vulnerable-demo.war
アクセスアドレス:
http://127.0.0.1:8080/spring4shell-vulnerable-demo/
診断ページ:
http://127.0.0.1:8080/spring4shell-vulnerable-demo/binding-probe
プロジェクトディレクトリ:
fixed-demo
使用バージョン:
Spring Framework 5.3.18
生成される WAR ファイル:
spring4shell-fixed-demo.war
アクセスアドレス:
http://127.0.0.1:8080/spring4shell-fixed-demo/
診断ページ:
http://127.0.0.1:8080/spring4shell-fixed-demo/binding-probe
テストプロジェクトは、以下の内容を含むシンプルなユーザープロフィールフォームを提供します。
コントローラーは以下の方法でリクエストパラメータを受け取ります。
@ModelAttribute("profile") UserProfile profile
ユーザーが名前とメールアドレスを送信すると、Spring MVC は name と email パラメータを UserProfile オブジェクトに自動的にバインドします。
結果ページはバインドされたオブジェクトを読み取り、ユーザーが送信した名前とメールアドレスを表示します。
この機能は、プロジェクトが正常に動作することを確認し、アプリケーションに有効な Spring MVC リクエストパラメータデータバインディング入口が存在することを証明するために使用します。
本プロジェクトは、「まず通常機能を確認し、次に影響条件を確認し、その後読み取り専用のリスク診断を行い、最後に修正して再テストする」という方針で実施します。
@ModelAttribute を使用してリクエストパラメータを UserProfile オブジェクトにバインドする。BeanWrapper を使用して class.module.name の読み取り専用診断を行う。本プロジェクトでは、以下の影響条件を項目ごとに確認しました。
spring-webmvc コンポーネントが含まれる@ModelAttribute に基づくデータバインディング入口が存在する修正前プロジェクトで実際にデプロイされた Spring 依存関係は以下のとおりです。
spring-beans-5.3.17.jarspring-core-5.3.17.jarspring-web-5.3.17.jarspring-webmvc-5.3.17.jar本プロジェクトでは、Spring Framework のバージョンだけで脆弱性の有無を直接判断するのではなく、JDK、Spring MVC、Tomcat、WAR デプロイ、データバインディング入口を組み合わせて総合的に分析します。
破壊的な脆弱性悪用の実行を避けるため、本プロジェクトでは Spring Framework が提供する BeanWrapper を使用して、以下のプロパティパスを読み取り専用で検査します。
class.module.name
このパスは以下を意味します。
class:現在のビジネスオブジェクトに対応する Java Class オブジェクトにアクセスするmodule:そのクラスが属する Java モジュールにアクセスするname:モジュール名を読み取る診断プロセスでは、プロパティの読み取り可能性チェックとプロパティ値の読み取りメソッドのみを呼び出します。
したがって、この診断は修正前後の内部プロパティパスへのアクセス差異を観察するためだけに使用でき、それ単独でリモートコード実行が達成されたことを証明することはできません。
修正前の環境で使用:
Spring Framework 5.3.17
確認するプロパティパス:
class.module.name
診断結果:
truenulltrue は、現在の環境が通常のビジネスオブジェクトの class プロパティに沿って module.name を引き続き解決できることを示します。
読み取り結果が null なのは、現在の WAR アプリケーションが Java の unnamed モジュールで実行されているためモジュール名が空であり、プロパティパスの読み取りが失敗したことを意味するものではありません。
修正後の環境で使用:
Spring Framework 5.3.18
同じプロパティパスで再診断:
class.module.name
診断結果:
falseNot readable修正前後の結果は明確な対比を示しています。
この結果は、バージョンアップグレード後、元の診断プロパティパスへのアクセスが制限され、修正前に観察されたリスクの顕在化が再発しないことを示しています。
本プロジェクトでは、Spring Framework のバージョンをアップグレードする方法で修正しました。
修正前の設定:
<spring.version>5.3.17</spring.version>
修正後の設定:
<spring.version>5.3.18</spring.version>
修正プロセスでは以下の操作を完了しました。
fixed-demo にコピーする。修正後プロジェクトで実際にデプロイされた Spring 依存関係は以下のとおりです。
spring-beans-5.3.18.jarspring-core-5.3.18.jarspring-web-5.3.18.jarspring-webmvc-5.3.18.jarこの結果は、修正バージョンが再構築され実際にデプロイされたことを証明しており、pom.xml のバージョン番号を変更しただけではないことを示しています。
Spring Framework 5.3.18 にアップグレード後、修正プロジェクトのホームページに再度アクセスし、以下のテストデータを送信しました。
Alice[email protected]送信後も、ページは正常に表示されました。
Alice[email protected]この結果は、バージョンアップグレードがプロジェクト本来の正常なリクエストパラメータバインディングとページ表示機能に影響を与えていないことを示しています。
Spring MVC の自動データバインディング機構は、HTTP リクエストパラメータ名に基づいて Java オブジェクトのプロパティにアクセスできます。
通常の業務パラメータ name と email は、UserProfile 内の対応する通常のプロパティにアクセスするだけです。
しかし、Spring のプロパティアクセス機構は、ドット付きのネストされたプロパティパスもサポートしています。影響を受けるバージョンでは、一部の内部プロパティパスへの制限が十分に厳格ではなく、外部パラメータが特定の環境では通常のビジネスオブジェクトから Java Class、モジュール、クラスローダー、または Servlet コンテナ関連オブジェクトへとアクセスを続行する可能性があります。
内部オブジェクトにサーバー設定やファイルシステムに影響を与えられる書き込み可能なプロパティが存在し、アプリケーションが JDK、Tomcat、WAR デプロイ、データバインディングなどの条件を同時に満たす場合、さらにリモートコード実行のリスクが生じる可能性があります。
この脆弱性は name や email プロパティ自体に問題があるからではなく、また Spring MVC を使用するすべてのプロジェクトが必ず悪用可能というわけでもありません。脆弱性が成立するには、通常、複数の条件が同時に存在する必要があります。
実際の業務システムでは、以下の対策を推奨します。













本プロジェクトは、ローカル分離環境で Spring Framework CVE-2022-22965 の影響条件確認、リスク顕在化の診断、バージョンアップグレードによる修正、修正後の再テストを完了しました。
修正前プロジェクトは Spring Framework 5.3.17 を使用しました。JDK 11、Spring MVC、Apache Tomcat 9.0.60、従来の WAR デプロイ環境において、class.module.name プロパティパスは読み取り可能と判断されました。
修正後プロジェクトは Spring Framework を 5.3.18 にアップグレードしました。同じプロパティパスは読み取り不可になり、同時に名前とメールアドレスの通常のデータバインディング機能は引き続き使用できます。
本プロジェクトでは完全なリモートコード悪用は実行せず、安全で制御可能な読み取り専用の方法で修正前後の差分検証を完了しました。
プロジェクトは以下の能力を重点的に示しています。