
log4jのCVE-2021-44228脆弱性に対する汎用回避策
このプロジェクトは、log4j CVE-2021-44228 脆弱性に対する汎用的な回避策を提供します。これは、プロジェクトを再ビルドしたり、log4j-core の jar にパッチを適用するという代替手段を短期的に取れない場合に使用できます。
アイデアは非常にシンプルです。Java ランタイムの "-Xbootclasspath/a" オプションを使って、クラスローダーに JndiLookup クラスの「空の」バージョンを強制的にロードさせます。
したがって、この回避策全体は、この単一のクラス "org.apache.logging.log4j.core.lookup.JndiLookup.java" のみで構成され、他に依存関係はありません。
Maven でコンパイルして jar 化するための利便性のために pom.xml も用意されていますが、お好みの JDK を使って "javac" と "jar" コマンドで同じことを行うこともできます。
この「空の」バージョンの "JndiLookup" クラスは、元の log4j2 実装と互換性を持たせられないことに注意してください。特定のクラスローディング状況で失敗するためです。
回避策を適用すると、次のメッセージが表示されます:
"WARN JNDI lookup class is not available because this JRE does not support JNDI.
JNDI string lookups will not be available, continuing configuration.
Ignoring java.lang.ClassCastException: class org.apache.logging.log4j.core.lookup.JndiLookup"
それでも Log4j2 は問題なく動作し続けます。JNDI ルックアップを使用しないだけです。これで JNDI ルックアップが無効になりました!
クラスをコンパイルして jar ファイルを作成したら、Java コマンドの先頭に "-Xbootclasspath/a:" オプションを追加し、jar ファイルを置いたディレクトリを指定します (例: log4j-workaround-1.0-SNAPSHOT.jar)。これを行う方法の例については、概念実証のセクションを参照してください。
この回避策を適用する Java コマンドは、あらゆるものを起動できます (Weblgic、Tomcat、Spring でビルドされた fat jar など)。
回避策にだけ興味があり、それが本当に機能するかどうかの確認方法には興味がない場合は、以下は無視して構いません。
このアプローチを検証するために、"POC" フォルダを追加しました。そこには別の Maven プロジェクトが含まれています。ユニットテストは使いたくなく、むしろ本番セットアップに近い形、つまり fat jar の明示的なコマンドライン起動や、検証に使用した Tomcat のようなコンテナ起動に近い形を選びました。
概念実証には 2 つのクラスがあります。"POC.java" はコマンドラインで回避策をテストするためのもので、"POCServlet.java" はアプリケーションサーバーで同じことをテストするためのものです。
両方のシナリオで "${jndi:ldap://localhost/test}" をログに記録しようとします。そのため、回避策を適用しない場合、log4j はローカルホスト上の ldap に接続しようとし、connection refused で失敗します。
コマンドラインの POC を実行するには (Maven でビルドした後):
"target\log4j-workaround-1.0-SNAPSHOT\WEB-INF" ディレクトリに移動し、そこで実行します (Windows コマンドラインの場合):
java -Xbootclasspath/a:..\..\..\..\target\log4j-workaround-1.0-SNAPSHOT.jar -classpath classes;lib\* com.github.grimch.log4j_workaround.poc.POC
Tomcat で POC を実行するには:
なぜ "-Xbootclasspath" を使うのか、回避策の jar を「通常の」クラスパスの最初のエントリとして置くだけでは駄目なのか? 一部のコンテナでは、デプロイされたアプリケーションアーカイブ内の jar ファイルがシステムクラスパス内の同じ jar よりも優先されるように、クラスローディングに影響を与えることができます。 一方、ブートストラップクラスパスにあるものは、他のすべてよりも優先されます。
しかし、同じようなものを使用していないことが確実な場合 (例: Weblogic の "prefer-application-packages") は、"-classpath" の代替案も使用できます。