Day 10: 総合プロジェクト
今日のゴール
これまで学んだすべてのSplunk技術を使って、セキュリティ監視ダッシュボードを構築します。
プロジェクト概要
| 項目 | 内容 |
|---|---|
| ダッシュボード名 | Security Operations Center (SOC) |
| 機能 | 脅威検知、インシデント対応、コンプライアンスレポート |
| 使用技術 | SPL全般、ダッシュボード、アラート、ルックアップ、マクロ |
flowchart TB
subgraph SOC["SOC Dashboard"]
KPI["KPIパネル<br>総イベント・アラート数"]
Timeline["タイムライン<br>イベント推移"]
Threat["脅威検知<br>異常パターン"]
Detail["詳細分析<br>ドリルダウン"]
end
style KPI fill:#3b82f6,color:#fff
style Timeline fill:#22c55e,color:#fff
style Threat fill:#ef4444,color:#fff
style Detail fill:#f59e0b,color:#fff
Step 1: サンプルデータの準備
セキュリティログの生成
以下のログを用意します。
firewall.log
2026-01-30 10:00:01 action=allowed src_ip=192.168.1.10 dst_ip=10.0.0.1 dst_port=443 proto=TCP bytes=2048
2026-01-30 10:00:02 action=blocked src_ip=10.10.10.5 dst_ip=192.168.1.100 dst_port=22 proto=TCP bytes=0
2026-01-30 10:00:03 action=allowed src_ip=192.168.1.20 dst_ip=172.16.0.5 dst_port=80 proto=TCP bytes=4096
2026-01-30 10:00:05 action=blocked src_ip=203.0.113.50 dst_ip=192.168.1.100 dst_port=3389 proto=TCP bytes=0
2026-01-30 10:00:10 action=allowed src_ip=192.168.1.30 dst_ip=10.0.0.2 dst_port=53 proto=UDP bytes=128
auth.log
2026-01-30 10:00:01 action=login_success user=alice src_ip=192.168.1.10 method=password
2026-01-30 10:00:05 action=login_failed user=admin src_ip=203.0.113.50 method=password
2026-01-30 10:00:06 action=login_failed user=admin src_ip=203.0.113.50 method=password
2026-01-30 10:00:07 action=login_failed user=admin src_ip=203.0.113.50 method=password
2026-01-30 10:00:10 action=login_success user=bob src_ip=192.168.1.20 method=ssh_key
2026-01-30 10:00:15 action=login_failed user=root src_ip=198.51.100.10 method=password
2026-01-30 10:00:20 action=privilege_escalation user=alice src_ip=192.168.1.10 target=root
web_access.log
192.168.1.10 - alice [30/Jan/2026:10:00:01 +0900] "GET /admin HTTP/1.1" 200 2048
203.0.113.50 - - [30/Jan/2026:10:00:05 +0900] "GET /../../../../etc/passwd HTTP/1.1" 403 128
192.168.1.20 - bob [30/Jan/2026:10:00:10 +0900] "GET /api/users HTTP/1.1" 200 4096
198.51.100.10 - - [30/Jan/2026:10:00:15 +0900] "POST /api/login HTTP/1.1" 401 64
10.10.10.5 - - [30/Jan/2026:10:00:20 +0900] "GET /wp-admin HTTP/1.1" 404 128
Step 2: ルックアップテーブル
threat_intel.csv(脅威インテリジェンス)
ip_address,threat_type,severity,description
203.0.113.50,brute_force,high,Known brute force attacker
198.51.100.10,scanner,medium,Network scanner
10.10.10.5,botnet,critical,Botnet C2 server
asset_inventory.csv(資産情報)
ip_address,hostname,department,criticality
192.168.1.10,ws-alice,Engineering,medium
192.168.1.20,ws-bob,Marketing,low
192.168.1.30,ws-charlie,Finance,high
192.168.1.100,srv-web01,IT,critical
10.0.0.1,srv-db01,IT,critical
Step 3: サーチマクロ
# macros.conf
# 脅威IPの検出
[threat_detected]
definition = lookup threat_intel ip_address AS src_ip OUTPUT threat_type, severity, description AS threat_description | where isnotnull(threat_type)
# セキュリティイベントの重要度分類
[severity_classification]
definition = eval alert_severity=case(severity="critical", 4, severity="high", 3, severity="medium", 2, severity="low", 1, 1=1, 0)
# 認証失敗の検出
[auth_failures(1)]
args = threshold
definition = index=security sourcetype=auth_log action=login_failed | stats count by src_ip, user | where count >= $threshold$
Step 4: アラートの定義
ブルートフォース検知
index=security sourcetype=auth_log action=login_failed
| bin _time span=5m
| stats count by src_ip, _time
| where count >= 5
| `threat_detected`
設定:
- Schedule:
*/5 * * * * - Trigger: Number of Results > 0
- Suppress: 30分、src_ipごと
- Action: メール、Slack通知
不正アクセス試行
index=web sourcetype=access_combined
| rex field=uri "(?P<attack_pattern>(\.\./|etc/passwd|wp-admin|\.env|\.git))"
| where isnotnull(attack_pattern)
| stats count by clientip, attack_pattern
Step 5: SOCダッシュボード
<dashboard theme="dark">
<label>Security Operations Center</label>
<description>セキュリティ監視ダッシュボード</description>
<fieldset submitButton="false">
<input type="time" token="time">
<default>
<earliest>-24h@h</earliest>
<latest>now</latest>
</default>
</input>
<input type="dropdown" token="severity_filter">
<label>Severity</label>
<choice value="*">All</choice>
<choice value="critical">Critical</choice>
<choice value="high">High</choice>
<choice value="medium">Medium</choice>
<default>*</default>
</input>
</fieldset>
<!-- KPI行 -->
<row>
<panel><title>Total Security Events</title>
<single>
<search>
<query>index=security OR index=web | stats count</query>
<earliest>$time.earliest$</earliest>
<latest>$time.latest$</latest>
</search>
<option name="colorMode">block</option>
<option name="rangeColors">["0x22c55e","0xf59e0b","0xef4444"]</option>
<option name="rangeValues">[1000,5000]</option>
<option name="useColors">true</option>
</single>
</panel>
<panel><title>Threat Detections</title>
<single>
<search>
<query>
index=security OR index=web
| `threat_detected`
| stats dc(src_ip) AS threat_count
</query>
<earliest>$time.earliest$</earliest>
<latest>$time.latest$</latest>
</search>
<option name="colorMode">block</option>
<option name="rangeColors">["0x22c55e","0xef4444"]</option>
<option name="rangeValues">[0]</option>
<option name="useColors">true</option>
</single>
</panel>
<panel><title>Failed Logins</title>
<single>
<search>
<query>index=security sourcetype=auth_log action=login_failed | stats count</query>
<earliest>$time.earliest$</earliest>
<latest>$time.latest$</latest>
</search>
</single>
</panel>
<panel><title>Blocked Connections</title>
<single>
<search>
<query>index=security sourcetype=firewall action=blocked | stats count</query>
<earliest>$time.earliest$</earliest>
<latest>$time.latest$</latest>
</search>
</single>
</panel>
</row>
<!-- タイムライン -->
<row>
<panel><title>Security Events Timeline</title>
<chart>
<search>
<query>
index=security OR index=web
| eval event_type=case(
action="blocked", "Firewall Block",
action="login_failed", "Auth Failure",
status>=400, "Web Error",
1=1, "Other"
)
| timechart span=1h count by event_type
</query>
<earliest>$time.earliest$</earliest>
<latest>$time.latest$</latest>
</search>
<option name="charting.chart">area</option>
<option name="charting.chart.stackMode">stacked</option>
<option name="charting.legend.placement">bottom</option>
</chart>
</panel>
</row>
<!-- 脅威分析 -->
<row>
<panel><title>Threat Intelligence Matches</title>
<table>
<search>
<query>
index=security OR index=web
| `threat_detected`
| stats count, values(action) AS actions, latest(_time) AS last_seen by src_ip, threat_type, severity
| eval last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort -count
</query>
<earliest>$time.earliest$</earliest>
<latest>$time.latest$</latest>
</search>
<option name="drilldown">row</option>
<drilldown>
<link target="_blank">/app/search/search?q=index%3Dsecurity%20src_ip%3D$row.src_ip$</link>
</drilldown>
</table>
</panel>
<panel><title>Top Blocked IPs</title>
<chart>
<search>
<query>
index=security sourcetype=firewall action=blocked
| stats count by src_ip
| sort -count
| head 10
</query>
<earliest>$time.earliest$</earliest>
<latest>$time.latest$</latest>
</search>
<option name="charting.chart">bar</option>
</chart>
</panel>
</row>
<!-- 認証分析 -->
<row>
<panel><title>Authentication Failures by User</title>
<chart>
<search>
<query>
index=security sourcetype=auth_log action=login_failed
| stats count by user
| sort -count
</query>
<earliest>$time.earliest$</earliest>
<latest>$time.latest$</latest>
</search>
<option name="charting.chart">pie</option>
</chart>
</panel>
<panel><title>Recent Security Events</title>
<table>
<search>
<query>
index=security
| eval severity=case(
action="privilege_escalation", "critical",
action="login_failed", "warning",
action="blocked", "info",
1=1, "low"
)
| table _time, sourcetype, action, user, src_ip, severity
| sort -_time
| head 20
</query>
<earliest>$time.earliest$</earliest>
<latest>$time.latest$</latest>
</search>
</table>
</panel>
</row>
</dashboard>
10日間の振り返り
flowchart TB
D1["Day 1<br>Splunkの基礎<br>アーキテクチャ"]
D2["Day 2<br>データ取り込み<br>inputs.conf"]
D3["Day 3<br>サーチの基本<br>SPL入門"]
D4["Day 4<br>フィールドと<br>フィルタリング"]
D5["Day 5<br>統計と集計<br>stats/timechart"]
D6["Day 6<br>データの可視化<br>ダッシュボード"]
D7["Day 7<br>サーチの応用<br>lookup/join"]
D8["Day 8<br>アラートと<br>レポート"]
D9["Day 9<br>Splunkの管理<br>ロール/アプリ"]
D10["Day 10<br>総合プロジェクト"]
D1 --> D2 --> D3 --> D4 --> D5
D5 --> D6 --> D7 --> D8 --> D9 --> D10
style D1 fill:#3b82f6,color:#fff
style D2 fill:#3b82f6,color:#fff
style D3 fill:#22c55e,color:#fff
style D4 fill:#22c55e,color:#fff
style D5 fill:#22c55e,color:#fff
style D6 fill:#f59e0b,color:#fff
style D7 fill:#f59e0b,color:#fff
style D8 fill:#8b5cf6,color:#fff
style D9 fill:#8b5cf6,color:#fff
style D10 fill:#ef4444,color:#fff
| Day | トピック | 習得したスキル |
|---|---|---|
| 1 | Splunkの世界へようこそ | アーキテクチャ、インストール、Web UI |
| 2 | データの取り込み | monitor, HEC, sourcetype, indexes |
| 3 | サーチの基本 | SPL構文、キーワード/フィールド検索、パイプ |
| 4 | フィールドとフィルタリング | eval, where, rex |
| 5 | 統計と集計 | stats, chart, timechart, top, eventstats |
| 6 | データの可視化 | ダッシュボード、Simple XML、ドリルダウン |
| 7 | サーチの応用 | サブサーチ、lookup, join, transaction |
| 8 | アラートとレポート | スケジュールサーチ、アラート、マクロ |
| 9 | Splunkの管理 | ロール、インデックス管理、ナレッジオブジェクト |
| 10 | 総合プロジェクト | SOCダッシュボード構築 |
次のステップ
Splunkの基礎を習得しました。次に学ぶべきトピックを紹介します。
| トピック | 説明 |
|---|---|
| Splunk Enterprise Security (ES) | SIEM機能の活用 |
| Splunk SOAR | セキュリティオーケストレーション |
| SPL2 | 次世代のサーチ言語 |
| データモデルとCIM | Common Information Model |
| Splunk Cloud | クラウド版の活用 |
| Splunk認定資格 | Splunk Core Certified User / Power User |
Splunk認定資格
| 資格 | レベル | 対象 |
|---|---|---|
| Splunk Core Certified User | 基礎 | SPLの基本操作 |
| Splunk Core Certified Power User | 中級 | 高度なSPL、ダッシュボード |
| Splunk Core Certified Advanced Power User | 上級 | データモデル、最適化 |
| Splunk Enterprise Certified Admin | 管理 | インフラ管理、設定 |
練習問題
問題1: 機能追加
地理情報(iplocationコマンド)を使って、攻撃元の国をマップ上に表示するパネルを追加してください。
問題2: 応用
eventstatsを使って、各IPの通常のアクセス頻度を計算し、異常なアクセス数(平均の3倍以上)を検知するクエリを作成してください。
チャレンジ問題
完全なSplunkアプリとして、このSOCダッシュボードをパッケージ化してください。app.conf、ナビゲーション、ダッシュボード、ルックアップ、マクロ、保存済みサーチ(アラート)を含めましょう。
参考リンク
おめでとうございます! 10日間でSplunkの基礎をマスターしました。ここで学んだ知識は、セキュリティ運用、IT監視、データ分析など、あらゆるSplunk活用の土台になります。