脆弱性が発見されたApache Log4jとは？公式ページ全訳

# はじめに
Apache Log4jは、Javaベースのログの保存や出力に使われるプログラムです。2021年12月、Apache Log4jに致命的な脆弱性があることが判明しました。Apache Log4jとは何なのかを、公式ページを全訳して調べてみました。
全訳したページは以下です。

https://logging.apache.org/log4j/1.2/

https://logging.apache.org/log4j/2.x/

最後に公式ページに書いてある用語も調べてみました。
# Apache log4j1.2の公式ページ
## サポート終了
2015年8月5日、ロギングサービスプロジェクト管理委員会は、Log4j1.xのサポートが終了したことを発表しました。発表の全文については、[Apacheブログ](http://blogs.apache.org/foundation/entry/apache_logging_services_project_announces)を参照してください。Log4j1のユーザーは、[Apache Log4j2](http://logging.apache.org/log4j/2.x/index.html)にアップグレードすることを強くお勧めします。
## セキュリティ脆弱性
Log4j1に対して、セキュリティ脆弱性である[CVE-2019-17571](https://www.cvedetails.com/cve/CVE-2019-17571/)が確認されました。Log4jには、シリアライズされたログイベントを受け入れ、オブジェクトが許可されているかどうかを確認せずにそれらをデシリアライズするSocketServerが含まれています。これは悪用が可能である攻撃ベクトルを提供します。Log4j1はメンテナンスされなくなったため、この問題は修正されません。ユーザーはLog4j2にアップグレードすることをお勧めします。
## Javaバージョンの非互換性
Java9でバージョン検出アルゴリズムが変更されたため、MDCが正しく機能しなくなりました。詳細については、[Java9でのLog4j1.2の故障](https://blogs.apache.org/logging/entry/moving_on_to_log4j_2)を参照してください。
## Apache log4j 1.2
Java用のロギングライブラリであるApache log4jへようこそ。Apache log4jは、Apacheソフトウェア財団プロジェクトであり、Apacheソフトウェア財団のコミッタの専門チームによって開発されました。詳細については、[Apacheソフトウェア財団](http://www.apache.org/)を参照してください。Apache log4jは、[Apache Logging](http://logging.apache.org/)として知られるプロジェクトの一部でもあります。ライセンスをご覧ください。
最近の変更に興味がある場合は、[変更レポート](https://logging.apache.org/changes-report.html)にアクセスしてください。
## なぜロギングするのか
コードにログステートメントを挿入することは、デバッグのローテクな方法です。デバッガが常に利用可能または適用可能であるとは限らないため、これが唯一の方法である可能性もあります。これは、分散アプリケーションの場合によくあります。
一方で、ログステートメントはソースコードを汚し、可読性を低下させると主張する人もいます。（私たちはその逆が真実であると考えています）。プリプロセッサが使用できないJava言語では、ロギングがオフになっている場合でも、ログステートメントがコードの量を増やし、速度を低下させます。適度なサイズのアプリケーションに数千のログステートメントが含まれる可能性があることを考えると、速度は特に重要です。
## なぜlog4jか
log4jを使用すると、アプリケーションバイナリを変更せずに、実行時にロギングを有効にすることができます。log4jパッケージは、これらのステートメントが大きなパフォーマンスコストを生じさせることなく、送られたコードの中に残すことができるように設計されています。ロギング動作は、アプリケーションバイナリに触れることなく、設定ファイルを編集することで操作できます。
ロギングは、開発者にアプリケーション障害の詳細なコンテキストを提供します。一方、テスト時には、アプリケーションに品質保証と信頼性を提供します。ロギングとテストを混同しないでください。それらは補完的です。ロギングを賢く使用すると、不可欠なツールであることがわかります。
log4jに特有な機能の1つは、ロガーでの継承の概念です。ロガーの階層を使用すると、どのログステートメントがどれだけの細かさで出力されるかを自由に制御できますが、非常に簡単にできます。これは、ログに記録される出力の量とロギングのコストを削減するのに役立ちます。
ログ出力先は、ファイル、OutputStream、java.io.Writer、リモートlog4jサーバー、リモートUnix Syslogデーモン、他の多くを出力先にすることができます。
## パフォーマンス
JDK1.3.1を実行している800MhzでクロックされるAMD Duronでは、ロギングステートメントがロギングすべきかどうかを判断するのに約5ナノ秒かかります。実際のロギングも非常に高速で、SimpleLayoutを使用した場合は21マイクロ秒、TTCCLayoutを使用した場合は37マイクロ秒の範囲です。PatternLayoutのパフォーマンスは、専用レイアウトとほぼ同様です、ただし柔軟性ははるかに高いです。

# Apache Log4j2の公式ページ
Apache Log4j2は前身であるLog4j 1.xを大幅改善したLog4jのアップグレード版であり、Logbackの構造に固有な問題を修正することで、Logbackで利用可能な多くの改良がなされています。
## 重要：セキュリティ脆弱性 CVE-2021-44832
概要：Apache Log4j2は、攻撃者がJDBC Appenderを経由して設定を変更すると、RCE脆弱性が発生します。
### 詳細
ロギング設定ファイルを変更する権限を持つ攻撃者は、JDBC Appenderを使用することで悪意のある設定を構築できるため、Apache Log4j2バージョン2.0-beta7～2.17.0（セキュリティ修正リリース2.3.2および2.12.4を除く）は、リモートコード実行（RCE）攻撃に対して脆弱です。これは、JDBC Appenderがリモートコードを実行できるJNDI URIを参照するデータソースを持つためです。この問題は、Log4j2のバージョン2.17.1、2.12.4、および2.3.2のJavaプロトコルに対して、JNDIデータソース名を制限することで修正されています。
### 軽減策
Log4j 2.3.2（Java 6の場合）、2.12.4（Java 7の場合）、または2.17.1（Java 8以降の場合）にアップグレードします。
## 重要：セキュリティ脆弱性 CVE-2021-45105、CVE-2021-45046、CVE-2021-44228 
これらのセキュリティの問題の詳細と軽減策については、[セキュリティページ](https://logging.apache.org/log4j/2.x/security.html)を参照してください。
## 特徴
### APIの分離
Log4jのAPIは実装から分離しているため、上位互換性を確保しながら使うことのできるクラスとメソッドが、アプリケーション開発者にとって明確になります。これにより、Log4jチームは安全で互換性のある方法で実装の改善ができます。

Log4j APIは、もちろんLog4jの実装で使用できるロギングファサードですが、Logbackなどの他のロギングの実装で使用することもできます。Log4j APIには、SLF4Jに対するいくつかの利点があります。
1. Log4j APIは、単なる文字列でなくロギング[メッセージ](https://logging.apache.org/log4j/2.x/manual/messages.html)をサポートします。 
2. Log4j APIはラムダ式をサポートします。
3. Log4j APIはSLF4Jよりも多くのロギングメソッドを提供します。
4. SLF4Jでサポートされている「パラメーター化されたロギング」形式に加えて、Log4j APIではprintfスタイルのメッセージと同様にjava.text.MessageFormat構文も使用したイベントをサポートします。 
5. Log4j APIは、LogManager.shutdown()メソッドを提供します。基になるロギングの実装では、メソッドが効果を発揮するためにTerminableインタフェースを実装する必要があります。
6. Marker、log Level、ThreadContext（別名、MDC）などの他の構成は完全にサポートされています。

### 改善された性能
Log4j2には、LMAX Disruptorライブラリに基づく次世代非同期ロガーが含まれています。マルチスレッドシナリオでは、非同期ロガーはLog4j 1.xやLogbackよりもスループットが18倍高く、レイテンシーが桁違いに低くなります。詳細については、[非同期ロギングの性能](https://logging.apache.org/log4j/2.x/manual/async.html#Performance)を参照してください。それ以外では、特にマルチスレッドアプリケーションでは、Log4j2はLog4j1.x、Logback、java.util.loggingを大幅に上回ります。詳細については、[性能](https://logging.apache.org/log4j/2.x/performance.html)を参照してください。

### 複数のAPIのサポート
Log4j2 APIはベストパフォーマンスを提供する一方で、Log4j2はLog4j1.2、SLF4J、Commons Logging、java.util.logging (JUL) APIのサポートを提供します。
### ロックインの回避
Log4j2 APIを使って書かれたアプリケーションは、log4j-to-slf4jアダプタのロガー実装としてSLF4J準拠のライブラリを使用するオプションが常にあります。 
### 設定の自動リロード
Logbackと同様に、Log4j2は変更時に設定を自動的にリロードできます。Logbackとは異なり、再設定が行われている間、ログイベントを失うことはありません。 
### 高度なフィルタリング
Logbackと同様に、Log4j2はコンテキストデータ、Marker、正規表現、ログイベントの他のコンポーネントに基づくフィルタリングをサポートします。フィルタリングは、ロガーを通過する前、またはアペンダーを通過するときにすべてのイベントに適用するように指定できます。さらに、フィルタをロガーに関連付けることもできます。Logbackとは異なり、これらの状況のいずれでも共通のフィルタクラスを使用できます。
### プラグインアーキテクチャ
Log4jはコンポーネントの設定のために、プラグインパターンを使用してします。そのため、アペンダ、レイアウト、パターンコンバータなどを作成および設定するためのコードを書く必要はありません。Log4jはプラグインを自動的に認識し、設定が参照するときにプラグインを使用します。
### プロパティサポート
設定内のプロパティを参照することができます。Log4jがプロパティを直接置き換えるか、Log4jが基になるコンポーネントのプロパティを通過するかで、動的に解決します。プロパティは、設定ファイルで定義された値、システムプロパティ、環境変数、ThreadContextマップ、イベントに存在するデータから取得されます。ユーザーは、独自の[ルックアップ](https://logging.apache.org/log4j/2.x/manual/lookups.html)プラグインを追加することにより、プロパティプロバイダをさらにカスタマイズできます。
### Java8 Lambdaサポート
以前は、ログメッセージの作成に費用がかかる場合、メッセージを作成する前に、要求されたログレベルが有効になっているかどうかを明示的に確認することがありました。Java8で実行されているクライアントコードは、Log4jの[ラムダサポート](https://logging.apache.org/log4j/2.x/manual/api.html#LambdaSupport)の恩恵を受けることができます。要求されたログレベルが有効になっていない場合、Log4jはラムダ式の値を求めないため、より少ないコードで同じ効果を達成できます。
### カスタムログレベル
Log4j2では、[カスタムログレベル](https://logging.apache.org/log4j/2.x/manual/customloglevels.html)をコードまたは設定で簡単に定義できます。サブクラス化は必要ありません。
### Log Builder API
Log4j APIの多くのログメソッドの1つを使用することに加えて、ログイベントはビルダーを使用して構築できます。詳細については、[Log Builder](https://logging.apache.org/log4j/2.x/manual/logbuilder.html)を参照してください。
### ゴミフリー（不要データフリー）
定常状態のロギング中、Log4j2はスタンドアロンアプリケーションでは[ゴミフリー](https://logging.apache.org/log4j/2.x/manual/garbagefree.html)（不要データフリー）であり、Webアプリケーションではゴミが少ないです。これにより、不要データ回収の負担が軽減され、応答時間のパフォーマンスが向上します。
### アプリケーションサーバとの統合
バージョン2.10.0では、log4j-appserverモジュールが追加され、Apache TomcatおよびEclipse Jettyとの統合が改善されました。
### クラウド対応
バージョン2.12.0では、ルックアップを介してDockerコンテナ情報にアクセスしたり、Spring Cloud Configurationを通してLog4jの設定にアクセスして更新したりするためのサポートが導入されました。このサポートはバージョン2.13.0で拡張され、Spring BootプロパティやKubernetes情報にアクセスするためのサポートが追加されました。詳細については、[クラウドへのログイン](https://logging.apache.org/log4j/2.x/manual/cloud.html)を参照してください。
### Log4j1.xとの互換性
Log4j2のLog4j-1.2-apiモジュールは、Log4j1のロギングメソッドを使用するアプリケーションに互換性を提供します。Log4j 2.13.0以降、Log4j2はLog4j1.x設定ファイルの実験的なサポートも提供しています。詳細については、[Log4j2とLog4j1との互換性](https://logging.apache.org/log4j/2.x/manual/compatibility.html)を参照してください。
### ドキュメンテーション
Log4j2ユーザーガイドは、この[サイト](https://logging.apache.org/log4j/2.x/manual/index.html)上で、またダウンロード可能な[PDF](https://logging.apache.org/log4j/2.x/log4j-users-guide.pdf)を入手して読むことができます。
### 要件
Log4j 2.13.0以降ではJava8が必要です。バージョン2.4から2.12.1にはJava7が必要でした（Log4jチームはJava7をサポートしなくなりました）。一部の機能にはオプションの依存関係があります。これらの機能のドキュメントには、必要な依存関係が指定されています。
### ニュース
Log4j 2.17.1は次の場所にリリースされました。 
・アドレスCVE-2021-44832
・その他小規模なバグの修正

2.17.1（Java8の場合）は推奨されるアップグレード版です。

Log4j 2.17.1が本番環境で利用できるようになりました。Log4j2のAPIはLog4j1.xと互換性がありませんが、アプリケーションがLog4j1.x APIを引き続き使用できるようにするアダプタを使用できます。アダプタは、Apache Commons Logging、SLF4J、java.util.loggingでも使用できます。

Log4j 2.17.1は、Log4jの最新リリースです。 Log4j 2.13.0以降、Log4j2は実行時にJava8以上を必要とします。このリリースには、最新の[変更レポート](https://logging.apache.org/log4j/2.x/changes-report.html#a2.17.1)に記載されている新機能と修正が含まれています。

Log4j 2.17.1は、以前のリリースとのバイナリ互換性を維持しています。

# 用語解説
## Logback
Log4j の開発者が作った別のロギングライブラリ。

https://qiita.com/opengl-8080/items/49719f2d35171f017aa9

## SLF4J
Javaのロギング実装の柔軟な切り替えを実現するFacadeのこと。

https://qiita.com/NagaokaKenichi/items/9febd2e559331152fcf8

## RCE脆弱性
遠隔から任意のコード実行ができる脆弱性のこと。

https://shinkufencer.hateblo.jp/entry/2019/05/04/000000

## LMAX Disruptor
複数のスレッド間でのデータのやり取りを行うためのプログラム。

https://sitotkfm.hateblo.jp/entry/2015/12/16/235027

https://lmax-exchange.github.io/disruptor/