CVE-2022-43484について

本ドキュメントは、TERASOLUNA フレームワークユーザの皆様に、CVE-2022-43484に関する情報提供を行う目的で公開するものです。 本ドキュメントの内容を参考に各システムにおける対策立案を行ってください。

本脆弱性の概要

本脆弱性はクラスローダマニピュレーション(クラスローダを操作可能な脆弱性)であり、これを利用した攻撃方法や影響は実行環境によって異なります。

APサーバがTomcatである場合、リモートコード実行(RCE)が可能であることが確認されています。これ以外のAPサーバにおける影響は明確ではありませんが、クラスローダマニピュレーションはAPサーバの種類に関係なく可能であるため、Tomcat以外のAPサーバにおいても何らかの攻撃を受ける可能性があります。

本脆弱性はCVE-2022-22965(Spring4Shell)と同様のものですが、特定のSpringのバージョンの範囲では、利用するJDKのバージョンに関係なく本脆弱性を利用した攻撃が可能である点に注意が必要です。

本脆弱性の影響範囲

本脆弱性は、Spring 3.2.6よりも古いバージョンを利用する、以下のTERASOLUNA フレームワークのバージョンで影響を受ける可能性があります。

  • TERASOLUNA Global Framework 1.0.0(Public review version)
  • TERASOLUNA Server Framework for Java(Rich版) 2.0.5.1以下のすべてのバージョン

本ドキュメントでは、TERASOLUNA Server Framework for Java(Rich版) に関する内容を記載します。TERASOLUNA Global Framework 1.0.0(Public review version) については、

をご確認ください。

TERASOLUNA Server Framework for Java(Rich版) 2.0.5.1以下をご利用の場合は、アプリケーションの実装に依存して、影響の有無が決定します。

Server Framework for Java(Rich版)2.x における影響有無について

Server Framework for Java(Rich版)2.x では、Controllerごとに入力電文の形式(XML形式 or クエリ形式)を指定でき、どちらを使用しているかによって、影響有無が決定します。

  • XML形式のリクエストを受け付けるControllerのみを定義している場合、本脆弱性の影響は受けません
  • クエリ形式のリクエストを受け付けるControllerを定義している場合、本脆弱性の影響を受けます

なお、機能説明書に記載の方法でファイルアップロードを利用している場合は、「クエリ形式のリクエストを受け付けるControllerをBean定義している場合」に該当します。

Server Framework for Java(Rich版)2.x における影響有無の確認方法

クエリ形式のリクエストを受け付けるのか、XML形式のリクエストを受け付けるのかは、 TerasolunaControllerのサブクラス(BLogicControllerを含む)のdataBinderCreatorプロパティにDIされるServletRequestDataBinderCreator実装クラスが

  • QueryServletRequestDataBinderCreator
    • リクエストパラメータをオブジェクトにバインドする、SpringのServletRequestDataBinder(本脆弱性の影響有)を生成するクラス
  • XMLServletRequestDataBinderCreator
    • リクエストボディのXMLの内容をオブジェクトにバインドする(リクエストパラメータはバインドしない)、TERASOLUNAのXMLServletRequestDataBinder(本脆弱性の影響無)を生成するクラス

のどちらであるかによって決定されます。

ブランクプロジェクトのblank-servlet.xmlの記載を変更していない場合は、

  • クエリ形式のリクエストを受け付けるためのControllerのBean定義の親となる抽象Bean定義には、そのBean IDに「QueryRequest」を、
  • XML形式のリクエストを受け付けるためのControllerのBean定義の親となる抽象Bean定義には、そのBean IDに「XmlRequest」を、

それぞれ含めているため、

ControllerのBean定義(通常、Controllerのbean要素のname属性の値は「/~Controller」となります)の中に、parent属性が「~QueryRequest~」に該当するものがあれば、影響有と判断できます。

parentのBean ID以外で確認する方法としては、ControllerのBean定義のparentを辿っていき、dataBinderCreatorプロパティにDIされているものを確認する方法があります。

dataBinderCreatorプロパティにDIされているものを確認する方法の例

ControllerのBean定義でparent="pojoQueryRequestVelocityViewController"となっている。(このbeanではdataBinderCreatorプロパティは設定されていない)
↓parentを辿る
pojoQueryRequestVelocityViewController(このbeanではdataBinderCreatorプロパティは設定されていない)
↓parentを辿る
pojoQueryRequestController(このbeanでdataBinderCreatorプロパティが設定されている <property name="dataBinderCreator" ref="queryDataBinderCreator"/>)
↓dataBinderCreatorプロパティにDIされているもの(この例では「queryDataBinderCreator」)のBean定義を確認する。
<bean id="queryDataBinderCreator" class="jp.co.nttdata.terasoluna.fw.web.rich.springmvc.bind.creator.QueryServletRequestDataBinderCreator"/>
⇒TerasolunaControllerのサブクラス(BLogicControllerを含む)のdataBinderCreatorプロパティにはQueryServletRequestDataBinderCreatorがDIされている(影響有)。

