
Building Incident Response Dashboard
- 171 installs
- 27.3k repo stars
- Updated August 2, 2026
- mukul975/anthropic-cybersecurity-skills
building-incident-response-dashboard is a Claude Code skill that builds real-time incident-response dashboards in Splunk, Elastic, or Grafana for SOC situational awareness.
About
This skill builds real-time incident-response dashboards in Splunk, Elastic, or Grafana. It gives SOC analysts and leadership situational awareness during active incidents by tracking affected systems, containment status, IOC spread, and the response timeline. A developer uses it when IR teams need unified visibility during incident coordination and post-incident reporting. It provides Splunk Dashboard Studio XML and SPL queries for affected-systems, IOC-tracking, and timeline panels.
- Builds IR dashboards in Splunk, Elastic, or Grafana
- Tracks affected systems, IOC spread, and containment status
- Provides Dashboard Studio XML and SPL queries
Building Incident Response Dashboard by the numbers
- 171 all-time installs (skills.sh)
- +6 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #841 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
building-incident-response-dashboard capabilities & compatibility
Free skill; requires an existing SIEM platform (Splunk, Elastic, or Grafana).
- Capabilities
- incident response · soc dashboard · ioc tracking · siem visualization
- Works with
- splunk · grafana · elasticsearch · servicenow
- Use cases
- security audit · data analysis
- Pricing
- Free
What building-incident-response-dashboard says it does
Builds real-time incident response dashboards in Splunk, Elastic, or Grafana to provide SOC analysts and leadership with situational awareness during active incidents
Do not use** for day-to-day SOC monitoring dashboards (use Incident Review instead)
npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill building-incident-response-dashboardAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 171 |
|---|---|
| repo stars | ★ 27.3k |
| Last updated | August 2, 2026 |
| Repository | mukul975/anthropic-cybersecurity-skills ↗ |
How do I give SOC analysts and leadership real-time visibility during an active security incident?
Build a real-time SOC incident-response dashboard
Who is it for?
IR and SOC teams needing unified real-time visibility during active incident coordination.
Skip if: Day-to-day SOC monitoring dashboards; the skill says to use Incident Review for those instead.
When should I use this skill?
When IR teams need real-time dashboards during active incidents for coordination and tracking.
What you get
A real-time IR dashboard tracking affected systems, containment status, IOC spread, and the response timeline.
- Real-time active-incident dashboard
- IOC tracking and response-timeline panels
Files
Building Incident Response Dashboard
When to Use
Use this skill when:
- IR teams need real-time dashboards during active incidents for coordination and tracking
- SOC leadership requires operational dashboards showing incident status and analyst workload
- Post-incident reviews need visual timelines and impact assessments
- Executive briefings require high-level incident metrics and trend analysis
Do not use for day-to-day SOC monitoring dashboards (use Incident Review instead) — IR dashboards are designed for active incident coordination and management reporting.
Prerequisites
- SIEM platform (Splunk with Dashboard Studio, Elastic Kibana, or Grafana)
- Notable event and incident data in SIEM (Splunk ES incident_review index)
- Ticketing system integration (ServiceNow, Jira) for remediation tracking
- Asset and identity lookup tables for context enrichment
- Dashboard publishing access for SOC team and management distribution
Workflow
Step 1: Design Active Incident Dashboard Layout
Build a Splunk Dashboard Studio dashboard for active incident tracking:
<dashboard version="2" theme="dark">
<label>Active Incident Response Dashboard</label>
<description>Real-time tracking for IR-2024-0450</description>
<row>
<panel>
<title>Incident Summary</title>
<single>
<search>
<query>
| makeresults
| eval incident_id="IR-2024-0450",
status="CONTAINMENT",
severity="Critical",
affected_hosts=7,
contained_hosts=5,
iocs_identified=23,
hours_elapsed=round((now()-strptime("2024-03-15 14:00","%Y-%m-%d %H:%M"))/3600,1)
| table incident_id, status, severity, affected_hosts, contained_hosts, iocs_identified, hours_elapsed
</query>
</search>
</single>
</panel>
</row>
</dashboard>Step 2: Build Real-Time Affected Systems Panel
Track affected systems and their containment status:
| inputlookup ir_affected_systems.csv
| eval status_color = case(
status="Contained", "#2ecc71",
status="Compromised", "#e74c3c",
status="Investigating", "#f39c12",
status="Recovered", "#3498db",
1=1, "#95a5a6"
)
| stats count by status
| eval order = case(status="Compromised", 1, status="Investigating", 2,
status="Contained", 3, status="Recovered", 4)
| sort order
| table status, count
--- Detailed host table
| inputlookup ir_affected_systems.csv
| lookup asset_lookup_by_cidr ip AS host_ip OUTPUT category, owner, priority
| table hostname, host_ip, category, owner, status, containment_time,
compromise_vector, analyst_assigned
| sort status, hostnameStep 3: Build IOC Tracking Panel
Monitor IOC spread across the environment:
--- IOCs identified during incident
index=* (src_ip IN ("185.234.218.50", "45.77.123.45") OR
dest IN ("evil-c2.com", "malware-drop.com") OR
file_hash IN ("a1b2c3d4...", "e5f6a7b8..."))
earliest="2024-03-14"
| stats count AS hits, dc(src_ip) AS unique_sources,
dc(dest) AS unique_dests, latest(_time) AS last_seen
by sourcetype
| sort - hits
--- IOC timeline
index=* (src_ip IN ("185.234.218.50") OR dest="evil-c2.com")
earliest="2024-03-14"
| timechart span=1h count by sourcetype
--- New IOC discovery tracking
| inputlookup ir_ioc_list.csv
| stats count by ioc_type, source, discovery_time
| sort discovery_time
| table discovery_time, ioc_type, ioc_value, source, statusStep 4: Build Response Timeline Panel
Create chronological incident timeline:
| inputlookup ir_timeline.csv
| sort _time
| eval phase = case(
action_type="detection", "Detection",
action_type="triage", "Triage",
action_type="containment", "Containment",
action_type="eradication", "Eradication",
action_type="recovery", "Recovery",
1=1, "Other"
)
| eval phase_color = case(
phase="Detection", "#e74c3c",
phase="Triage", "#f39c12",
phase="Containment", "#e67e22",
phase="Eradication", "#2ecc71",
phase="Recovery", "#3498db"
)
| table _time, phase, action, analyst, detailsExample timeline data:
_time,action_type,action,analyst,details
2024-03-15 14:00,detection,Alert triggered - Cobalt Strike beacon detected,splunk_es,Notable event NE-2024-08921
2024-03-15 14:12,triage,Alert triaged - confirmed true positive,analyst_jdoe,VT score 52/72 on beacon hash
2024-03-15 14:23,containment,Host WORKSTATION-042 isolated,analyst_jdoe,CrowdStrike network isolation
2024-03-15 14:35,containment,C2 domain blocked on firewall,analyst_msmith,Palo Alto rule deployed
2024-03-15 15:00,eradication,Enterprise-wide IOC scan initiated,analyst_jdoe,Splunk search across all indices
2024-03-15 15:30,containment,3 additional hosts identified and isolated,analyst_msmith,Lateral movement confirmed
2024-03-15 16:00,eradication,Malware removed from all affected hosts,analyst_tier3,CrowdStrike RTR cleanup
2024-03-15 18:00,recovery,Systems restored and monitored,analyst_msmith,72-hour monitoring period startedStep 5: Build SOC Operations Dashboard
Track overall SOC performance metrics:
--- Incident volume by severity (last 30 days)
index=notable earliest=-30d
| stats count by urgency
| eval order = case(urgency="critical", 1, urgency="high", 2, urgency="medium", 3,
urgency="low", 4, urgency="informational", 5)
| sort order
--- MTTD (Mean Time to Detect)
index=notable earliest=-30d status_label="Resolved*"
| eval mttd_minutes = round((time_of_first_event - orig_time) / 60, 1)
| stats avg(mttd_minutes) AS avg_mttd, median(mttd_minutes) AS med_mttd,
perc95(mttd_minutes) AS p95_mttd
--- MTTR (Mean Time to Respond/Resolve)
index=notable earliest=-30d status_label="Resolved*"
| eval mttr_hours = round((status_end - _time) / 3600, 1)
| stats avg(mttr_hours) AS avg_mttr, median(mttr_hours) AS med_mttr by urgency
--- Analyst workload distribution
index=notable earliest=-7d
| stats count by owner
| sort - count
--- Alert disposition breakdown
index=notable earliest=-30d status_label IN ("Resolved*", "Closed*")
| stats count by disposition
| eval percentage = round(count / sum(count) * 100, 1)
| sort - countStep 6: Build Executive Briefing Dashboard
Create a high-level dashboard for leadership during major incidents:
--- Executive summary panel
| makeresults
| eval metrics = "Business Impact: 1 file server offline (Finance dept), "
."Estimated Recovery: 4 hours, "
."Data Loss Risk: Low (backups verified), "
."Customer Impact: None, "
."Regulatory Notification: Not required (no PII exposure confirmed)"
--- Trend comparison (this month vs last month)
index=notable earliest=-60d
| eval period = if(_time > relative_time(now(), "-30d"), "Current Month", "Previous Month")
| stats count by period, urgency
| chart sum(count) AS incidents by period, urgency
--- Top threat categories
index=notable earliest=-30d
| top rule_name limit=10
| table rule_name, count, percentStep 7: Automate Dashboard Updates
Use Splunk scheduled searches to maintain dashboard data:
--- Scheduled search to update affected systems lookup (runs every 5 minutes)
index=* (src_ip IN [| inputlookup ir_ioc_list.csv | search ioc_type="ip"
| fields ioc_value | rename ioc_value AS src_ip])
earliest=-1h
| stats latest(_time) AS last_seen, count AS event_count,
values(sourcetype) AS data_sources by src_ip
| eval status = if(last_seen > relative_time(now(), "-15m"), "Active", "Dormant")
| outputlookup ir_affected_systems_auto.csvKey Concepts
| Term | Definition |
|---|---|
| Situational Awareness | Real-time understanding of incident scope, affected systems, and response progress |
| MTTD | Mean Time to Detect — average time from threat occurrence to SOC alert generation |
| MTTR | Mean Time to Respond — average time from alert to incident resolution or containment |
| Containment Rate | Percentage of affected systems successfully isolated relative to total compromised systems |
| Burn-Down Chart | Visual tracking of remaining open investigation tasks over time during an incident |
| Executive Briefing | Non-technical summary dashboard showing business impact, timeline, and recovery status |
Tools & Systems
- Splunk Dashboard Studio: Modern dashboard framework with drag-and-drop visualization and real-time data
- Elastic Kibana Dashboard: Visualization platform with Lens, Maps, and Canvas for security dashboards
- Grafana: Open-source visualization platform supporting multiple data sources including Elasticsearch and Splunk
- Microsoft Sentinel Workbooks: Azure-native dashboard framework with Kusto-based analytics visualization
- TheHive: Open-source incident response platform with built-in case tracking and metrics dashboards
Common Scenarios
- Active Ransomware Incident: Dashboard showing encryption spread, containment status, backup verification, recovery progress
- Data Breach Investigation: Dashboard tracking affected data stores, exfiltration volume, notification requirements
- Phishing Campaign Response: Dashboard showing recipient count, click rate, credential exposure, remediation status
- Monthly SOC Report: Leadership dashboard with incident trends, MTTD/MTTR metrics, analyst performance
- Compliance Audit: Dashboard demonstrating detection coverage, response SLA compliance, and incident closure metrics
Output Format
INCIDENT RESPONSE DASHBOARD — IR-2024-0450
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STATUS: CONTAINMENT PHASE (6h 30m elapsed)
Affected Systems: Containment Progress:
Compromised: 2 [==========----------] 71%
Investigating: 1 5 of 7 systems contained
Contained: 3
Recovered: 1
IOC Summary: Response Timeline:
IPs: 4 14:00 — Alert triggered
Domains: 2 14:12 — Confirmed malicious
Hashes: 3 14:23 — First host isolated
URLs: 5 15:00 — Enterprise scan started
Emails: 1 15:30 — 3 more hosts isolated
Key Metrics:
MTTD: 12 minutes
MTTC: 23 minutes (first host)
Analysts Active: 3 (Tier 2: 2, Tier 3: 1)
Business Impact: LOW — Finance file server offline, no customer-facing systems affected
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
API Reference: Building Incident Response Dashboard
splunk-sdk (splunklib)
import splunklib.client as client
import splunklib.results as results
service = client.connect(host="localhost", port=8089,
username="admin", password="changeme")
# Run a blocking search
job = service.jobs.create(
'search index=notable | stats count by urgency',
earliest_time="-24h", latest_time="now", exec_mode="blocking"
)
for result in results.JSONResultsReader(job.results(output_mode="json")):
print(result)
# Create a saved search (dashboard panel)
service.saved_searches.create("IR_Affected_Systems", search="""
search index=notable incident_id="IR-*"
| stats count by dest, urgency | sort - count
""")Key SPL Patterns for IR Dashboards
--- Incident summary single-value panels
| makeresults | eval status="CONTAINMENT", affected=7, contained=5
--- SOC Metrics (MTTD / MTTR)
index=notable status_label="Resolved*"
| eval mttr_hours = round((status_end - _time) / 3600, 1)
| stats avg(mttr_hours) AS avg_mttr by urgency
--- Analyst workload
index=notable earliest=-7d | stats count by owner | sort - count
--- IOC spread tracking
index=* (src_ip IN ("1.2.3.4") OR dest="evil.com")
| timechart span=1h count by sourcetype
--- Alert disposition
index=notable status_label="Closed*"
| stats count by disposition
| eventstats sum(count) AS total
| eval pct = round(count/total*100, 1)Dashboard Studio (Splunk v2)
<dashboard version="2" theme="dark">
<label>IR Dashboard</label>
<row>
<panel><title>Affected Systems</title>
<table><search><query>| inputlookup ir_systems.csv</query></search></table>
</panel>
</row>
</dashboard>TheHive API (Case Tracking)
import requests
headers = {"Authorization": "Bearer <api_key>"}
# List open cases
resp = requests.get("http://thehive:9000/api/case",
headers=headers, params={"range": "0-50", "sort": "-startDate"})References
- splunk-sdk-python: https://github.com/splunk/splunk-sdk-python
- Splunk Dashboard Studio: https://docs.splunk.com/Documentation/DashboardStudio
- TheHive API: https://docs.strangebee.com/thehive/api-docs/
#!/usr/bin/env python3
"""Agent for building and managing incident response dashboards in Splunk."""
import os
import json
import argparse
from datetime import datetime
import splunklib.client as client
import splunklib.results as results
def connect_splunk(host, port, username, password):
"""Connect to Splunk instance."""
return client.connect(host=host, port=port, username=username, password=password)
def run_search(service, query, earliest="-24h", latest="now"):
"""Execute a Splunk search and return results."""
kwargs = {"earliest_time": earliest, "latest_time": latest, "exec_mode": "blocking"}
job = service.jobs.create(query, **kwargs)
rows = []
for result in results.JSONResultsReader(job.results(output_mode="json")):
if isinstance(result, dict):
rows.append(result)
return rows
def get_incident_summary(service, incident_id):
"""Get summary of a specific incident from notable events."""
query = f"""
search index=notable incident_id="{incident_id}"
| stats count AS total_events, dc(src_ip) AS unique_sources,
dc(dest) AS unique_destinations,
min(_time) AS first_seen, max(_time) AS last_seen,
values(urgency) AS severity
| eval duration_hours = round((last_seen - first_seen) / 3600, 1)
"""
return run_search(service, query)
def get_affected_systems(service, incident_id):
"""Track systems affected by an incident."""
query = f"""
search index=notable incident_id="{incident_id}"
| stats count AS events, latest(_time) AS last_activity,
values(rule_name) AS detections by dest
| lookup asset_lookup_by_str dest OUTPUT category, owner, priority
| eval status = case(
last_activity > relative_time(now(), "-15m"), "Active",
last_activity > relative_time(now(), "-1h"), "Recent",
1=1, "Historical")
| sort - events
| table dest, category, owner, status, events, detections
"""
return run_search(service, query)
def get_ioc_spread(service, iocs, earliest="-7d"):
"""Monitor IOC hits across the environment."""
ip_list = [i for i in iocs if i.get("type") == "ip"]
domain_list = [i for i in iocs if i.get("type") == "domain"]
hash_list = [i for i in iocs if i.get("type") == "hash"]
search_parts = []
if ip_list:
ips = " ".join(f'"{i["value"]}"' for i in ip_list)
search_parts.append(f"src_ip IN ({ips}) OR dest_ip IN ({ips})")
if domain_list:
domains = " ".join(f'"{d["value"]}"' for d in domain_list)
search_parts.append(f"query IN ({domains}) OR dest IN ({domains})")
if hash_list:
hashes = " ".join(f'"{h["value"]}"' for h in hash_list)
search_parts.append(f"file_hash IN ({hashes})")
condition = " OR ".join(search_parts)
query = f"""
search index=* ({condition})
| stats count AS hits, dc(src_ip) AS sources,
dc(dest) AS destinations, latest(_time) AS last_seen
by sourcetype
| sort - hits
"""
return run_search(service, query, earliest=earliest)
def get_soc_metrics(service, days=30):
"""Calculate SOC operational metrics."""
query = f"""
search index=notable earliest=-{days}d status_label="Resolved*"
| eval mttr_hours = round((status_end - _time) / 3600, 1)
| eval mttd_minutes = round((time_of_first_event - orig_time) / 60, 1)
| stats avg(mttr_hours) AS avg_mttr, median(mttr_hours) AS med_mttr,
avg(mttd_minutes) AS avg_mttd, median(mttd_minutes) AS med_mttd,
count AS resolved_count by urgency
| sort urgency
"""
return run_search(service, query, earliest=f"-{days}d")
def get_analyst_workload(service, days=7):
"""Get analyst workload distribution."""
query = f"""
search index=notable earliest=-{days}d
| stats count AS assigned, dc(rule_name) AS rule_types,
avg(eval(if(status_label="Resolved*", (status_end - _time)/3600, null()))) AS avg_resolve_hrs
by owner
| sort - assigned
"""
return run_search(service, query, earliest=f"-{days}d")
def get_alert_disposition(service, days=30):
"""Get alert disposition breakdown."""
query = f"""
search index=notable earliest=-{days}d status_label IN ("Resolved*", "Closed*")
| stats count by disposition
| eventstats sum(count) AS total
| eval percentage = round(count / total * 100, 1)
| sort - count
| table disposition, count, percentage
"""
return run_search(service, query, earliest=f"-{days}d")
def get_incident_timeline(service, incident_id):
"""Build chronological incident timeline."""
query = f"""
search index=notable incident_id="{incident_id}"
| sort _time
| eval phase = case(
action_type="detection", "Detection",
action_type="triage", "Triage",
action_type="containment", "Containment",
action_type="eradication", "Eradication",
action_type="recovery", "Recovery",
1=1, "Other")
| table _time, phase, action, analyst, details
"""
return run_search(service, query)
def main():
parser = argparse.ArgumentParser(description="Incident Response Dashboard Agent")
parser.add_argument("--host", default=os.getenv("SPLUNK_HOST", "localhost"))
parser.add_argument("--port", type=int, default=int(os.getenv("SPLUNK_PORT", "8089")))
parser.add_argument("--username", default=os.getenv("SPLUNK_USERNAME", "admin"))
parser.add_argument("--password", default=os.getenv("SPLUNK_PASSWORD", ""))
parser.add_argument("--incident-id", help="Specific incident ID to track")
parser.add_argument("--output", default="ir_dashboard_report.json")
parser.add_argument("--action", choices=[
"summary", "systems", "iocs", "metrics", "workload", "timeline", "full_dashboard"
], default="full_dashboard")
args = parser.parse_args()
service = connect_splunk(args.host, args.port, args.username, args.password)
report = {"generated_at": datetime.utcnow().isoformat(), "data": {}}
if args.action in ("summary", "full_dashboard") and args.incident_id:
report["data"]["summary"] = get_incident_summary(service, args.incident_id)
print(f"[+] Incident summary loaded for {args.incident_id}")
if args.action in ("systems", "full_dashboard") and args.incident_id:
report["data"]["affected_systems"] = get_affected_systems(service, args.incident_id)
print(f"[+] Affected systems: {len(report['data']['affected_systems'])}")
if args.action in ("metrics", "full_dashboard"):
report["data"]["soc_metrics"] = get_soc_metrics(service)
print(f"[+] SOC metrics calculated")
if args.action in ("workload", "full_dashboard"):
report["data"]["analyst_workload"] = get_analyst_workload(service)
print(f"[+] Analyst workload: {len(report['data']['analyst_workload'])} analysts")
if args.action in ("timeline", "full_dashboard") and args.incident_id:
report["data"]["timeline"] = get_incident_timeline(service, args.incident_id)
print(f"[+] Timeline events: {len(report['data']['timeline'])}")
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Dashboard data saved to {args.output}")
if __name__ == "__main__":
main()
Construcción de un Dashboard de Respuesta a Incidentes
Cuándo Utilizar
Utilice esta habilidad cuando:
- Los equipos de IR necesitan dashboards en tiempo real durante incidentes activos para coordinación y seguimiento
- La dirección del SOC requiere dashboards operacionales que muestren el estado de incidentes y la carga de trabajo de los analistas
- Las revisiones post-incidente necesitan líneas de tiempo visuales y evaluaciones de impacto
- Las sesiones informativas ejecutivas requieren métricas de incidentes de alto nivel y análisis de tendencias
No utilizar para dashboards de monitoreo diario del SOC (use Incident Review en su lugar) — los dashboards de IR están diseñados para la coordinación de incidentes activos e informes de gestión.
Requisitos Previos
- Plataforma SIEM (Splunk con Dashboard Studio, Elastic Kibana o Grafana)
- Datos de eventos notables e incidentes en el SIEM (índice incident_review de Splunk ES)
- Integración con sistema de tickets (ServiceNow, Jira) para seguimiento de remediación
- Tablas de búsqueda de activos e identidades para enriquecimiento de contexto
- Acceso de publicación de dashboards para el equipo SOC y distribución a la gerencia
Flujo de Trabajo
Paso 1: Diseñar el Layout del Dashboard de Incidente Activo
Construir un dashboard en Splunk Dashboard Studio para seguimiento de incidentes activos:
<dashboard version="2" theme="dark">
<label>Active Incident Response Dashboard</label>
<description>Real-time tracking for IR-2024-0450</description>
<row>
<panel>
<title>Incident Summary</title>
<single>
<search>
<query>
| makeresults
| eval incident_id="IR-2024-0450",
status="CONTAINMENT",
severity="Critical",
affected_hosts=7,
contained_hosts=5,
iocs_identified=23,
hours_elapsed=round((now()-strptime("2024-03-15 14:00","%Y-%m-%d %H:%M"))/3600,1)
| table incident_id, status, severity, affected_hosts, contained_hosts, iocs_identified, hours_elapsed
</query>
</search>
</single>
</panel>
</row>
</dashboard>Paso 2: Construir el Panel de Sistemas Afectados en Tiempo Real
Rastrear sistemas afectados y su estado de contención:
| inputlookup ir_affected_systems.csv
| eval status_color = case(
status="Contained", "#2ecc71",
status="Compromised", "#e74c3c",
status="Investigating", "#f39c12",
status="Recovered", "#3498db",
1=1, "#95a5a6"
)
| stats count by status
| eval order = case(status="Compromised", 1, status="Investigating", 2,
status="Contained", 3, status="Recovered", 4)
| sort order
| table status, count
--- Tabla detallada de hosts
| inputlookup ir_affected_systems.csv
| lookup asset_lookup_by_cidr ip AS host_ip OUTPUT category, owner, priority
| table hostname, host_ip, category, owner, status, containment_time,
compromise_vector, analyst_assigned
| sort status, hostnamePaso 3: Construir el Panel de Seguimiento de IOCs
Monitorear la propagación de IOCs en el entorno:
--- IOCs identificados durante el incidente
index=* (src_ip IN ("185.234.218.50", "45.77.123.45") OR
dest IN ("evil-c2.com", "malware-drop.com") OR
file_hash IN ("a1b2c3d4...", "e5f6a7b8..."))
earliest="2024-03-14"
| stats count AS hits, dc(src_ip) AS unique_sources,
dc(dest) AS unique_dests, latest(_time) AS last_seen
by sourcetype
| sort - hits
--- Línea de tiempo de IOCs
index=* (src_ip IN ("185.234.218.50") OR dest="evil-c2.com")
earliest="2024-03-14"
| timechart span=1h count by sourcetype
--- Seguimiento de descubrimiento de nuevos IOCs
| inputlookup ir_ioc_list.csv
| stats count by ioc_type, source, discovery_time
| sort discovery_time
| table discovery_time, ioc_type, ioc_value, source, statusPaso 4: Construir el Panel de Línea de Tiempo de Respuesta
Crear una línea de tiempo cronológica del incidente:
| inputlookup ir_timeline.csv
| sort _time
| eval phase = case(
action_type="detection", "Detección",
action_type="triage", "Triaje",
action_type="containment", "Contención",
action_type="eradication", "Erradicación",
action_type="recovery", "Recuperación",
1=1, "Otro"
)
| eval phase_color = case(
phase="Detección", "#e74c3c",
phase="Triaje", "#f39c12",
phase="Contención", "#e67e22",
phase="Erradicación", "#2ecc71",
phase="Recuperación", "#3498db"
)
| table _time, phase, action, analyst, detailsEjemplo de datos de línea de tiempo:
_time,action_type,action,analyst,details
2024-03-15 14:00,detection,Alerta activada - Beacon de Cobalt Strike detectado,splunk_es,Evento notable NE-2024-08921
2024-03-15 14:12,triage,Alerta triada - verdadero positivo confirmado,analyst_jdoe,Puntuación VT 52/72 en hash del beacon
2024-03-15 14:23,containment,Host WORKSTATION-042 aislado,analyst_jdoe,Aislamiento de red con CrowdStrike
2024-03-15 14:35,containment,Dominio C2 bloqueado en firewall,analyst_msmith,Regla desplegada en Palo Alto
2024-03-15 15:00,eradication,Escaneo de IOCs a nivel empresarial iniciado,analyst_jdoe,Búsqueda en Splunk en todos los índices
2024-03-15 15:30,containment,3 hosts adicionales identificados y aislados,analyst_msmith,Movimiento lateral confirmado
2024-03-15 16:00,eradication,Malware eliminado de todos los hosts afectados,analyst_tier3,Limpieza con CrowdStrike RTR
2024-03-15 18:00,recovery,Sistemas restaurados y en monitoreo,analyst_msmith,Período de monitoreo de 72 horas iniciadoPaso 5: Construir el Dashboard de Operaciones del SOC
Rastrear las métricas generales de rendimiento del SOC:
--- Volumen de incidentes por severidad (últimos 30 días)
index=notable earliest=-30d
| stats count by urgency
| eval order = case(urgency="critical", 1, urgency="high", 2, urgency="medium", 3,
urgency="low", 4, urgency="informational", 5)
| sort order
--- MTTD (Tiempo Medio de Detección)
index=notable earliest=-30d status_label="Resolved*"
| eval mttd_minutes = round((time_of_first_event - orig_time) / 60, 1)
| stats avg(mttd_minutes) AS avg_mttd, median(mttd_minutes) AS med_mttd,
perc95(mttd_minutes) AS p95_mttd
--- MTTR (Tiempo Medio de Respuesta/Resolución)
index=notable earliest=-30d status_label="Resolved*"
| eval mttr_hours = round((status_end - _time) / 3600, 1)
| stats avg(mttr_hours) AS avg_mttr, median(mttr_hours) AS med_mttr by urgency
--- Distribución de carga de trabajo por analista
index=notable earliest=-7d
| stats count by owner
| sort - count
--- Desglose de disposición de alertas
index=notable earliest=-30d status_label IN ("Resolved*", "Closed*")
| stats count by disposition
| eval percentage = round(count / sum(count) * 100, 1)
| sort - countPaso 6: Construir el Dashboard de Sesión Informativa Ejecutiva
Crear un dashboard de alto nivel para la dirección durante incidentes mayores:
--- Panel de resumen ejecutivo
| makeresults
| eval metrics = "Impacto de Negocio: 1 servidor de archivos fuera de línea (depto. Finanzas), "
."Recuperación Estimada: 4 horas, "
."Riesgo de Pérdida de Datos: Bajo (respaldos verificados), "
."Impacto al Cliente: Ninguno, "
."Notificación Regulatoria: No requerida (sin exposición de PII confirmada)"
--- Comparación de tendencias (mes actual vs mes anterior)
index=notable earliest=-60d
| eval period = if(_time > relative_time(now(), "-30d"), "Mes Actual", "Mes Anterior")
| stats count by period, urgency
| chart sum(count) AS incidents by period, urgency
--- Principales categorías de amenazas
index=notable earliest=-30d
| top rule_name limit=10
| table rule_name, count, percentPaso 7: Automatizar las Actualizaciones del Dashboard
Usar búsquedas programadas de Splunk para mantener los datos del dashboard:
--- Búsqueda programada para actualizar la tabla de sistemas afectados (se ejecuta cada 5 minutos)
index=* (src_ip IN [| inputlookup ir_ioc_list.csv | search ioc_type="ip"
| fields ioc_value | rename ioc_value AS src_ip])
earliest=-1h
| stats latest(_time) AS last_seen, count AS event_count,
values(sourcetype) AS data_sources by src_ip
| eval status = if(last_seen > relative_time(now(), "-15m"), "Activo", "Inactivo")
| outputlookup ir_affected_systems_auto.csvConceptos Clave
| Término | Definición |
|---|---|
| Conciencia Situacional | Comprensión en tiempo real del alcance del incidente, sistemas afectados y progreso de la respuesta |
| MTTD | Tiempo Medio de Detección — tiempo promedio desde la ocurrencia de la amenaza hasta la generación de la alerta del SOC |
| MTTR | Tiempo Medio de Respuesta — tiempo promedio desde la alerta hasta la resolución o contención del incidente |
| Tasa de Contención | Porcentaje de sistemas afectados aislados exitosamente en relación con el total de sistemas comprometidos |
| Gráfico de Quema | Seguimiento visual de las tareas de investigación abiertas restantes a lo largo del tiempo durante un incidente |
| Sesión Informativa Ejecutiva | Dashboard de resumen no técnico que muestra el impacto en el negocio, la línea de tiempo y el estado de recuperación |
Herramientas y Sistemas
- Splunk Dashboard Studio: Framework moderno de dashboards con visualización de arrastrar y soltar y datos en tiempo real
- Elastic Kibana Dashboard: Plataforma de visualización con Lens, Maps y Canvas para dashboards de seguridad
- Grafana: Plataforma de visualización de código abierto que soporta múltiples fuentes de datos incluyendo Elasticsearch y Splunk
- Microsoft Sentinel Workbooks: Framework de dashboards nativo de Azure con visualización de analíticas basadas en Kusto
- TheHive: Plataforma de respuesta a incidentes de código abierto con seguimiento de casos integrado y dashboards de métricas
Escenarios Comunes
- Incidente de Ransomware Activo: Dashboard que muestra la propagación del cifrado, estado de contención, verificación de respaldos, progreso de recuperación
- Investigación de Brecha de Datos: Dashboard que rastrea almacenes de datos afectados, volumen de exfiltración, requisitos de notificación
- Respuesta a Campaña de Phishing: Dashboard que muestra el conteo de destinatarios, tasa de clics, exposición de credenciales, estado de remediación
- Informe Mensual del SOC: Dashboard para la dirección con tendencias de incidentes, métricas MTTD/MTTR, rendimiento de analistas
- Auditoría de Cumplimiento: Dashboard que demuestra cobertura de detección, cumplimiento de SLA de respuesta y métricas de cierre de incidentes
Formato de Salida
DASHBOARD DE RESPUESTA A INCIDENTES — IR-2024-0450
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ESTADO: FASE DE CONTENCIÓN (6h 30m transcurridas)
Sistemas Afectados: Progreso de Contención:
Comprometidos: 2 [==========----------] 71%
En Investigación: 1 5 de 7 sistemas contenidos
Contenidos: 3
Recuperados: 1
Resumen de IOCs: Línea de Tiempo de Respuesta:
IPs: 4 14:00 — Alerta activada
Dominios: 2 14:12 — Confirmado como malicioso
Hashes: 3 14:23 — Primer host aislado
URLs: 5 15:00 — Escaneo empresarial iniciado
Correos: 1 15:30 — 3 hosts más aislados
Métricas Clave:
MTTD: 12 minutos
MTTC: 23 minutos (primer host)
Analistas Activos: 3 (Nivel 2: 2, Nivel 3: 1)
Impacto de Negocio: BAJO — Servidor de archivos de Finanzas fuera de línea, sin afectación a sistemas orientados al clienteRelated skills
FAQ
Which platforms are supported?
Splunk with Dashboard Studio, Elastic Kibana, or Grafana, using notable-event and incident data from the SIEM.
When should I not use this skill?
For day-to-day SOC monitoring dashboards; these IR dashboards are designed for active incident coordination and management reporting.