Stranger Danger:Log4Shellエクスプロイトの仕組みをライブハックで解説
Sarah Wills
2022年1月25日
0 分で読めます2021年末、Log4Shellの脆弱性はJavaコミュニティに衝撃を与えました。多くの組織が、今もその影響を軽減するための対応を続けています。状況の進展に合わせて開発チームが最新情報を把握できるよう、SnykはLog4j脆弱性リソースセンターを開設し、継続的に更新しています。
先日開催されたStranger Dangerのライブハックでは、SnykのフィールドCTOであるSimon Maple、シニアデベロッパーアドボケイトのEric Smalling、DevSecOps AccelerationディレクターのMicah Silvermanが、Log4Shellの脆弱性について解説し、エクスプロイトの仕組みを実演しました。
Log4Shellの要点
Log4Shellは、Log4j2 Javaロギングフレームワークに存在する、広く普及した深刻な脆弱性で、容易に悪用される可能性があります。Log4j2は非常に多くのオープンソースライブラリで使われているため、この脆弱性は多数のJavaアプリケーションに影響を及ぼしました。
「この脆弱性が2013年から潜在していたことからも分かるように、予期しない副作用が生じることがあります」とMicahは語ります。「これはオープンソースプロジェクトの性質のようなものです。」
この脆弱性を修正するには、アプリケーションでLog4j2ライブラリが直接依存関係または間接依存関係として使われている箇所を特定し、バージョン2.17.1にアップグレードする必要があります。これによりLog4Shellの脆弱性だけでなく、その直後に公表されたサービス拒否の脆弱性も軽減できます。
さらに詳しく知りたい方は、Log4Shellの完全な修正ガイドをご覧ください。
Log4Shellの仕組み
2013年、ログメッセージ内の補間文字列を通じてJava Naming Directory Interface(JNDI)参照を利用する機能が、Log4jライブラリに追加されました。補間文字列には、変数、関数呼び出し、その他の解決可能な式を含めることができます。問題は、JNDIがこうした文字列内のURLを検索し、悪意のあるエンドポイントへのネットワーク接続を発生させる可能性があることです。

さらに、認証されていないLDAPサーバーは、JNDIリクエストに対して、リモートのJavaクラスやその他の望ましくないコードへの悪意ある参照を返すことができます。このクラスは、アプリケーションのクラスパス上にない場合でもデシリアライズされ、リモートコード実行(RCE)攻撃につながるおそれがあります。
Log4Shellエクスプロイトのデモ
ライブハックのデモでは、Javaで構築したLog4Shellエクスプロイトのサンプル(GitHubで公開)をTomcatサーバー上で実行します。ログインページで誤ったパスワードを入力すると、アプリケーションから情報がログに記録される旨が通知されます。

「Javaフレームワークやアプリケーションで、エラーや例外が発生したとき、あるいは通常のトランザクションのときにログを記録するのは一般的です」とSimonは説明します。「これにより、さまざまな処理の流れや、ユーザーがサイトをどのように利用しているかを把握できます。」
アプリケーションのコードを見ると、ユーザー名が正しくない場合にLog4jを使ってそのユーザー名をログに記録していることが分かります。ユーザーが入力したデータを後からログに記録するこうしたケースは、Log4Shellの脆弱性が悪用される最も一般的な経路です。

たとえば、ログイン欄に悪意のある文字列を入力し、RCE攻撃の準備をすることができます。まずはPythonのエクスプロイトスクリプトを見てみましょう。このスクリプトの重要な点は、初期化時に新しいソケットを作成し、自分たちのサーバーに接続するJavaクラスを生成することです。

「これは、これから構築するリモートプロキシの一部として機能します」とSimonは説明します。「このクラスはループを継続し、コマンドを受け取り、実行して、接続先のサービスに送り返します。」
悪意のあるサーバー上でJavaファイルを作成してコンパイルし、HTTPサービス経由でアクセスできるようにします。次にLDAPサーバーを作成し、対象アプリケーションのJNDIが悪意のあるJavaクラスを検索するための文字列を返します。
LDAPサーバーとHTTPサーバーを立ち上げれば、エクスプロイトの実行準備はほぼ完了です。Log4Shellの「シェル」部分を実行するため、ネットワークユーティリティのnetcatを使ってリバースプロキシサーバーも設定します。リバースプロキシによってTomcatサーバー上でリモートコマンドを実行できるようになり、アプリケーションとサーバーがさらなる攻撃に対して脆弱な状態になります。
対象アプリケーションのログインページにある入力欄に悪意のある文字列を入力して、エクスプロイトを実行します。この文字列がLog4jによってログに記録されると、ライブラリは補間文字列の解決も試みます。その結果、アプリケーションはJNDIサービスを使ってLDAPサーバーに接続し、HTTPサーバー上にある悪意のあるJavaクラスへの参照を取得して、ローカルで実行します。このJavaクラスがnetcatに接続し、リバースプロキシを作成します。
SnykでLog4Shellを軽減する
前述のとおり、Log4Shellを軽減する最善の方法は、直接依存関係と間接依存関係に含まれるすべてのLog4jを特定し、アップグレードすることです。Snyk Open Sourceは、依存関係を自動スキャンし、Log4Shellのような脆弱性を含むパッケージを検出できます。
Snykプラットフォームはまず、プロジェクト内のすべてのアーティファクトを特定して分類し、スキャン方法を判断します。たとえば、pom.xmlファイルにはソフトウェア構成分析(SCA)スキャンを、Javaファイルには静的アプリケーションセキュリティテスト(SAST)スキャンを実行します。また、コンテナ化されたアプリケーションのInfrastructure as Code(IaC)設定やDockerファイルもスキャンできます。

上記の脆弱なアプリケーションをスキャンした後、依存関係を含むMaven設定ファイルであるpom.xmlのスキャン結果を開くことができます。Snykのインターフェースでは依存関係ツリーも確認でき、アプリケーションがLog4jを直接依存関係と間接依存関係の両方で使用していることが分かります。この脆弱性を修正をクリックすると、SnykがすべてのLog4jをバージョン2.17.1にアップグレードするプルリクエスト(PR)を自動で作成します。先ほどのエクスプロイトを再実行すれば、もう機能しないことを確認できます。

同様に、開発者はIntelliJ(またはその他のIDE)向けのSnykプラグインやSnyk CLIを使って、セキュリティ上の問題をスキャンし、開発中に直接修正できます。Snykは開発プロセス全体にわたって連携し、アプリケーションの脆弱性管理を効率化します。
脆弱なパッケージをすぐにアップグレードできない組織もあります。その場合は、Log4Shellのリスクを軽減する別の方法を検討する必要があります。開発者はJNDIルックアップクラスを削除したり、ほかの暫定的な修正を実装したりできますが、新しいバージョンのライブラリに含まれる公式パッチほど効果的ではありません。
Log4Shellの脆弱性に対してどのような軽減策を選ぶ場合でも、Snykはプロジェクトのオープンソース依存関係やコンテナをスキャンし、Log4jやその他数千もの潜在的な脆弱性を特定できます。これにより組織は、アプリケーションのリスクプロファイルを理解するために必要な可視性を確保できます。
CTFを始めよう
オンデマンドのバーチャル入門ワークショップを視聴して、CTFの課題の解き方を学びましょう。



