Claude CodeがSOC業務を全自動でやってくれるってさ

Claude CodeがSOC業務を全自動でやってくれるってさ

はじめに

こんにちは、情報セキュリティ部の兵藤です。日々ZOZOの安全を守るためSOC業務に取り組んでいます。

本記事では、SOCでの業務効率化のためにClaude Codeを活用して、自動アラートトリアージエージェント(以降SOC Agent)を構築した事例を紹介します。

また、情報セキュリティ部ではその他にもZOZOを守るための取り組みを行っています。詳細については以下の「OpenCTIをSplunkに食わせてみた」をご覧ください。

techblog.zozo.com

目次

背景と概要

ZOZOのSOCメンバーは3人体制で、日々大量のセキュリティアラートを処理しています。これらのアラートは、ZOZOTOWNやWEARなどのプロダクトや社内システムのログから生成され、3人で分担して対応するにしては量が多く、負荷がとても高い状況でした。

そこでClaude Codeを活用して、アラートの内容を分析し、優先的に対応すべきアラートを自動で選別するエージェントを構築することにしました。これにより、SOCメンバーは重要なアラートへ集中できるようになり、効率的な対応が可能になると考えました。

また、このSOC AgentのSkillsによってある程度網羅的な調査が可能になるため、SOCメンバーの負荷軽減だけでなく、アラート対応における質の平準化にも寄与しています。

SOC Agentの設計

このAgentが担うのは、初動対応の切り分けです。一般的にはTier1の初動対応に相当します。具体的なレスポンスや即時対応はSOARで行う想定のため、SOC AgentはRead権限で完結する設計にしています。

Agentの全体像

SOC Agentは以下のようなフロー設計で構築しました。

SOC Agentの全体像

  • SOCアナリストの指示、またはSlackのアラート通知のもと、Claude Codeが動作
  • Splunk MCPを通じ、アラートデータや詳細なログデータを取得
  • ZOZOで活用している脅威インテリジェンスプラットフォーム(TIP)であるOpenCTIから、脅威インテリジェンスを取得
  • 取得した情報をもとに、SOC Agentがアラートの優先度を評価し、対応案を検討
  • レポートを生成し、Slackに対応サマリを投稿
  • Slackに対する起動は定期実行も可能で、未処理アラートを自動検知して対応サマリを投稿

Splunk MCPの活用

SOC AgentはSplunk MCPを活用して、アラートデータや詳細なログデータを取得しています。Splunk MCPを活用する際、Splunk Cloudにはレガシーなエンドポイントも存在します。ただし、オンプレミスのSplunkと同様にSplunk MCP Serverの公式Splunk Appを利用することが推奨されています1

このAppを利用すると、通常のSplunk APIを利用する場合と異なり、MCP専用のTokenをUserごとに払い出すことが可能です。

Splunk MCP Server

このMCP Serverに接続するためにはIP allow listsを設定する必要があります。見落としがちな点のため、注意してください。

また、このMCPを利用するためのRoleはこのSOC Agentにおいて基本的に以下の4つで、SPLを実行するためのRead権限があれば十分でした。

  • search
  • get_metadata
  • indexes_list_all
  • mcp_tool_execute

クライアント側の設定は基本的に.mcp.jsonなどのファイルに記載します。以下は.mcp.jsonの例です。

{
  "mcpServers": {
    "splunk-mcp-server": {
      "command": "op",
      "args": [
        "run",
        "--",
        "npx",
        "-y",
        "mcp-remote",
        "https://<stack-name>.splunkcloud.com:8089/services/mcp",
        "--header",
        "Authorization: Bearer ${AUTH_TOKEN}"
      ],
      "env": {
        "AUTH_TOKEN": "op://<vault-name>/<item-name>/<token-field>"
      }
    }
  }
}

上記のように1Password CLIを利用してMCP ServerのTokenを取得します。このSOC AgentのコードはチームでGitHub管理しているため、誤ってTokenをコミットしてしまうリスクを避けるために、VaultからTokenを取得しています。

MCPのエンドポイントは443ポートのもの(/en-US/splunkd/__raw/services/mcp)もあります。ただし、内部的には8089ポートにリダイレクトされるのでどちらを使っても問題ありません。

OpenCTI MCPの活用

