FlawOpen

flawopen.com/Incidents/log4shell-jndi-injection-december-2021

● Apache Software Foundation · CVE-2021-44228 · December 2021 · CVSS 10.0 · 緊急
セキュリティ研究 · FlawOpen

Log4Shell(CVE-2021-44228):原因と対策

CVE-2021-44228ではログ内データがLog4j 2のlookupとJNDIクラス読み込みを起動できました。更新し、同梱コピーも洗い出してください。[1], [2], [4]

💡 わかりやすい解説 (ELI5)

訪問者の話を書き留めることだけが仕事の係員がいるオフィスを想像してください。ある人が、訪問者が特定の言葉を口にすると、係員が書くのをやめ、その言葉に出てくる住所へ行き、見知らぬ人から封をした封筒を受け取って、中の指示に従うことに気づきます。係員は書き留めることしか求められていなかったのに。[1]

主要な概念と専門用語

メッセージのルックアップ
ログメッセージ内の ${...} 式を書き込み時に値へ置き換える Log4j 2 の機能。2.15.0 より前は、設定したパターンだけでなくメッセージ内のデータにも適用されていました。[1]
JNDI
Java Naming and Directory Interface。LDAP などのディレクトリサービスからオブジェクトを探す API です。リモートサーバーへの JNDI ルックアップは、JVM に読み込ませるクラスを返し得ました。[1]
式インジェクション(CWE-917)
信頼できないデータが式の評価器に届き、データとして渡した文字列が命令として実行されることです。[1]
推移的依存関係
別のライブラリが必要とするからという理由だけでアプリケーションに含まれるライブラリ。Log4Shell の影響の多くは、誰も把握していなかった Log4j のコピーから生じました。[4]
ソフトウェア部品表(SBOM)
ビルドに含まれるすべてのコンポーネントとバージョンを機械可読で並べた一覧。「Log4j 2.14 はどこで動いているか」にすぐ答えられます。[4], [3]

フレームワーク対応

インシデントのタイムライン

2021-11-24

Alibaba Cloud Security の陳兆軍氏が Apache に非公開で欠陥を報告する。[1]

2021-12-09

欠陥が公になり、Log4j 2.15.0 がリリースされ、数時間のうちに大規模なスキャンが始まる。[1], [4]

2021-12-17

CISA が緊急指令 22-02 を出し、米連邦機関に Log4j の洗い出しと緩和を義務づける。[3]

2021-12-28

Log4j 2.17.1 が CVE-2021-44832 を修正する。2.15.0 の後に続いた 3 件の CVE(ほかに CVE-2021-45046 と CVE-2021-45105)の最後の一つ。[1]

ステップ・バイ・ステップの攻撃フロー

ステップ 1

攻撃者の文字列がログ呼び出しに届く

アプリケーションがログに記録する値、たとえばユーザー名やヘッダー、検索語などに、攻撃者が選んだルックアップ式を含めることができます。[1]

ステップ 2

Log4j が式を評価する

脆弱なバージョンはログに書くデータの中のルックアップを処理するため、式は文字列として書かれずに解決されます。[1], [2]

ステップ 3

JNDI が外部に接続する

JNDI ルックアップにより、サーバーは式で指定されたディレクトリサービスへ接続します。多くの場合、それは攻撃者のインフラです。[1], [4]

ステップ 4

リモートのコードが実行される

リモートのディレクトリは JVM に読み込むクラスを指示でき、そのクラスはアプリケーションの権限で実行されます。外向き接続が遮断されていた環境では、この段階は失敗しました。[1], [2]

ソースコード比較:脆弱 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>

エンジニアリング&システム堅牢化チェックリスト

参考資料