JavaのロギングツールであるApache Log4j 2.x(以下、Log4j 2)に報告された脆弱性「CVE-2021-44228」が大きな波紋を呼んでいる。通称「Log4Shell」とも呼ばれているこの脆弱性は、Log4j 2が動作するJavaアプリケーションに対してリモートの第三者が任意のコードを実行させることができるというもの。その脆弱性の深刻度を表すCVSS v3のベーススコアは最高値の10.0が付けられており、早急に対処する必要がある。そんな中、米国のサイバーセキュリティ企業Cybereasonの研究者が12月10日(米国時間)、この脆弱性に対して緊急的に対策パッチを適用することができるワクチンを公開した。
先に断っておくと、ワクチンと称してはいるものの、これはLog4j 2のプロジェクトから公式にリリースされたものではないため、内容を理解せずに安易に適用することは推奨しない。後述するGitHubリポジトリの免責事項にも、このコードは有志によるものでバグやエラーが含まれている可能性があり、使用することで生じたいかなる損害も補償しないと明記されている。
なお、問題となっているLog4j 2の脆弱性については、次の記事も参照にしていただきたい。
今回Cybereasonが公開した「Logout4Shell」と名付けられたこのワクチンプログラムについては、同社公式ブログの次のエントリで詳しく紹介されている。
また、Logout4Shellのプログラム本体はGitHubの次のリポジトリで公開されている。
Log4j 2の脆弱性は、同ライブラリが提供している「JNDI Lookup」と呼ばれる機能に起因している。この機能を利用すると、外部のサーバからLDAP(Lightweight Directory Access Protocol)などを介して任意のファイルを読み込むことができる。結果として、もし悪意を持った第三者が任意のクラスファイルを自前のLDAPサーバに配置し、そのURLをLog4j 2が動作するサーバに送信した場合、Log4j 2はそれを読み込んで実行してしまう。
2021年12月6日にリリースされた Apache Log4j 2.15.0では、このJNDI Lookupがデフォルトで無効に設定されるようになっており、続いて12月13日にリリースされた2.16.0では機能そのものが削除されている。
一方で、すぐにアップデートが適用できない場合の回避策としては、起動時のJVMオプションまたは環境変数の設定によってJNDI Lookup機能を無効にする方法が提示されている。
CybereasonによるLogout4Shellワクチンは、この設定値の変更を、Log4Shellの脆弱性を悪用して強制的に実施するというものだ。まず、設定値を変更するためのJavaプログラムのクラスファイルを用意して、自前のLDAPサーバ上に配置する。そして、ワクチンを適用したいアプリケーションの脆弱なフィールドに、クラスファイルの場所を表すURLを入力して送信する。ここで言う脆弱なフィールドとは、入力値がログの出力対象になっているフィールドのことで、たとえばユーザIDの入力フィールドなどは多くのケースで該当するだろう。
あとは、アプリケーションがその入力値をログとして出力しようとした際に、URLがクラスファイルに置換されて読み込まれ、設定値が強制的に書き換えられるという仕組みである。
前述の通り、筆者としては安易にこのLogout4Shellワクチンを使用することは推奨しないが、内部の仕組みを理解するための教材としては興味深いコンテンツと言えるだろう。