実際の攻撃手法や攻撃に使われたIOC情報などを取得して危険度を評価するために、OpenCTI MCPも活用しています。OpenCTI MCPはFiligran社から公式にMCPが提供されています。

OpenCTI MCPを利用するにはTokenが必要なため、MCPを使うためのロール、グループ、サービスアカウントの作成が必要です。アカウントの作成に大きな手間はかかりませんが、ロールに関しては実際のAgentにどこまで作業をさせるかで必要な権限が変わります。今回のSOC AgentではRead権限のみで完結するように設計しているため、以下のようなロールを作成しました。

OpenCTI MCP ロール設定

基本的にこのAccess knowledgeのRoleがあればこのAgentの機能は十分に動かすことができました。caseまで記載させたい場合は別の権限が必要でしょう。

また、グループの作成の際にそのグループがアクセスできるインテリジェンスの範囲を定義できます。これは組織によってAIのオプトアウトの設定やインテリジェンスの発行元、TLPなどを考慮して設定する必要があります。個々の組織にあったポリシーを設定してください。

以下のような画面でグループのアクセス範囲を設定できます。「TLP:RED」のインテリジェンスは定義上見せない設定が基本でしょう。「TLP:AMBER」に関しては状況によるでしょう。

OpenCTI MCP グループ設定

クライアント側の設定は以下の記載で接続できます。

{
  "mcpServers": {
    "opencti-mcp-server": {
      "command": "op",
      "args": [
        "run",
        "--",
        "<path-to-python-venv>/.venv/bin/python3",
        "-m",
        "opencti_mcp.server"
      ],
      "env": {
        "OPENCTI_URL": "op://<vault-name>/<item-name>/<url-field>",
        "OPENCTI_TOKEN": "op://<vault-name>/<item-name>/<token-field>",
        "PYTHONPATH": "<path-to-xtm-mcp>"
      }
    }
  }
}

このサーバはfrom opencti_mcp.graphql_queriesなどの記述でPythonモジュールをimportしているため、PYTHONPATHの環境設定が必要です。

これらのMCPの設定のように、AIはある程度予期せぬ挙動を取る可能性も考え、与えるTokenの権限を絞ることをまずお勧めします。AIには自由にさせた方が柔軟に対応してくれます。変更されたくない接続先の権限を絞ることで、万が一の暴走リスクを減らせます。

SOC AgentのSubAgent設計

このSOC Agentは、特定のSkillを呼び出すAgentを並列起動できるようSubAgentを設計しています。具体的には、OpenCTIから脅威インテリジェンスを取得するSubAgentと、Splunkからログを取得するSubAgentの2つです。

Agent名 説明
opencti-agent OpenCTI MCPを通じて脅威インテリジェンスを取得するSubAgent
log-search-agent Splunk MCPを通じてログデータを取得するSubAgent

全体像は以下のとおりです。

SubAgentの構成

この2つのSubAgentが調査によって数十体並列で呼び出されます。IOCの種類や調査するログの種類によって呼び出すSubAgentを分けることで、効率的に必要な情報を取得できるようにしています。

opencti-agent

このAgentはOpenCTI MCPを通じて脅威インテリジェンスを取得するSubAgentです。OpenCTIから攻撃手法や攻撃に使われたIOC情報などを取得して、SOC AgentのメインのAgentがアラートの優先度を評価する際に活用します。基本的には別途設計したOpenCTIへGraphQLを投げるopencti-lookupSkillを参考にしています。大量の調査結果やインテリジェンスを収集する目的で利用するため、分析機能を持たせず、ひたすらクエリを投げる設計にしています。高度な分析を必要としないため、sonnetのモデルで動かしています。

上記Skillのreferenceに各種GraphQLのテンプレートを記載することで、必要な情報を取得する際のクエリを定義しています。例えば、「Reportの基本情報」を取得する際には以下のようなクエリを定義しています。

query ReportById {
  report(id: "<REPORT_ID>") {
    id
    standard_id
    entity_type
    name
    description
    published
    report_types
    confidence
    created_at
    updated_at
    objectLabel {
      value
      color
    }
    createdBy {
      ... on Identity {
        id
        name
        entity_type
      }
    }
  }
}

