Overview
A comprehensive Security Incident Response Playbook implementation in Java that automates incident handling, coordination, and remediation processes.
Core Incident Response Framework
1. Incident Management System
package com.example.security.incident; import org.springframework.stereotype.Service; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @Service public class IncidentManager { private final Map<String, SecurityIncident> activeIncidents = new ConcurrentHashMap<>(); private final Map<String, List<IncidentAction>> incidentActions = new ConcurrentHashMap<>(); private final IncidentNotifier notifier; private final IncidentRepository repository; public IncidentManager(IncidentNotifier notifier, IncidentRepository repository) { this.notifier = notifier; this.repository = repository; } public SecurityIncident createIncident(IncidentCreationRequest request) { SecurityIncident incident = new SecurityIncident(); incident.setId(generateIncidentId()); incident.setTitle(request.getTitle()); incident.setDescription(request.getDescription()); incident.setSeverity(request.getSeverity()); incident.setCategory(request.getCategory()); incident.setStatus(IncidentStatus.NEW); incident.setCreatedAt(new Date()); incident.setCreatedBy(request.getReporter()); incident.setLastUpdated(new Date()); // Apply incident classification classifyIncident(incident); // Store incident activeIncidents.put(incident.getId(), incident); repository.save(incident); // Trigger notifications notifier.notifyIncidentCreated(incident); // Execute initial response actions executeInitialResponse(incident); return incident; } public IncidentResponse escalateIncident(String incidentId, EscalationReason reason) { SecurityIncident incident = getIncident(incidentId); if (incident == null) { return new IncidentResponse(false, "Incident not found"); } IncidentEscalation escalation = new IncidentEscalation(); escalation.setIncidentId(incidentId); escalation.setReason(reason); escalation.setPreviousSeverity(incident.getSeverity()); escalation.setNewSeverity(calculateEscalatedSeverity(incident.getSeverity())); escalation.setEscalatedAt(new Date()); escalation.setEscalatedBy("System"); incident.setSeverity(escalation.getNewSeverity()); incident.setLastUpdated(new Date()); incident.addTimelineEvent(createTimelineEvent("INCIDENT_ESCALATED", "Incident escalated to " + escalation.getNewSeverity() + ": " + reason)); repository.save(incident); notifier.notifyIncidentEscalated(incident, escalation); return new IncidentResponse(true, "Incident escalated successfully"); } public IncidentResponse assignIncident(String incidentId, String assignee, String team) { SecurityIncident incident = getIncident(incidentId); if (incident == null) { return new IncidentResponse(false, "Incident not found"); } incident.setAssignee(assignee); incident.setAssignedTeam(team); incident.setStatus(IncidentStatus.INVESTIGATING); incident.setLastUpdated(new Date()); incident.addTimelineEvent(createTimelineEvent("INCIDENT_ASSIGNED", "Assigned to " + assignee + " (" + team + ")")); repository.save(incident); notifier.notifyIncidentAssigned(incident); return new IncidentResponse(true, "Incident assigned successfully"); } public IncidentResponse updateIncidentStatus(String incidentId, IncidentStatus status, String comment) { SecurityIncident incident = getIncident(incidentId); if (incident == null) { return new IncidentResponse(false, "Incident not found"); } IncidentStatus previousStatus = incident.getStatus(); incident.setStatus(status); incident.setLastUpdated(new Date()); incident.addTimelineEvent(createTimelineEvent("STATUS_CHANGED", "Status changed from " + previousStatus + " to " + status + ": " + comment)); repository.save(incident); notifier.notifyStatusUpdate(incident, previousStatus, status); // Execute status-specific actions executeStatusChangeActions(incident, previousStatus, status); return new IncidentResponse(true, "Incident status updated successfully"); } public IncidentResponse addEvidence(String incidentId, Evidence evidence) { SecurityIncident incident = getIncident(incidentId); if (incident == null) { return new IncidentResponse(false, "Incident not found"); } incident.addEvidence(evidence); incident.setLastUpdated(new Date()); incident.addTimelineEvent(createTimelineEvent("EVIDENCE_ADDED", "Evidence added: " + evidence.getType() + " - " + evidence.getDescription())); repository.save(incident); return new IncidentResponse(true, "Evidence added successfully"); } public IncidentResponse executeAction(String incidentId, IncidentAction action) { SecurityIncident incident = getIncident(incidentId); if (incident == null) { return new IncidentResponse(false, "Incident not found"); } action.setExecutedAt(new Date()); action.setStatus(ActionStatus.EXECUTING); // Store action incidentActions.computeIfAbsent(incidentId, k -> new ArrayList<>()).add(action); incident.addTimelineEvent(createTimelineEvent("ACTION_EXECUTED", "Action executed: " + action.getType() + " - " + action.getDescription())); // Execute the action try { ActionExecutor executor = getActionExecutor(action.getType()); ActionExecutionResult result = executor.execute(action, incident); action.setStatus(result.isSuccess() ? ActionStatus.COMPLETED : ActionStatus.FAILED); action.setResult(result.getMessage()); action.setCompletedAt(new Date()); incident.addTimelineEvent(createTimelineEvent("ACTION_COMPLETED", "Action " + (result.isSuccess() ? "completed" : "failed") + ": " + action.getType() + " - " + result.getMessage())); } catch (Exception e) { action.setStatus(ActionStatus.FAILED); action.setResult("Execution failed: " + e.getMessage()); incident.addTimelineEvent(createTimelineEvent("ACTION_FAILED", "Action failed: " + action.getType() + " - " + e.getMessage())); } repository.save(incident); return new IncidentResponse(true, "Action execution completed"); } public IncidentReport generateIncidentReport(String incidentId) { SecurityIncident incident = getIncident(incidentId); if (incident == null) { throw new IllegalArgumentException("Incident not found: " + incidentId); } List<IncidentAction> actions = incidentActions.getOrDefault(incidentId, Collections.emptyList()); return IncidentReport.builder() .incident(incident) .actions(actions) .timeline(incident.getTimeline()) .evidence(incident.getEvidence()) .metrics(calculateIncidentMetrics(incident, actions)) .recommendations(generateRecommendations(incident, actions)) .build(); } // Helper methods private void classifyIncident(SecurityIncident incident) { IncidentClassifier classifier = new IncidentClassifier(); IncidentClassification classification = classifier.classify(incident); incident.setCategory(classification.getCategory()); incident.setSubCategory(classification.getSubCategory()); incident.setConfidence(classification.getConfidence()); if (classification.getRecommendedSeverity() != null) { incident.setSeverity(classification.getRecommendedSeverity()); } } private void executeInitialResponse(SecurityIncident incident) { PlaybookExecutor playbook = new PlaybookExecutor(); List<IncidentAction> initialActions = playbook.getInitialResponseActions(incident); for (IncidentAction action : initialActions) { executeAction(incident.getId(), action); } } private void executeStatusChangeActions(SecurityIncident incident, IncidentStatus previousStatus, IncidentStatus newStatus) { PlaybookExecutor playbook = new PlaybookExecutor(); List<IncidentAction> statusActions = playbook.getStatusChangeActions( incident, previousStatus, newStatus); for (IncidentAction action : statusActions) { executeAction(incident.getId(), action); } } private IncidentSeverity calculateEscalatedSeverity(IncidentSeverity current) { switch (current) { case LOW: return IncidentSeverity.MEDIUM; case MEDIUM: return IncidentSeverity.HIGH; case HIGH: return IncidentSeverity.CRITICAL; case CRITICAL: return IncidentSeverity.CRITICAL; default: return IncidentSeverity.MEDIUM; } } private TimelineEvent createTimelineEvent(String type, String description) { TimelineEvent event = new TimelineEvent(); event.setType(type); event.setDescription(description); event.setTimestamp(new Date()); event.setActor("System"); return event; } private ActionExecutor getActionExecutor(ActionType type) { // Factory method to get appropriate executor switch (type) { case ISOLATE_SYSTEM: return new SystemIsolationExecutor(); case BLOCK_IP: return new IPBlockingExecutor(); case REVOKE_ACCESS: return new AccessRevocationExecutor(); case COLLECT_LOGS: return new LogCollectionExecutor(); case FORENSIC_ANALYSIS: return new ForensicAnalysisExecutor(); default: throw new IllegalArgumentException("Unknown action type: " + type); } } private IncidentMetrics calculateIncidentMetrics(SecurityIncident incident, List<IncidentAction> actions) { IncidentMetrics metrics = new IncidentMetrics(); metrics.setTimeToDetection(calculateTimeToDetection(incident)); metrics.setTimeToContainment(calculateTimeToContainment(incident, actions)); metrics.setTimeToResolution(calculateTimeToResolution(incident)); metrics.setActionsExecuted(actions.size()); metrics.setSuccessfulActions((int) actions.stream() .filter(a -> a.getStatus() == ActionStatus.COMPLETED) .count()); return metrics; } private long calculateTimeToDetection(SecurityIncident incident) { // Implementation would calculate time from first indicator to detection return 0L; } private long calculateTimeToContainment(SecurityIncident incident, List<IncidentAction> actions) { // Implementation would calculate time from detection to containment return 0L; } private long calculateTimeToResolution(SecurityIncident incident) { if (incident.getStatus() != IncidentStatus.RESOLVED) { return 0L; } // Calculate time from creation to resolution return incident.getResolvedAt().getTime() - incident.getCreatedAt().getTime(); } private List<String> generateRecommendations(SecurityIncident incident, List<IncidentAction> actions) { List<String> recommendations = new ArrayList<>(); // Generate recommendations based on incident type and actions taken if (incident.getCategory() == IncidentCategory.MALWARE) { recommendations.add("Conduct full system antivirus scan"); recommendations.add("Review and update antivirus signatures"); } if (incident.getCategory() == IncidentCategory.UNAUTHORIZED_ACCESS) { recommendations.add("Review and strengthen access controls"); recommendations.add("Implement multi-factor authentication"); } return recommendations; } private String generateIncidentId() { return "INC-" + System.currentTimeMillis() + "-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase(); } public SecurityIncident getIncident(String incidentId) { return activeIncidents.get(incidentId); } public List<SecurityIncident> getActiveIncidents() { return new ArrayList<>(activeIncidents.values()); } public List<SecurityIncident> getIncidentsByStatus(IncidentStatus status) { return activeIncidents.values().stream() .filter(incident -> incident.getStatus() == status) .collect(Collectors.toList()); } // Data Classes public static class SecurityIncident { private String id; private String title; private String description; private IncidentSeverity severity; private IncidentCategory category; private String subCategory; private IncidentStatus status; private String reporter; private String assignee; private String assignedTeam; private Date createdAt; private Date lastUpdated; private Date resolvedAt; private double confidence; private List<Evidence> evidence = new ArrayList<>(); private List<TimelineEvent> timeline = new ArrayList<>(); private Map<String, String> metadata = new HashMap<>(); // Getters and setters public String getId() { return id; } public void setId(String id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public IncidentSeverity getSeverity() { return severity; } public void setSeverity(IncidentSeverity severity) { this.severity = severity; } public IncidentCategory getCategory() { return category; } public void setCategory(IncidentCategory category) { this.category = category; } public String getSubCategory() { return subCategory; } public void setSubCategory(String subCategory) { this.subCategory = subCategory; } public IncidentStatus getStatus() { return status; } public void setStatus(IncidentStatus status) { this.status = status; } public String getReporter() { return reporter; } public void setReporter(String reporter) { this.reporter = reporter; } public String getAssignee() { return assignee; } public void setAssignee(String assignee) { this.assignee = assignee; } public String getAssignedTeam() { return assignedTeam; } public void setAssignedTeam(String assignedTeam) { this.assignedTeam = assignedTeam; } public Date getCreatedAt() { return createdAt; } public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; } public Date getLastUpdated() { return lastUpdated; } public void setLastUpdated(Date lastUpdated) { this.lastUpdated = lastUpdated; } public Date getResolvedAt() { return resolvedAt; } public void setResolvedAt(Date resolvedAt) { this.resolvedAt = resolvedAt; } public double getConfidence() { return confidence; } public void setConfidence(double confidence) { this.confidence = confidence; } public List<Evidence> getEvidence() { return evidence; } public void setEvidence(List<Evidence> evidence) { this.evidence = evidence; } public void addEvidence(Evidence evidence) { this.evidence.add(evidence); } public List<TimelineEvent> getTimeline() { return timeline; } public void setTimeline(List<TimelineEvent> timeline) { this.timeline = timeline; } public void addTimelineEvent(TimelineEvent event) { this.timeline.add(event); } public Map<String, String> getMetadata() { return metadata; } public void setMetadata(Map<String, String> metadata) { this.metadata = metadata; } } public enum IncidentSeverity { LOW, MEDIUM, HIGH, CRITICAL } public enum IncidentCategory { MALWARE, UNAUTHORIZED_ACCESS, DATA_BREACH, DOS_ATTACK, PHISHING, INSIDER_THREAT, CONFIGURATION_ERROR, VULNERABILITY_EXPLOIT } public enum IncidentStatus { NEW, INVESTIGATING, CONTAINED, ERADICATED, RESOLVED, CLOSED, REOPENED } public static class IncidentCreationRequest { private String title; private String description; private IncidentSeverity severity; private IncidentCategory category; private String reporter; // Getters and setters public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public IncidentSeverity getSeverity() { return severity; } public void setSeverity(IncidentSeverity severity) { this.severity = severity; } public IncidentCategory getCategory() { return category; } public void setCategory(IncidentCategory category) { this.category = category; } public String getReporter() { return reporter; } public void setReporter(String reporter) { this.reporter = reporter; } } public static class IncidentResponse { private boolean success; private String message; private String incidentId; public IncidentResponse(boolean success, String message) { this.success = success; this.message = message; } // Getters and setters public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getIncidentId() { return incidentId; } public void setIncidentId(String incidentId) { this.incidentId = incidentId; } } } Playbook Execution Engine
2. Automated Playbook Executor
package com.example.security.incident; import org.springframework.stereotype.Component; import java.util.*; @Component public class PlaybookExecutor { private final Map<IncidentCategory, IncidentPlaybook> playbooks; private final Map<IncidentStatus, List<ActionType>> statusActions; public PlaybookExecutor() { this.playbooks = loadPlaybooks(); this.statusActions = loadStatusActions(); } public List<IncidentAction> getInitialResponseActions(SecurityIncident incident) { IncidentPlaybook playbook = playbooks.get(incident.getCategory()); if (playbook == null) { return getDefaultInitialActions(incident); } return playbook.getInitialResponseActions(incident); } public List<IncidentAction> getContainmentActions(SecurityIncident incident) { IncidentPlaybook playbook = playbooks.get(incident.getCategory()); if (playbook == null) { return getDefaultContainmentActions(incident); } return playbook.getContainmentActions(incident); } public List<IncidentAction> getEradicationActions(SecurityIncident incident) { IncidentPlaybook playbook = playbooks.get(incident.getCategory()); if (playbook == null) { return getDefaultEradicationActions(incident); } return playbook.getEradicationActions(incident); } public List<IncidentAction> getRecoveryActions(SecurityIncident incident) { IncidentPlaybook playbook = playbooks.get(incident.getCategory()); if (playbook == null) { return getDefaultRecoveryActions(incident); } return playbook.getRecoveryActions(incident); } public List<IncidentAction> getStatusChangeActions(SecurityIncident incident, IncidentStatus previousStatus, IncidentStatus newStatus) { List<IncidentAction> actions = new ArrayList<>(); if (newStatus == IncidentStatus.CONTAINED) { actions.addAll(getContainmentActions(incident)); } else if (newStatus == IncidentStatus.ERADICATED) { actions.addAll(getEradicationActions(incident)); } else if (newStatus == IncidentStatus.RESOLVED) { actions.addAll(getRecoveryActions(incident)); } return actions; } public IncidentPlaybook getPlaybook(IncidentCategory category) { return playbooks.get(category); } public void executePlaybookStep(String incidentId, String stepId) { // Implementation for executing specific playbook steps } // Default action implementations private List<IncidentAction> getDefaultInitialActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); // Common initial actions for any incident actions.add(createAction(ActionType.COLLECT_LOGS, "Collect relevant system and application logs", incident)); actions.add(createAction(ActionType.PRESERVE_EVIDENCE, "Preserve current system state for forensic analysis", incident)); actions.add(createAction(ActionType.NOTIFY_STAKEHOLDERS, "Notify relevant stakeholders about the incident", incident)); return actions; } private List<IncidentAction> getDefaultContainmentActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); if (incident.getSeverity() == IncidentSeverity.HIGH || incident.getSeverity() == IncidentSeverity.CRITICAL) { actions.add(createAction(ActionType.ISOLATE_SYSTEM, "Isolate affected systems from network", incident)); } actions.add(createAction(ActionType.BLOCK_IP, "Block malicious IP addresses", incident)); actions.add(createAction(ActionType.REVOKE_ACCESS, "Revoke compromised user access", incident)); return actions; } private List<IncidentAction> getDefaultEradicationActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.REMOVE_MALWARE, "Remove identified malware or malicious code", incident)); actions.add(createAction(ActionType.PATCH_VULNERABILITIES, "Apply security patches for exploited vulnerabilities", incident)); actions.add(createAction(ActionType.CHANGE_CREDENTIALS, "Change compromised passwords and keys", incident)); return actions; } private List<IncidentAction> getDefaultRecoveryActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.RESTORE_SYSTEMS, "Restore systems from clean backups", incident)); actions.add(createAction(ActionType.VERIFY_INTEGRITY, "Verify system integrity and functionality", incident)); actions.add(createAction(ActionType.MONITOR_SYSTEMS, "Enhanced monitoring of recovered systems", incident)); return actions; } private IncidentAction createAction(ActionType type, String description, SecurityIncident incident) { IncidentAction action = new IncidentAction(); action.setId(generateActionId()); action.setType(type); action.setDescription(description); action.setIncidentId(incident.getId()); action.setCreatedAt(new Date()); action.setStatus(ActionStatus.PENDING); return action; } private Map<IncidentCategory, IncidentPlaybook> loadPlaybooks() { Map<IncidentCategory, IncidentPlaybook> playbooks = new HashMap<>(); // Malware Incident Playbook playbooks.put(IncidentCategory.MALWARE, createMalwarePlaybook()); // Unauthorized Access Playbook playbooks.put(IncidentCategory.UNAUTHORIZED_ACCESS, createUnauthorizedAccessPlaybook()); // Data Breach Playbook playbooks.put(IncidentCategory.DATA_BREACH, createDataBreachPlaybook()); // DDoS Attack Playbook playbooks.put(IncidentCategory.DOS_ATTACK, createDDoSPlaybook()); return playbooks; } private Map<IncidentStatus, List<ActionType>> loadStatusActions() { Map<IncidentStatus, List<ActionType>> actions = new HashMap<>(); actions.put(IncidentStatus.INVESTIGATING, Arrays.asList( ActionType.COLLECT_LOGS, ActionType.ANALYZE_LOGS, ActionType.IDENTIFY_SCOPE )); actions.put(IncidentStatus.CONTAINED, Arrays.asList( ActionType.ISOLATE_SYSTEM, ActionType.BLOCK_IP, ActionType.REVOKE_ACCESS )); actions.put(IncidentStatus.ERADICATED, Arrays.asList( ActionType.REMOVE_MALWARE, ActionType.PATCH_VULNERABILITIES, ActionType.CHANGE_CREDENTIALS )); actions.put(IncidentStatus.RESOLVED, Arrays.asList( ActionType.RESTORE_SYSTEMS, ActionType.VERIFY_INTEGRITY, ActionType.MONITOR_SYSTEMS )); return actions; } private IncidentPlaybook createMalwarePlaybook() { return new IncidentPlaybook() { @Override public List<IncidentAction> getInitialResponseActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.ISOLATE_SYSTEM, "Isolate infected system from network", incident)); actions.add(createAction(ActionType.COLLECT_MALWARE_SAMPLES, "Collect malware samples for analysis", incident)); actions.add(createAction(ActionType.SCAN_NETWORK, "Scan network for similar infections", incident)); return actions; } @Override public List<IncidentAction> getContainmentActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.QUARANTINE_MALWARE, "Quarantine identified malware", incident)); actions.add(createAction(ActionType.BLOCK_COMMUNICATION, "Block C&C server communication", incident)); return actions; } @Override public List<IncidentAction> getEradicationActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.REMOVE_MALWARE, "Remove malware using antivirus tools", incident)); actions.add(createAction(ActionType.CLEAN_SYSTEM, "Clean infected system thoroughly", incident)); return actions; } }; } private IncidentPlaybook createUnauthorizedAccessPlaybook() { return new IncidentPlaybook() { @Override public List<IncidentAction> getInitialResponseActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.REVOKE_ACCESS, "Revoke compromised account access", incident)); actions.add(createAction(ActionType.ANALYZE_ACCESS_LOGS, "Analyze authentication and access logs", incident)); actions.add(createAction(ActionType.IDENTIFY_ACCESS_METHOD, "Identify method of unauthorized access", incident)); return actions; } @Override public List<IncidentAction> getContainmentActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.BLOCK_IP, "Block source IP addresses", incident)); actions.add(createAction(ActionType.DISABLE_ACCOUNTS, "Disable compromised accounts", incident)); return actions; } @Override public List<IncidentAction> getEradicationActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.PATCH_VULNERABILITIES, "Patch exploited vulnerabilities", incident)); actions.add(createAction(ActionType.STRENGTHEN_AUTHENTICATION, "Strengthen authentication mechanisms", incident)); return actions; } }; } private IncidentPlaybook createDataBreachPlaybook() { return new IncidentPlaybook() { @Override public List<IncidentAction> getInitialResponseActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.IDENTIFY_DATA_SCOPE, "Identify scope of compromised data", incident)); actions.add(createAction(ActionType.SECURE_DATA_STORAGE, "Secure remaining data storage", incident)); actions.add(createAction(ActionType.NOTIFY_LEGAL, "Notify legal team for compliance requirements", incident)); return actions; } @Override public List<IncidentAction> getContainmentActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.BLOCK_DATA_EXFILTRATION, "Block data exfiltration channels", incident)); actions.add(createAction(ActionType.ENCRYPT_SENSITIVE_DATA, "Encrypt remaining sensitive data", incident)); return actions; } @Override public List<IncidentAction> getEradicationActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.IMPLEMENT_ACCESS_CONTROLS, "Implement stronger data access controls", incident)); actions.add(createAction(ActionType.MONITOR_DATA_ACCESS, "Implement enhanced data access monitoring", incident)); return actions; } }; } private IncidentPlaybook createDDoSPlaybook() { return new IncidentPlaybook() { @Override public List<IncidentAction> getInitialResponseActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.ACTIVATE_DDOS_PROTECTION, "Activate DDoS mitigation services", incident)); actions.add(createAction(ActionType.ANALYZE_TRAFFIC_PATTERNS, "Analyze attack traffic patterns", incident)); actions.add(createAction(ActionType.NOTIFY_ISP, "Notify ISP for upstream mitigation", incident)); return actions; } @Override public List<IncidentAction> getContainmentActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.BLOCK_MALICIOUS_TRAFFIC, "Block malicious traffic at network perimeter", incident)); actions.add(createAction(ActionType.RATE_LIMIT_REQUESTS, "Implement request rate limiting", incident)); return actions; } @Override public List<IncidentAction> getEradicationActions(SecurityIncident incident) { List<IncidentAction> actions = new ArrayList<>(); actions.add(createAction(ActionType.IMPLEMENT_TRAFFIC_FILTERING, "Implement permanent traffic filtering rules", incident)); actions.add(createAction(ActionType.ENHANCE_CAPACITY, "Enhance infrastructure capacity", incident)); return actions; } }; } private String generateActionId() { return "ACT-" + System.currentTimeMillis() + "-" + UUID.randomUUID().toString().substring(0, 6).toUpperCase(); } // Interface for playbooks public interface IncidentPlaybook { List<IncidentAction> getInitialResponseActions(SecurityIncident incident); List<IncidentAction> getContainmentActions(SecurityIncident incident); List<IncidentAction> getEradicationActions(SecurityIncident incident); default List<IncidentAction> getRecoveryActions(SecurityIncident incident) { return getDefaultRecoveryActions(incident); } } } Action Execution Framework
3. Action Executors
package com.example.security.incident; import org.springframework.stereotype.Component; import java.util.*; // Base interface for all action executors @Component public interface ActionExecutor { ActionExecutionResult execute(IncidentAction action, SecurityIncident incident); ActionType getSupportedActionType(); } // System Isolation Executor @Component public class SystemIsolationExecutor implements ActionExecutor { private final NetworkService networkService; private final SystemInventoryService inventoryService; public SystemIsolationExecutor(NetworkService networkService, SystemInventoryService inventoryService) { this.networkService = networkService; this.inventoryService = inventoryService; } @Override public ActionExecutionResult execute(IncidentAction action, SecurityIncident incident) { try { // Extract target systems from action parameters or incident evidence List<String> targetSystems = extractTargetSystems(action, incident); if (targetSystems.isEmpty()) { return new ActionExecutionResult(false, "No target systems specified for isolation"); } List<String> isolationResults = new ArrayList<>(); for (String system : targetSystems) { // Isolate system from network boolean isolated = networkService.isolateSystem(system); if (isolated) { isolationResults.add("Successfully isolated: " + system); } else { isolationResults.add("Failed to isolate: " + system); } } String message = String.format("Isolated %d systems: %s", targetSystems.size(), String.join(", ", isolationResults)); return new ActionExecutionResult(true, message); } catch (Exception e) { return new ActionExecutionResult(false, "System isolation failed: " + e.getMessage()); } } @Override public ActionType getSupportedActionType() { return ActionType.ISOLATE_SYSTEM; } private List<String> extractTargetSystems(IncidentAction action, SecurityIncident incident) { List<String> systems = new ArrayList<>(); // Extract from action parameters if (action.getParameters() != null && action.getParameters().containsKey("targetSystems")) { String[] targetSystems = action.getParameters().get("targetSystems").split(","); systems.addAll(Arrays.asList(targetSystems)); } // Extract from incident evidence for (Evidence evidence : incident.getEvidence()) { if (evidence.getType() == EvidenceType.SYSTEM_LOG && evidence.getContent().contains("compromised")) { // Parse system identifiers from evidence String systemId = extractSystemIdFromEvidence(evidence); if (systemId != null) { systems.add(systemId); } } } return systems; } private String extractSystemIdFromEvidence(Evidence evidence) { // Implementation to extract system identifier from evidence return "system-" + evidence.getId(); } } // IP Blocking Executor @Component public class IPBlockingExecutor implements ActionExecutor { private final FirewallService firewallService; private final ThreatIntelligenceService threatIntelService; public IPBlockingExecutor(FirewallService firewallService, ThreatIntelligenceService threatIntelService) { this.firewallService = firewallService; this.threatIntelService = threatIntelService; } @Override public ActionExecutionResult execute(IncidentAction action, SecurityIncident incident) { try { Set<String> ipsToBlock = extractIPsToBlock(action, incident); if (ipsToBlock.isEmpty()) { return new ActionExecutionResult(false, "No IP addresses specified for blocking"); } List<String> blockResults = new ArrayList<>(); int successfullyBlocked = 0; for (String ip : ipsToBlock) { if (isValidIP(ip) && !isInternalIP(ip)) { boolean blocked = firewallService.blockIP(ip, "Security Incident: " + incident.getId()); if (blocked) { successfullyBlocked++; blockResults.add("Blocked: " + ip); // Add to threat intelligence threatIntelService.addMaliciousIP(ip, incident.getId(), "Blocked during incident response"); } else { blockResults.add("Failed to block: " + ip); } } else { blockResults.add("Skipped invalid/internal IP: " + ip); } } String message = String.format("Blocked %d/%d IPs: %s", successfullyBlocked, ipsToBlock.size(), String.join(", ", blockResults)); return new ActionExecutionResult(true, message); } catch (Exception e) { return new ActionExecutionResult(false, "IP blocking failed: " + e.getMessage()); } } @Override public ActionType getSupportedActionType() { return ActionType.BLOCK_IP; } private Set<String> extractIPsToBlock(IncidentAction action, SecurityIncident incident) { Set<String> ips = new HashSet<>(); // Extract from action parameters if (action.getParameters() != null && action.getParameters().containsKey("ipAddresses")) { String[] ipArray = action.getParameters().get("ipAddresses").split(","); ips.addAll(Arrays.asList(ipArray)); } // Extract from incident evidence for (Evidence evidence : incident.getEvidence()) { if (evidence.getType() == EvidenceType.NETWORK_LOG) { Set<String> foundIPs = extractIPsFromEvidence(evidence); ips.addAll(foundIPs); } } return ips; } private Set<String> extractIPsFromEvidence(Evidence evidence) { // Implementation to extract IP addresses from evidence content Set<String> ips = new HashSet<>(); // Simple IP regex pattern matching String ipPattern = "\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b"; // Actual implementation would use proper IP parsing return ips; } private boolean isValidIP(String ip) { // Basic IP validation return ip.matches("\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b"); } private boolean isInternalIP(String ip) { // Check if IP is in private ranges return ip.startsWith("10.") || ip.startsWith("192.168.") || (ip.startsWith("172.") && isInPrivateRange(ip)); } private boolean isInPrivateRange(String ip) { // Check 172.16.0.0 - 172.31.255.255 String[] parts = ip.split("\\."); if (parts.length >= 2) { int secondOctet = Integer.parseInt(parts[1]); return secondOctet >= 16 && secondOctet <= 31; } return false; } } // Access Revocation Executor @Component public class AccessRevocationExecutor implements ActionExecutor { private final IdentityManagementService idmService; private final AccessReviewService accessReviewService; public AccessRevocationExecutor(IdentityManagementService idmService, AccessReviewService accessReviewService) { this.idmService = idmService; this.accessReviewService = accessReviewService; } @Override public ActionExecutionResult execute(IncidentAction action, SecurityIncident incident) { try { Set<String> usersToRevoke = extractUsersToRevoke(action, incident); if (usersToRevoke.isEmpty()) { return new ActionExecutionResult(false, "No users specified for access revocation"); } List<String> revocationResults = new ArrayList<>(); int successfullyRevoked = 0; for (String username : usersToRevoke) { boolean revoked = idmService.revokeUserAccess(username, "Security Incident: " + incident.getId()); if (revoked) { successfullyRevoked++; revocationResults.add("Revoked: " + username); // Schedule access review accessReviewService.scheduleUserAccessReview(username, "Post-incident access review"); } else { revocationResults.add("Failed to revoke: " + username); } } String message = String.format("Revoked access for %d/%d users: %s", successfullyRevoked, usersToRevoke.size(), String.join(", ", revocationResults)); return new ActionExecutionResult(true, message); } catch (Exception e) { return new ActionExecutionResult(false, "Access revocation failed: " + e.getMessage()); } } @Override public ActionType getSupportedActionType() { return ActionType.REVOKE_ACCESS; } private Set<String> extractUsersToRevoke(IncidentAction action, SecurityIncident incident) { Set<String> users = new HashSet<>(); // Extract from action parameters if (action.getParameters() != null && action.getParameters().containsKey("usernames")) { String[] userArray = action.getParameters().get("usernames").split(","); users.addAll(Arrays.asList(userArray)); } // Extract from incident evidence for (Evidence evidence : incident.getEvidence()) { if (evidence.getType() == EvidenceType.ACCESS_LOG) { Set<String> foundUsers = extractUsersFromEvidence(evidence); users.addAll(foundUsers); } } return users; } private Set<String> extractUsersFromEvidence(Evidence evidence) { // Implementation to extract usernames from evidence content return new HashSet<>(); } } // Data Classes for Actions public class IncidentAction { private String id; private ActionType type; private String description; private String incidentId; private ActionStatus status; private Date createdAt; private Date executedAt; private Date completedAt; private String result; private Map<String, String> parameters = new HashMap<>(); // Getters and setters public String getId() { return id; } public void setId(String id) { this.id = id; } public ActionType getType() { return type; } public void setType(ActionType type) { this.type = type; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getIncidentId() { return incidentId; } public void setIncidentId(String incidentId) { this.incidentId = incidentId; } public ActionStatus getStatus() { return status; } public void setStatus(ActionStatus status) { this.status = status; } public Date getCreatedAt() { return createdAt; } public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; } public Date getExecutedAt() { return executedAt; } public void setExecutedAt(Date executedAt) { this.executedAt = executedAt; } public Date getCompletedAt() { return completedAt; } public void setCompletedAt(Date completedAt) { this.completedAt = completedAt; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } public Map<String, String> getParameters() { return parameters; } public void setParameters(Map<String, String> parameters) { this.parameters = parameters; } } public enum ActionType { ISOLATE_SYSTEM, BLOCK_IP, REVOKE_ACCESS, COLLECT_LOGS, COLLECT_MALWARE_SAMPLES, SCAN_NETWORK, QUARANTINE_MALWARE, BLOCK_COMMUNICATION, REMOVE_MALWARE, CLEAN_SYSTEM, ANALYZE_ACCESS_LOGS, IDENTIFY_ACCESS_METHOD, DISABLE_ACCOUNTS, PATCH_VULNERABILITIES, STRENGTHEN_AUTHENTICATION, IDENTIFY_DATA_SCOPE, SECURE_DATA_STORAGE, NOTIFY_LEGAL, BLOCK_DATA_EXFILTRATION, ENCRYPT_SENSITIVE_DATA, IMPLEMENT_ACCESS_CONTROLS, MONITOR_DATA_ACCESS, ACTIVATE_DDOS_PROTECTION, ANALYZE_TRAFFIC_PATTERNS, NOTIFY_ISP, BLOCK_MALICIOUS_TRAFFIC, RATE_LIMIT_REQUESTS, IMPLEMENT_TRAFFIC_FILTERING, ENHANCE_CAPACITY, PRESERVE_EVIDENCE, NOTIFY_STAKEHOLDERS, ANALYZE_LOGS, IDENTIFY_SCOPE, CHANGE_CREDENTIALS, RESTORE_SYSTEMS, VERIFY_INTEGRITY, MONITOR_SYSTEMS, FORENSIC_ANALYSIS } public enum ActionStatus { PENDING, EXECUTING, COMPLETED, FAILED, CANCELLED } public class ActionExecutionResult { private boolean success; private String message; private Map<String, Object> details = new HashMap<>(); public ActionExecutionResult(boolean success, String message) { this.success = success; this.message = message; } // Getters and setters public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Map<String, Object> getDetails() { return details; } public void setDetails(Map<String, Object> details) { this.details = details; } } Incident Classification and Analysis
4. Intelligent Incident Classifier
package com.example.security.incident; import org.springframework.stereotype.Component; import java.util.*; import java.util.regex.Pattern; @Component public class IncidentClassifier { private final Map<Pattern, IncidentCategory> patternCategories; private final Map<String, Double> keywordWeights; public IncidentClassifier() { this.patternCategories = initializePatterns(); this.keywordWeights = initializeKeywordWeights(); } public IncidentClassification classify(SecurityIncident incident) { String text = incident.getTitle() + " " + incident.getDescription(); text = text.toLowerCase(); Map<IncidentCategory, Double> categoryScores = new HashMap<>(); Map<String, Double> featureScores = new HashMap<>(); // Pattern-based classification for (Map.Entry<Pattern, IncidentCategory> entry : patternCategories.entrySet()) { if (entry.getKey().matcher(text).find()) { categoryScores.merge(entry.getValue(), 1.0, Double::sum); } } // Keyword-based classification for (Map.Entry<String, Double> entry : keywordWeights.entrySet()) { if (text.contains(entry.getKey())) { String category = getCategoryFromKeyword(entry.getKey()); IncidentCategory incidentCategory = IncidentCategory.valueOf(category); categoryScores.merge(incidentCategory, entry.getValue(), Double::sum); featureScores.put(entry.getKey(), entry.getValue()); } } // Determine primary category IncidentCategory primaryCategory = determinePrimaryCategory(categoryScores); String subCategory = determineSubCategory(primaryCategory, featureScores); double confidence = calculateConfidence(categoryScores, primaryCategory); // Determine severity based on features IncidentSeverity recommendedSeverity = determineSeverity(primaryCategory, featureScores); return new IncidentClassification(primaryCategory, subCategory, confidence, recommendedSeverity); } public List<IncidentCategory> getPossibleCategories(SecurityIncident incident) { IncidentClassification classification = classify(incident); // Return top 3 possible categories based on confidence return Arrays.asList( classification.getCategory(), getSecondaryCategory(incident), getTertiaryCategory(incident) ); } public boolean requiresImmediateAttention(SecurityIncident incident) { IncidentClassification classification = classify(incident); return classification.getConfidence() > 0.8 && (classification.getRecommendedSeverity() == IncidentSeverity.HIGH || classification.getRecommendedSeverity() == IncidentSeverity.CRITICAL); } // Helper methods private Map<Pattern, IncidentCategory> initializePatterns() { Map<Pattern, IncidentCategory> patterns = new HashMap<>(); // Malware patterns patterns.put(Pattern.compile("\\b(malware|virus|trojan|ransomware|worm)\\b"), IncidentCategory.MALWARE); patterns.put(Pattern.compile("\\b(infected|compromised.system)\\b"), IncidentCategory.MALWARE); // Unauthorized access patterns patterns.put(Pattern.compile("\\b(unauthorized.access|breach|intrusion|hack)\\b"), IncidentCategory.UNAUTHORIZED_ACCESS); patterns.put(Pattern.compile("\\b(credential.theft|password.breach)\\b"), IncidentCategory.UNAUTHORIZED_ACCESS); // Data breach patterns patterns.put(Pattern.compile("\\b(data.breach|data.leak|pii.exposure)\\b"), IncidentCategory.DATA_BREACH); patterns.put(Pattern.compile("\\b(sensitive.data|personal.information)\\b"), IncidentCategory.DATA_BREACH); // DDoS patterns patterns.put(Pattern.compile("\\b(ddos|denial.of.service|service.unavailable)\\b"), IncidentCategory.DOS_ATTACK); patterns.put(Pattern.compile("\\b(flood.attack|traffic.surge)\\b"), IncidentCategory.DOS_ATTACK); return patterns; } private Map<String, Double> initializeKeywordWeights() { Map<String, Double> weights = new HashMap<>(); // Malware keywords weights.put("malware", 2.0); weights.put("virus", 1.5); weights.put("ransomware", 2.5); weights.put("infected", 1.0); // Access compromise keywords weights.put("unauthorized", 2.0); weights.put("breach", 2.5); weights.put("compromised", 1.5); weights.put("intrusion", 2.0); // Data exposure keywords weights.put("data leak", 3.0); weights.put("pii", 2.5); weights.put("sensitive", 1.5); // Availability keywords weights.put("ddos", 2.0); weights.put("outage", 1.5); weights.put("unavailable", 1.0); return weights; } private String getCategoryFromKeyword(String keyword) { // Map keywords to categories switch (keyword) { case "malware": case "virus": case "ransomware": case "infected": return "MALWARE"; case "unauthorized": case "breach": case "compromised": case "intrusion": return "UNAUTHORIZED_ACCESS"; case "data leak": case "pii": case "sensitive": return "DATA_BREACH"; case "ddos": case "outage": case "unavailable": return "DOS_ATTACK"; default: return "UNAUTHORIZED_ACCESS"; } } private IncidentCategory determinePrimaryCategory(Map<IncidentCategory, Double> scores) { return scores.entrySet().stream() .max(Map.Entry.comparingByValue()) .map(Map.Entry::getKey) .orElse(IncidentCategory.UNAUTHORIZED_ACCESS); } private String determineSubCategory(IncidentCategory category, Map<String, Double> features) { switch (category) { case MALWARE: return determineMalwareSubCategory(features); case UNAUTHORIZED_ACCESS: return determineAccessSubCategory(features); case DATA_BREACH: return determineBreachSubCategory(features); case DOS_ATTACK: return determineDDoSSubCategory(features); default: return "GENERIC"; } } private String determineMalwareSubCategory(Map<String, Double> features) { if (features.containsKey("ransomware")) return "RANSOMWARE"; if (features.containsKey("trojan")) return "TROJAN"; if (features.containsKey("virus")) return "VIRUS"; return "MALWARE_GENERIC"; } private String determineAccessSubCategory(Map<String, Double> features) { if (features.containsKey("credential")) return "CREDENTIAL_THEFT"; if (features.containsKey("privilege")) return "PRIVILEGE_ESCALATION"; return "UNAUTHORIZED_ACCESS_GENERIC"; } private String determineBreachSubCategory(Map<String, Double> features) { if (features.containsKey("pii")) return "PII_EXPOSURE"; if (features.containsKey("financial")) return "FINANCIAL_DATA_BREACH"; return "DATA_BREACH_GENERIC"; } private String determineDDoSSubCategory(Map<String, Double> features) { if (features.containsKey("application")) return "APPLICATION_DDOS"; if (features.containsKey("network")) return "NETWORK_DDOS"; return "DOS_ATTACK_GENERIC"; } private double calculateConfidence(Map<IncidentCategory, Double> scores, IncidentCategory primary) { double primaryScore = scores.getOrDefault(primary, 0.0); double totalScore = scores.values().stream().mapToDouble(Double::doubleValue).sum(); if (totalScore == 0) return 0.0; return primaryScore / totalScore; } private IncidentSeverity determineSeverity(IncidentCategory category, Map<String, Double> features) { // Base severity based on category Map<IncidentCategory, IncidentSeverity> baseSeverity = new HashMap<>(); baseSeverity.put(IncidentCategory.MALWARE, IncidentSeverity.HIGH); baseSeverity.put(IncidentCategory.UNAUTHORIZED_ACCESS, IncidentSeverity.HIGH); baseSeverity.put(IncidentCategory.DATA_BREACH, IncidentSeverity.CRITICAL); baseSeverity.put(IncidentCategory.DOS_ATTACK, IncidentSeverity.MEDIUM); IncidentSeverity severity = baseSeverity.getOrDefault(category, IncidentSeverity.MEDIUM); // Adjust based on features if (features.containsKey("ransomware")) { severity = IncidentSeverity.CRITICAL; } if (features.containsKey("pii") && category == IncidentCategory.DATA_BREACH) { severity = IncidentSeverity.CRITICAL; } return severity; } private IncidentCategory getSecondaryCategory(SecurityIncident incident) { // Implementation to determine secondary category return IncidentCategory.UNAUTHORIZED_ACCESS; } private IncidentCategory getTertiaryCategory(SecurityIncident incident) { // Implementation to determine tertiary category return IncidentCategory.CONFIGURATION_ERROR; } // Data Classes public static class IncidentClassification { private final IncidentCategory category; private final String subCategory; private final double confidence; private final IncidentSeverity recommendedSeverity; public IncidentClassification(IncidentCategory category, String subCategory, double confidence, IncidentSeverity recommendedSeverity) { this.category = category; this.subCategory = subCategory; this.confidence = confidence; this.recommendedSeverity = recommendedSeverity; } // Getters public IncidentCategory getCategory() { return category; } public String getSubCategory() { return subCategory; } public double getConfidence() { return confidence; } public IncidentSeverity getRecommendedSeverity() { return recommendedSeverity; } } } Spring Boot Configuration
5. Application Configuration
package com.example.security.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class IncidentResponseConfig { @Value("${incident.response.notification.enabled:true}") private boolean notificationEnabled; @Value("${incident.response.escalation.enabled:true}") private boolean escalationEnabled; @Value("${incident.response.auto.containment.enabled:false}") private boolean autoContainmentEnabled; @Value("${incident.response.playbook.default:standard}") private String defaultPlaybook; @Bean public IncidentManager incidentManager(IncidentNotifier notifier, IncidentRepository repository) { return new IncidentManager(notifier, repository); } @Bean public PlaybookExecutor playbookExecutor() { return new PlaybookExecutor(); } @Bean public IncidentClassifier incidentClassifier() { return new IncidentClassifier(); } @Bean public SystemIsolationExecutor systemIsolationExecutor() { return new SystemIsolationExecutor(); } @Bean public IPBlockingExecutor ipBlockingExecutor() { return new IPBlockingExecutor(); } @Bean public AccessRevocationExecutor accessRevocationExecutor() { return new AccessRevocationExecutor(); } } // application.yml incident: response: notification: enabled: true channels: - email - slack - sms escalation: enabled: true thresholds: critical: 30 # minutes high: 60 # minutes auto-containment: enabled: false actions: - BLOCK_IP - REVOKE_ACCESS playbook: default: standard custom: malware: malware-response data-breach: data-breach-response security: incident: retention-days: 365 backup-enabled: true encryption-enabled: true logging: level: com.example.security.incident: INFO This comprehensive Security Incident Response Playbook implementation provides:
- Incident Management - Creation, tracking, and lifecycle management
- Playbook Execution - Automated response workflows for different incident types
- Action Automation - Executors for containment, eradication, and recovery actions
- Intelligent Classification - AI-powered incident categorization and severity assessment
- Comprehensive Reporting - Detailed incident reports with metrics and recommendations
The system enables organizations to respond to security incidents quickly, consistently, and effectively while maintaining detailed audit trails and compliance with security frameworks.