例: Log4Shell のセキュリティ侵害を検出する

Apache Log4j ライブラリ バージョン 2.0~2.15 でセキュリティ上の脆弱性 CVE-2021-44228CVE-2021-45046 が見つかりました。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 セキュリティ アドバイザリをご確認ください。影響の程度を評価するには、米国国立標準技術研究所(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.typeresource.labelslogName などのインデックス フィールドを使用して、クエリを特定のサービスやログストリームのセットに絞り込みます。

一致するログエントリが検出されても、侵害が成功したとは限りません。何かが検出された場合は、組織のインシデント対応プロセスに従って対応することをおすすめします。この一致は、誰かがプロジェクトまたはワークロード内の脆弱性を悪用しようと探っていることを示している可能性があります。また、アプリケーションが HTTP リクエスト フィールドに ${jndi: などのパターンを使用している場合、誤検知になる可能性があります。ログを調べて、このパターンが通常のアプリケーション動作の一部ではないことを確認します。環境に合わせてクエリを調整してください。

不適切な IP アドレスを検索する

一致する結果を検出し、そのようなリクエストを送信したリモート IP アドレスについて集計する場合は、ログ エクスプローラの [ログのフィールド] ペインに remoteIp フィールドを追加します。remoteIp フィールドを追加するには、次のスクリーンショットに示すように、一致するログエントリのフィールド値をクリックして、[Add field to Logs fields pane] を選択します。

[ログフィールド] ペインに「remoteIp」フィールドを追加して、最も一致するリクエストを送信する IP アドレスを特定します。

一致するリクエストを送信した上位のリモート IP アドレスが [ログのフィールド] ペインに表示されます。

ログ エクスプローラに上位のリモート 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 フィールド値をクリックします。次に、[Add field to Logs fields pane] を選択します。

これで、Log4j 2 を悪用する試みのスキャン対象となる上位のアプリケーションやバックエンド サービスを確認できます。悪用の試みがバックエンド サービスまで到達したかどうかを判断するには、HTTP(S) ロードバランサによって入力された jsonPayload.statusDetails フィールドを使用して、リクエストがバックエンドにプロキシされたか、あるいは IAP や Google Cloud Armor などのサービスによって正常にブロックされたかを確認します。ログエントリの結果から jsonPayload.statusDetails フィールド値をクリックし、[Add field to Logs fields pane] を選択します。

これで、[ログのフィールド] ペインで、リクエストがどのように処理されたかを確認できるようになりました。

最も多く対象となったバックエンド サービスがログ エクスプローラに表示されます。

この例では、リクエストの大部分が IAP によってブロックされています。IAP がバックエンド サービスで有効になっている場合、ユーザーの ID を確認し、コンテキストを使用してからアクセスを許可します。これらの IAP でブロックされたリクエストでは、statusDetailshandled_by_identity_aware_proxy に設定されています。また、適切なセキュリティ ポリシーがバックエンド サービスに適用され、Google Cloud Armor を使用している場合、Google Cloud Armor によってブロックされるすべてのリクエストでは statusDetailsdenied_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)か、適切なインシデント対応チームに転送できます。

ログベースのアラートの作成については、ログベースのアラートを作成する(ログ エクスプローラ)をご覧ください。アラートを作成する際は、この例で指定したクエリではなく、攻撃文字列に対するクエリを使用してください。

ログベースの指標にアラート ポリシーを作成する

悪用の可能性をログに記録しているエンドポイントやサービスをモニタリングするには、ログベースの指標にアラート ポリシーを作成します。

  1. ログベースの指標は、ログ内で悪用の可能性を示す文字列の出現回数をカウントするために作成します。たとえば、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)"'
    

    ログベースの指標の作成については、カウンタ指標を構成するをご覧ください。

  2. 選択した回数になると通知するアラート ポリシーを作成します。アラート ポリシーの設定については、カウンタ指標にアラート ポリシーを作成するをご覧ください。

次のステップ