flawopen.com/Incidents/log4shell-jndi-injection-december-2021
Log4Shell(CVE-2021-44228):原因と対策
CVE-2021-44228ではログ内データがLog4j 2のlookupとJNDIクラス読み込みを起動できました。更新し、同梱コピーも洗い出してください。[1], [2], [4]
訪問者の話を書き留めることだけが仕事の係員がいるオフィスを想像してください。ある人が、訪問者が特定の言葉を口にすると、係員が書くのをやめ、その言葉に出てくる住所へ行き、見知らぬ人から封をした封筒を受け取って、中の指示に従うことに気づきます。係員は書き留めることしか求められていなかったのに。[1]
主要な概念と専門用語
メッセージのルックアップ- ログメッセージ内の ${...} 式を書き込み時に値へ置き換える Log4j 2 の機能。2.15.0 より前は、設定したパターンだけでなくメッセージ内のデータにも適用されていました。[1]
JNDI- Java Naming and Directory Interface。LDAP などのディレクトリサービスからオブジェクトを探す API です。リモートサーバーへの JNDI ルックアップは、JVM に読み込ませるクラスを返し得ました。[1]
式インジェクション(CWE-917)- 信頼できないデータが式の評価器に届き、データとして渡した文字列が命令として実行されることです。[1]
推移的依存関係- 別のライブラリが必要とするからという理由だけでアプリケーションに含まれるライブラリ。Log4Shell の影響の多くは、誰も把握していなかった Log4j のコピーから生じました。[4]
フレームワーク対応
- このガイドで説明する弱点の CWE 参照: CWE-20 CWE-502 CWE-917
- D3-OTF 送信トラフィックのフィルタリング — このガイドで説明する送信ネットワークの制限により、サービスまたはホストが接続できる宛先を絞れます。
- CISA KEV — 追加日 2021-12-10 — CVE-2021-44228
インシデントのタイムライン
Alibaba Cloud Security の陳兆軍氏が Apache に非公開で欠陥を報告する。[1]
CISA が緊急指令 22-02 を出し、米連邦機関に Log4j の洗い出しと緩和を義務づける。[3]
Log4j 2.17.1 が CVE-2021-44832 を修正する。2.15.0 の後に続いた 3 件の CVE(ほかに CVE-2021-45046 と CVE-2021-45105)の最後の一つ。[1]
ステップ・バイ・ステップの攻撃フロー
攻撃者の文字列がログ呼び出しに届く
アプリケーションがログに記録する値、たとえばユーザー名やヘッダー、検索語などに、攻撃者が選んだルックアップ式を含めることができます。[1]
ソースコード比較:脆弱 vs 堅牢化
説明用の Maven 設定です。log4j-bom をインポートすると、他のライブラリが持ち込んだコピーも含め、すべての Log4j モジュールが一つの最新バージョンに解決されます。さらに enforcer の規則により、2.17.1 より古い log4j-core が推移的なものも含めて一つでも残っていればビルドが失敗するので、新しい依存関係がこっそり脆弱なコードを持ち込むことはできません。本当の修正は更新です。アプリケーションサーバーから外向きの LDAP と RMI を遮断することは、パッチが遅れた環境でも悪用を断ち切った多層防御でした。
<!-- pom.xml: a direct dependency pinned to a vulnerable release -->
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
<!-- Nothing stops another library from pulling in an older log4j-core transitively. -->
<!-- pom.xml: one version for every Log4j module, and a build that fails on old ones -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-bom</artifactId>
<version>2.24.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>ban-vulnerable-log4j</id>
<goals><goal>enforce</goal></goals>
<configuration>
<rules>
<bannedDependencies>
<searchTransitive>true</searchTransitive>
<excludes>
<exclude>org.apache.logging.log4j:log4j-core:[2.0-beta9,2.17.1)</exclude>
</excludes>
</bannedDependencies>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
エンジニアリング&システム堅牢化チェックリスト
- ✓log4j-core を 2.17.1 以降(Java 7 では 2.12.4、Java 6 では 2.3.2)に更新し、依存関係ツリーのどこかで古いバージョンが解決されるビルドは失敗させる。[1]
- ✓ビルドごとに SBOM を生成して成果物と一緒に保存し、将来の公告を影響するサービスに数分で結びつけられるようにする。[4], [3]
- ✓ソースリポジトリだけでなく、デプロイ済みの成果物もスキャンする。多くの製品で、シェーディングや同梱された JAR が依存関係の一覧から Log4j を隠していた。[4]
- ✓アプリケーションサーバーの外向き通信を既定で拒否する。悪用には任意のホストへの外向きの LDAP、RMI、DNS が必要だった。[4], [3]
- ✓構造的な欠陥が修正されたら後続の CVE を想定し、ベンダーの修正が落ち着くまでインシデントを閉じない。[1]