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

セキュリティ上の脆弱性 CVE-2021-44228CVE-2021-45046Apache 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 をご確認ください。ご利用の露出状況を評価するには、CVE-2021-44228 の米国国立標準技術研究所(NIST)の脆弱性レポートをご覧ください。

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 フィールドを追加するには、次のスクリーンショットに示すように、一致するログエントリのフィールド値をクリックして、[ログ フィールド ペインへのフィールドの追加] を選択します。

[ログフィールド] ペインに「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 フィールド値をクリックします。次に、[[ログ フィールド] ペインにフィールドを追加] を選択します。

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

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

対象とされることが最も多いバックエンド サービスがログ エクスプローラに表示されます

この例では、リクエストの大部分が 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. 選択した回数になると通知するアラート ポリシーを作成します。アラート ポリシーの設定については、カウンタ指標でアラート ポリシーを作成するをご覧ください。

次のステップ