なお、ブランクプロジェクトには、動作確認用のControllerとして、

  1. <bean name="/testController"
  2. class="org.springframework.web.servlet.mvc.SimpleFormController">
  3. <property name="commandClass" value="java.lang.Object"/>
  4. <property name="successView" value="success"/>
  5. </bean>

が定義されています。

TERASOLUNAのRich版を利用するアプリの実装時には使用しないController(TerasolunaControllerのサブクラスでもない)ですが、 上記の定義通りであれば、削除せずにアプリケーションに残されていても、本脆弱性の影響は受けません。

SpringのSimpleFormController自体はリクエストパラメータのバインディングにSpring MVCの機構を利用するため、影響を受けるControllerですが、 commandClass(リクエストパラメータのバインド先)がjava.lang.Objectであり、 java.lang.Objectのクラスローダ(ブートストラップクラスローダ)はJavaアプリケーションで取得しようとしてもnullが返却される仕様であるため、 本脆弱性の本質であるクラスローダマニピュレーション自体が不可能となります。

本脆弱性の対策方法

本脆弱性は、以下のいずれかの方法で対処可能です。

  • フレームワークのバージョンアップ
  • 原因となるパラメータやリクエストの無視・遮断(ワークアラウンド)

フレームワークのバージョンアップ

以下のバージョンアップを行うことで対処可能です。可能な限りこちらの方法を採用することを検討してください。

  • TERASOLUNA Server Framework for Java(Rich版)2.0.5.1以下を利用している場合
    • TERASOLUNA Server Framework for Java(Rich版)2.0.6.1(Spring Framework 3.2.13を利用)以降にアップデートする
      • JDK9以降(非対応JDK)で運用している場合は、後述の「原因となるパラメータやリクエストの無視・遮断(ワークアラウンド)」も必ず併せてお読みください。

TERASOLUNA Server Framework for Java(Rich版) 2.x のバージョンアップ方法

https://osdn.net/projects/terasoluna/releases/p7128 で公開している、「terasoluna-server4jrich-doc_2.0.x.x.zip」に同梱された移行ガイドをご参照下さい。「terasoluna-server4jrich-doc_2.0.x.x.zip」が無い、または、移行ガイドが同梱されていないバージョンにつきましては、ブランクプロジェクトの差分適用以外、追加の手順はございません。

原因となるパラメータやリクエストの無視・遮断(ワークアラウンド)

バージョンアップが行えない場合、名前が

  • class.~
  • Class.~
  • ~.class.~
  • ~.Class.~

に該当するパラメータをすべて無視するか、上記のいずれかのパラメータを持つリクエストを遮断することで本脆弱性の影響を回避することができます。

これは、CVE-2022-22965に対するものと同様であり、CVE-2022-22965の対応として上記の対策を行っている場合は本脆弱性への対処は不要です。 ただし、本脆弱性はCVE-2022-22965と異なり、JDKに関係なく影響を受けるため、JDK8以前へのバージョンダウンは本脆弱性への対処にはならないことに注意してください。

また、TERASOLUNA Server Framework for Java(Rich版) 2.0.x.x については、JDK9以降には対応していませんが、もしも、JDK9以降で運用している場合は、本脆弱性の影響を受けない TERASOLUNA Server Framework for Java(Rich版) 2.0.6.1 以降であっても、CVE-2022-22965への対処(後述の本脆弱性の対策と同じ方法)が必要となるため、ご注意ください。

なお、原因となるパラメータやリクエストを無視・遮断する方針には、以下のようなものが考えられます。以降では、これらの具体的な実現方法について記載します。

  • WAF(ウェブアプリケーションファイアウォール)を利用して対策する
  • アプリケーションの実装で対策する
  • Tomcatをバージョンアップする(暫定対処)

WAF(ウェブアプリケーションファイアウォール)を利用して対策する

上記のいずれかのパラメータを持つリクエストを遮断するよう設定してください。実際の設定方法は製品ごとに異なるため、ベンダにお問い合わせください。

アプリケーションの実装で対策する

TERASOLUNA Server Framework for Java(Rich版)2.xのアプリケーションで対策を行う場合

QueryServletRequestDataBinderCreatorを以下のように拡張することで、対策可能です。

TERASOLUNA Server Framework for Java(Rich版)2.x は、Spring MVCの古いアーキテクチャで動作しているため、 https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement に記載されているような、ControllerAdviceを利用する方法は使用できません。代わりに、TERASOLUNA Server Framework for Java(Rich版) 2.x に設けている拡張ポイントを利用して、DataBinderのsetDisallowedFieldsメソッドを実行します。