念のため、Hooksにてcreatedelete、リレーションを変更するstixCoreRelationshipEditなどRead権限以外の操作するクエリは禁止しています。

  "hooks": {
    "PreToolUse": [
      {
        "matcher": "^mcp__opencti-mcp-server__(execute_graphql_query|validate_graphql_query)$",
        "hooks": [
          {
            "type": "command",
            "command": "python3 \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate-opencti-graphql.py",
            "timeout": 5,
            "statusMessage": "Validating OpenCTI GraphQL safety policy"
          }
        ]
      }
    ]
  }

このvalidate-opencti-graphql.pyには、禁止するGraphQLのパターンをtool_inputから正規表現でマッチさせるPythonコードが記載されています。

SOCの対応でVirusTotalなどの判定を利用するフローも一般的に存在します。一方ZOZOでは脅威情報をOpenCTIに集約しているため、このエージェント単体で完結させています。

また、OpenCTIにはZOZO独自で調査している脅威情報も蓄積しているため、外部の脅威情報と社内の知見を組み合わせてアラートの優先度評価ができるようになっています。例えば以下のようなMalware解析のレポートなどを参照します。

qiita.com

log-search-agent

このAgentはSplunk MCPを通じてログデータを取得するSubAgentです。NotableのReference IDなどをもとに、アラートの概要を取得したり、より詳細なログを取得するSPLを投げたりするために利用します。こちらも分析機能は持たせず、別途設計したsplunk-searchSkillをもとに、ひたすらクエリを投げる設計にしています。高度な分析を必要としないため、sonnetのモデルで動かしています。

上記Skillのreferenceに各種SPLのテンプレートを記載することで、必要な情報を取得する際のクエリを定義しています。例えば、「Notableの概要」を取得する際には以下のようなSPLを定義しています。

index=notable source_event_id="<SOURCE_EVENT_ID>"
| sort -_time
| head 5
| table _time source_event_id event_id notable_event_id orig_event_id search_name rule_title notable_title signature security_domain urgency severity status status_label owner src dest user host risk_object risk_object_type risk_score info_min_time info_max_time

SplunkのMCP側で詳細なSPL制御ができません。そこで、OpenCTI同様にHooksを利用してoutputlookupoutputcsvなどの作成・変更を伴うSPLは以下の設定で利用禁止にしています。

  "hooks": {
    "PreToolUse": [
      {
        "matcher": "^mcp__splunk-mcp-server__splunk_run_query$",
        "hooks": [
          {
            "type": "command",
            "command": "python3 \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate-splunk-spl.py",
            "timeout": 5,
            "statusMessage": "Validating Splunk SPL safety policy"
          }
        ]
      }
    ]
  }

このMCPの利用に際して、JSON形式で入れ子になっているログはSubAgentの判断で最初にspathなどのSPLを打つことがあります。簡易なログだと問題ありませんが、Endpoint系のログだと大量のkeyに対して展開するため、各種SPLのreferenceを詳細に定義しておく方が安全です。また、サーチマクロを定義しておけば、Agentの調査の平準化やトークン消費の最適化が可能です。

memoryの活用

このSOC Agentでは、過去の調査履歴も活用しています。「このインシデントは過去に過検知フィードバックがあったものだ」や「引き続きこの証跡と同じアクターが関与している可能性が高い」といった情報を基に、調査の効率化や精度向上を図っています。

SOC Agentの運用

SOC Agent Skillsのコマンド

このAgentには様々なSkillsを実装しています。その中でもZOZOのSOCアナリストが利用するコマンドに絞ってここでは紹介します。

コマンド 説明
/notable-response NotableのReference IDからインシデントを取得し、自動調査を実行するコマンド
/threat-hunting OpenCTIのレポートから脅威ハンティングを実行するコマンド
/slack-alert-triage Slackのアラートを自動でトリアージし、調査結果をスレッドに投稿するコマンド

notable-response

このコマンドでのワークフローは以下のイメージです。

  1. SOCアナリストが/notable-response <Reference ID etc>を入力
  2. SOC AgentがSplunk MCPを通じてNotableの概要を取得
  3. SOC AgentがNotableの内容をもとに、opencti-agentとlog-search-agentを呼び出して、関連する脅威インテリジェンスやログデータを取得
  4. SOC Agentが取得した情報をもとに、Notableの相関分析や脅威判定し、対応案を生成
  5. 深掘りが必要な場合は、さらに追加の情報を取得するために3からのステップを繰り返す
  6. レポート作成、メモリに事象の内容や調査結果を保存

