セキュリティ上の脆弱性 CVE-2021-44228 と CVE-2021-45046 が Apache Log4j ライブラリ バージョン 2.0 ~ 2.15 で公表されました。Apache Log4j ユーティリティは、リクエストのロギングに広く使用されているコンポーネントです。この脆弱性(Log4Shell とも呼ばれます)により、Apache Log4j バージョン 2.0~2.15 を実行するシステムが侵害される可能性があり、その場合、攻撃者は任意のコードを実行できるようになります。
この脆弱性は、Cloud Logging やサードパーティ アプリケーションからログを収集するために提供されるエージェントには影響しませんが、Log4j 2 を使用している場合はサービスに影響が及ぶ可能性があります。
潜在的な攻撃は、Cloud Logging を使用することで特定できます。このセクションでは、次のことを行う方法について説明します。
- Log Explorer でログを検索して、Log4j 2 の脆弱性を悪用しようとした形跡があるか調査する。
- Google Cloud Armor のセキュリティ ポリシーや Identity-Aware Proxy のアクセス制御などの有効な緩和策が、これらの Log4j 2 の悪用の試みをブロックして、正しく構成され、動作していることを確認します。
- 悪用の可能性があるメッセージがログに書き込まれたときに通知するアラート ポリシーを作成する。
Google Cloud の現在のプロダクトとサービスの評価については、Google Cloud の Log4j 2 Security Advisory をご確認ください。影響の程度を評価するには、米国国立標準技術研究所(NIST)の CVE-2021-44228 に関する脆弱性レポートをご覧ください。
Cloud Logging の検出
Cloud Logging のクエリ結果には、すでにログバケットに保存されていて、ユーザーが指定した保持期限内のログのみが含まれます。ほとんどの Google Cloud サービスでは、デフォルトでログが有効になっていますが、無効になっていたり、除外されているログはクエリに含まれません。環境の可視性を高めるために、環境全体でログを有効にすることをおすすめします。
HTTP(S) ロードバランサを使用している場合、リクエストログを Cloud Logging で使用できるようにするには、ロギングを有効にする必要があります。同様に、Apache や NGINX などのウェブサーバーが VM で実行されているが、Ops エージェントや Logging エージェントがインストールされていない場合も、そうしたログは Cloud Logging 内では利用できません。
ログのクエリを実行する
Log4j 2 の脆弱性を悪用したサービスに対する潜在的な攻撃は、ログ エクスプローラを使用して検出できます。Cloud Logging を使用してサービスに対するリクエストをログに記録している場合は、ユーザー作成コンテンツが含まれる httpRequest
フィールドをチェックして悪用の可能性を確認できます。
httpRequest
フィールドの値には、「${jndi:ldap://
」のような文字列トークンが含まれている可能性がありますが、この脆弱性が悪用される仕組みはさまざまです。たとえば、エスケープや Unicode を使用して検知を回避する方法は数多くあります。次の文字列は、システムを悪用する試みを表す一般的な例を示していますが、変化形の完全なセットではありません。
${jndi: $%7Bjndi: %24%7Bjndi: ${jNdI:ldAp ${jndi:${lower:l}${lower:d}${lower:a}${lower:p}: ${${lower:j}${lower:n}${lower:d}i: ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}: ${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}
ログ エクスプローラでは、クエリを作成して悪用可能ないくつかの文字列をスキャンできます。たとえば、次のクエリは、HTTP(S) ロードバランサ リクエスト ログの httpRequest
フィールドに含まれる文字列 ${jndi:
のさまざまな難読化されたバリエーションに対応しようとするものです。ただ、このクエリで使用されている正規表現は、すべてのバリエーションを検出するものではなく、また、誤検出が発生する可能性もあります。
resource.type="http_load_balancer" httpRequest.requestUrl=~"(?i)(\$|\%24)(\{|\%7b).*j.*n.*d.*i.*(\:|\%3a)" OR httpRequest.userAgent=~"(?i)(\$|\%24)(\{|\%7b).*j.*n.*d.*i.*(\:|\%3a)" OR httpRequest.referer=~"(?i)(\$|\%24)(\{|\%7b).*j.*n.*d.*i.*(\:|\%3a)"
上記のクエリは、resource.type
の値を変更することで、他のサービスのリクエストログのスキャンにも使用できます。
大量のログをスキャンする場合、上記のクエリでは、完了するまでに時間がかかる可能性があります。クエリを高速化するには、resource.type
、resource.labels
、logName
などのインデックス フィールドを使用して、クエリを特定のサービスやログストリームのセットに絞り込みます。
一致するログエントリを検出しても、侵害が成功したとは限りません。何かが検出された場合は、組織のインシデント対応プロセスに沿って対応することをおすすめします。一致は、誰かがプロジェクトまたはワークロード内の脆弱性を悪用しようと探っていることを示している可能性があります。また、アプリケーションが HTTP リクエスト フィールドに ${jndi:
などのパターンを使用している場合、誤検知になる可能性があります。ログを調べて、このパターンが通常のアプリケーション動作の一部ではないことを確認します。ご使用の環境に合うようにクエリを絞り込みます。
不適切な IP アドレスを検索する
一致する結果を検出し、そのようなリクエストを送信したリモート IP アドレスについて集計する場合は、ログ エクスプローラの [ログフィールド] ペインに remoteIp
フィールドを追加します。remoteIp
フィールドを追加するには、次のスクリーンショットに示すように、一致するログエントリのフィールド値をクリックして、[ログ フィールド ペインへのフィールドの追加] を選択します。
一致するリクエストを送信した上位のリモート IP アドレスが [ログフィールド] ペインに表示されます。
これにより、Log4j 2 の脆弱性悪用スキャンの発生元を確認できます。これには、Web Security Scanner など、構成したアプリケーションの脆弱性スキャンツールによる正規のスキャンである場合があります。Security Command Center から Web Security Scanner を使用している場合は、Web Security Scanner で使用される静的 IP アドレス範囲をメモしておきます。
対象のアプリケーションを検索して緩和策を検証する
また、対象のアプリケーションで集計を行い、不正のリクエストが実際にアプリケーションに到達したかどうかを特定することもできます。Google Cloud Armor のセキュリティ ポリシーまたは Identity-Aware Proxy(IAP)のアクセス制御を使用して緩和策を有効にしている場合は、HTTP(S) ロードバランサのログに記録された情報から想定どおりに動作するかどうかも検証できます。
対象のアプリケーションを [ログフィールド] ペインに追加するには、まずログエントリ結果の 1 つを選択して、resource.labels
を展開し、resource.labels.backend_service_name
フィールド値をクリックします。次に、[[ログ フィールド] ペインにフィールドを追加] を選択します。
これで、Log4j 2 の悪用の試みのスキャンの対象となる上位のアプリケーションやバックエンド サービスを確認できます。悪用の試みがバックエンド サービスまで到達したかどうかを判断するには、HTTP(S) ロードバランサによって入力された jsonPayload.statusDetails
フィールドを使用して、リクエストがバックエンドにプロキシされたか、あるいは IAP や Google Cloud Armor などのサービスによって正常にブロックされたかを確認します。ログエントリの結果から jsonPayload.statusDetails
フィールド値をクリックし、[[ログ フィールド] ペインにフィールドを追加] を選択します。
これで、[ログ フィールド] ペインで、リクエストがどのように処理されたかその詳細を確認できるようになりました。
この例では、リクエストの大部分が IAP によってブロックされており、バックエンド サービスで有効になっている場合は、ユーザーの ID を確認し、コンテキストを使用してからアクセスを許可します。これらの IAP でブロックされたリクエストは、statusDetails
が handled_by_identity_aware_proxy
に設定されています。また、適切なセキュリティ ポリシーがバックエンド サービスに接続され、Google Cloud Armor を使用している場合、Google Cloud Armor によってブロックされるすべてのリクエストには statusDetails
が denied_by_security_policy
に設定されます。事前構成された新しい cve-canary
WAF ルールを Google Cloud Armor セキュリティ ポリシーに適用する方法については、Apache Log4j の脆弱性による影響の低減を支援する Google Cloud Armor WAF ルールをご覧ください。
実際にバックエンド サービスに到達することを許可されたリクエストをフィルタリングするには、[ログフィールド] ペインの statusDetails
で [response_sent_by_backend
] を選択します。こうした悪用の試みをブロックするために、これらのバックエンド サービスで IAP を有効にするか、Google Cloud Armor セキュリティ ポリシーを適用して事前構成された cve-canary
WAF ルールを適用することを検討してください。
ログベースのアラートの作成
サービス内で影響を受けるログを検出するクエリを設計すると、そのクエリを使用して、新しいログエントリがクエリに一致したときに通知されるログベースのアラートを作成できます。このアラートは、組織のセキュリティ オペレーション センター(SOC)か、適切なインシデント対応チームに転送できます。
ログベースのアラートの作成については、ログベースのアラートの作成(ログ エクスプローラ)をご覧ください。アラートを作成する際は、この例で指定したクエリではなく、攻撃文字列のクエリを使用してください。
ログベースの指標のアラート ポリシーを作成する
悪用の可能性をログに記録しているエンドポイントやサービスをモニタリングするには、ログベースの指標にアラート ポリシーを作成します。
ログベースの指標は、ログ内で悪用される可能性がある文字列の出現回数をカウントするために作成します。たとえば、Google Cloud CLI を使用して、次のような指標を作成できます。
gcloud logging metrics create log4j_exploits \ --description="Detect log4j exploits" \ --log-filter='httpRequest.requestUrl=~"(?i)(\$|\%24)(\{|\%7b).*j.*n.*d.*i.*(\:|\%3a)" OR httpRequest.userAgent=~"(?i)(\$|\%24)(\{|\%7b).*j.*n.*d.*i.*(\:|\%3a)" OR httpRequest.referer=~"(?i)(\$|\%24)(\{|\%7b).*j.*n.*d.*i.*(\:|\%3a)"'
ログベースの指標の作成については、カウンタ指標の構成をご覧ください。
選択した回数になると通知するアラート ポリシーを作成します。アラート ポリシーの設定については、カウンタ指標でアラート ポリシーを作成するをご覧ください。
次のステップ
新しい情報が利用可能になったときは、このドキュメントをご確認ください。
Log4j 2 の脆弱性と Google Cloud サービスについて詳しくは、以下をご覧ください。