対策用ServletRequestDataBinderCreatorクラスの実装例

  1. package xxx;
  2. import javax.servlet.http.HttpServletRequest;
  3. import org.springframework.web.bind.ServletRequestDataBinder;
  4. import jp.terasoluna.fw.web.rich.springmvc.bind.creator.QueryServletRequestDataBinderCreator;
  5. public class QueryServletRequestSecureDataBinderCreator extends QueryServletRequestDataBinderCreator {
  6. @Override
  7. public ServletRequestDataBinder create(HttpServletRequest request, Object command, String requestName) {
  8. ServletRequestDataBinder dataBinder = super.create(request, command, requestName);
  9. String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
  10. dataBinder.setDisallowedFields(denylist);
  11. return dataBinder;
  12. }
  13. }

DataBinder(ServletRequestDataBinder)のsetDisallowedFieldsをアプリケーション内で既に使用している場合、上記の方法では、対策が取り消される可能性があるため、無視するパラメータのパターン(setDisallowedFieldsの引数)に、"class.*", "Class.*", "*.class.*", "*.Class.*" をマージするよう対策を行ってください。

対策用ServletRequestDataBinderCreatorクラスを有効にするには、以下のようにBean定義を修正します。

対策用ServletRequestDataBinderCreatorクラスの適用方法(xxx-servlet.xml)

  1. <!-- クエリ形式データバインダ生成クラス 修正前-->
  2. <bean id="queryDataBinderCreator"
  3. class="jp.terasoluna.fw.web.rich.springmvc.bind.creator.QueryServletRequestDataBinderCreator"/>
  4. <!-- クエリ形式データバインダ生成クラス 修正後-->
  5. <bean id="queryDataBinderCreator"
  6. class="xxx.QueryServletRequestSecureDataBinderCreator"/>

既にQueryServletRequestDataBinderCreatorを拡張している場合は、既存の拡張クラスの方に、上記の内容(DataBinderのsetDisallowedFieldsメソッドの呼び出し)をマージしてください。

対策が有効になっているかについては、ServletRequestDataBinderCreatorによる対策を行った後、org.springframework.validation.DataBinderのデバッグログが出力されるよう設定した状態で、疑似的な攻撃を行うことで確認することができます。

DataBinderのデバッグログを出力するためにlog4j.propertiesに追加する設定

log4j.category.org.springframework.validation.DataBinder=DEBUG

疑似的な攻撃用パラメータ

・class.a=a
・Class.b=b
・x.class.c=c
・x.Class.d=d

クエリ形式のリクエストを受け付けているControllerにリクエストを送信する際、上記の4つのパラメータを付与してください。

リクエスト電文の送り先のURLが~/secure/blogic.doであれば、その後ろに以下のようなクエリ文字列を付与してください。

付与するクエリ文字列

?class.a=a&Class.b=b&x.class.c=c&x.Class.d=d

既にクエリ文字列がある場合は先頭の「?」を「&」に置き換えて連結してください。

上記の疑似的な攻撃用パラメータによる攻撃を行い、以下のようなログが出力される場合、対策が有効になっています。

疑似的な攻撃用パラメータによる攻撃を防いだ際に出力される、DataBinderのデバッグログの例(メッセージ部分のみ抜粋)

~Field [Class.b] has been removed from PropertyValues and will not be bound, because it has not been found in the list of allowed fields
~Field [class.a] has been removed from PropertyValues and will not be bound, because it has not been found in the list of allowed fields
~Field [x.Class.d] has been removed from PropertyValues and will not be bound, because it has not been found in the list of allowed fields
~Field [x.class.c] has been removed from PropertyValues and will not be bound, because it has not been found in the list of allowed fields

順不同で、すべてのログが出力されていることを確認してください。 疑似攻撃を誤っていないにも関わらず、1つでも出力されていないログがある場合、対策誤りにより対策漏れがある状態です。

Tomcatをバージョンアップする(暫定対処)

本脆弱性と類似した脆弱性である、CVE-2022-22965 のPoCとして、WebアプリケーションがTomcat上で動作している場合にリモートコード実行が可能となる攻撃例が知られています。このPoCによる攻撃を成立させないようにTomcat側で対策されたものがTomcatの開発元であるApacheから提供されています。

Tomcat側で取られた対策は本脆弱性に対しても有効であるためTomcatを9.0.62 もしくは 8.5.78にバージョンアップすることでPoCに準ずる攻撃への対策が可能です。なお、Tomcat 10.0.20 でも同様の対策が行われていますが、少なくともTERASOLUNA Server Framework for Java 5.7.xまでは、Tomcat 10では動作しない点に注意してください。

Tomcatをバージョンアップする対応は特にEOLとなっている旧バージョンのSpring Frameworkを使用している場合には回避策の一つとなり得ますが、 本脆弱性の根本的な原因を修正したものではなく、今後別の攻撃手法が公開される可能性も否定できないため、あくまで一時的な回避策であることにご留意ください。

Tomcatバージョンアップによる対策は、以下のような条件をすべて満たす場合における暫定対処として実施することをおすすめします。

  • この回避策以外に記載している、いずれの回避策もすぐには実施できない
  • その間システムを停止することができない
  • Tomcatを使用している(直ちに攻撃を受ける可能性がある)
  • Tomcatのバージョンアップであればすぐに実施できる