引数には調査観点の概要を含めて渡すことでカスタムした調査が可能です。

threat-hunting

このコマンドでのワークフローは以下のイメージです。

  1. SOCアナリストがSlackで/threat-hunting <Report ID>を入力
  2. SOC AgentがOpenCTI MCPを通じてレポートの内容を取得
  3. SOC Agentがレポートの内容をもとに、関連するIOCや攻撃手法を抽出
  4. SOC Agentが抽出したIOCや攻撃手法をもとに、log-search-agentを呼び出して、関連するログデータを取得
  5. SOC Agentが取得した情報をもとに、脅威ハンティングの結果を分析し、対応案を生成
  6. 深掘りが必要な場合は、さらに追加の情報を取得するために4からのステップを繰り返す
  7. レポート作成、メモリに事象の内容や調査結果を保存

Report IDは別途ZOZOで活用しているMalware解析Agentの結果を渡すこともできます。

slack-alert-triage

このコマンドでのワークフローは以下のイメージです。

  1. SOCアナリストがSlackで/slack-alert-triage <time>を入力
  2. SOC Agentが指定された時間範囲のアラートをSlack MCPを通じて取得
  3. SOC Agentが取得したアラートをもとに、NotableのReference IDを抽出
  4. SOC Agentが抽出したReference IDをもとに、notable-responseと同様にNotableの内容を取得
  5. Notableの内容をもとに関連事象をグルーピング、Slackのスレッドに調査開始の投稿
  6. 各グループごとにopencti-agentとlog-search-agentを呼び出して、関連する脅威インテリジェンスやログデータを取得
  7. SOC Agentが取得した情報をもとに、Notableの相関分析や脅威判定し、対応案を生成
  8. 深掘りが必要な場合は、さらに追加の情報を取得するために6からのステップを繰り返す
  9. レポート作成、Slackスレッドに対応サマリを投稿
  10. 脅威度がCritical判定の場合は、SOCアナリストにメンション通知

このコマンドを/loop 1h /slack-alert-triage 1hのように定期実行することで、未処理のアラートを自動的に検知して対応サマリを投稿しています。24時間365日対応が難しい場合でも、こういった自動化を活用することでSOCメンバーの負荷を軽減できます。

SOARの活用

/slack-alert-triageコマンドのポイントはSlackのアラートにReference IDが含まれていることです。通常のSplunk ESの「Edit event-based detection」だと「Adaptive response」はNotableの作成とは別のアクションを実行するため、Reference IDがSlackのアラートに含まれません。そこでSplunk SOARを用いて、NotableのReference IDをSlackのアラートに含めています。こうすることで、SOC AgentがSlackのアラートからNotableのReference IDを抽出し、調査を開始できます。

SOARは以下のformatとSlackへのsend messageのSplunk Appの設定だけで済みます。

Splunk SOAR 設定

formatはSlackのblocks項目に以下の記述をすれば、ビジュアライズされたアラートをSlackに送れます。

[
  {{
    "type": "header",
    "text": {{
      "type": "plain_text",
      "text": "🟢 Splunk Finding Detected",
      "emoji": true
    }}
  }},
  {{
    "type": "section",
    "fields": [
      {{
        "type": "mrkdwn",
        "text": "*🔎 Name*\n{0}"
      }},
      {{
        "type": "mrkdwn",
        "text": "*🆔 Reference ID*\n`{1}`"
      }}
    ]
  }}
]

{0}にはアラート名、{1}にはReference IDを入れるように設定しています。これでSOC AgentがSlackのアラートからReference IDを抽出し、調査を開始できます。

SOC Agentの本命のSkillはこのコマンドです。ループ処理することでTier1相当の対応をAIで完全自動化することに成功しており、SOCメンバーの負荷軽減に大きく寄与しています。

以下はSOC Agentの対応例です。

SOC Agentの対応例

おわりに

本記事ではClaude Codeを用いたSOC Agentを紹介しました。SOC Agentの導入によって少人数のSOC業務を改善し、アラート対応の効率化、平準化、SOCメンバーのさらなる高度業務へのアサインを図れました。

ZOZOでは、一緒に安全なサービスを作り上げてくれる仲間を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください!

hrmos.co

カテゴリー