mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-20 14:30:59 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
---
|
||||
name: containing-active-security-breach
|
||||
description: Rapidly contain an active security breach by isolating compromised systems, blocking attacker communications, and preserving evidence while minimizing business disruption.
|
||||
domain: cybersecurity
|
||||
subdomain: incident-response
|
||||
tags: [incident-response, containment, breach-response, network-isolation, dfir]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Containing an Active Security Breach
|
||||
|
||||
## When to Use
|
||||
- Active unauthorized access detected on network or systems
|
||||
- IDS/IPS alerts indicate ongoing exploitation or data exfiltration
|
||||
- SOC analysts confirm a true positive security incident requiring immediate containment
|
||||
- Lateral movement or privilege escalation observed in real time
|
||||
- Ransomware encryption activity detected before full deployment
|
||||
|
||||
## Prerequisites
|
||||
- Incident Response Plan with defined containment procedures
|
||||
- Network access to firewalls, switches, and endpoint management consoles
|
||||
- EDR/XDR platform deployed across endpoints (CrowdStrike, SentinelOne, Microsoft Defender for Endpoint)
|
||||
- SIEM access with real-time log correlation (Splunk, Elastic, QRadar)
|
||||
- Pre-approved authority to isolate systems (documented in IR plan)
|
||||
- Forensic imaging tools ready for evidence preservation
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Validate and Classify the Incident
|
||||
```bash
|
||||
# Check SIEM for correlated alerts - Splunk example
|
||||
index=security sourcetype=ids_alerts severity=critical
|
||||
| stats count by src_ip, dest_ip, signature
|
||||
| where count > 5
|
||||
| sort -count
|
||||
|
||||
# Verify endpoint alerts via CrowdStrike Falcon API
|
||||
curl -X GET "https://api.crowdstrike.com/detects/queries/detects/v1?filter=status:'new'+max_severity_displayname:'Critical'" \
|
||||
-H "Authorization: Bearer $FALCON_TOKEN"
|
||||
```
|
||||
|
||||
### Step 2: Identify Scope of Compromise
|
||||
```bash
|
||||
# Identify all systems communicating with attacker C2
|
||||
# Using Zeek connection logs
|
||||
cat conn.log | zeek-cut id.orig_h id.resp_h id.resp_p duration orig_bytes resp_bytes \
|
||||
| awk '$3 == 443 && $5 > 1000000' | sort -t$'\t' -k5 -rn | head -20
|
||||
|
||||
# Check for lateral movement in Windows Event Logs
|
||||
wevtutil qe Security /q:"*[System[(EventID=4624)] and EventData[Data[@Name='LogonType']='3']]" /f:text /c:50
|
||||
|
||||
# Query Active Directory for recent authentication anomalies
|
||||
Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 100 |
|
||||
Group-Object -Property {$_.Properties[5].Value} | Sort-Object Count -Descending
|
||||
```
|
||||
|
||||
### Step 3: Execute Network Containment
|
||||
```bash
|
||||
# Block attacker IP at perimeter firewall (Palo Alto example)
|
||||
set cli pager off
|
||||
configure
|
||||
set rulebase security rules emergency-block from any to any source [attacker_ip] action deny
|
||||
set rulebase security rules emergency-block from any to any destination [attacker_ip] action deny
|
||||
commit force
|
||||
|
||||
# Isolate compromised VLAN at switch level (Cisco)
|
||||
configure terminal
|
||||
interface vlan 100
|
||||
shutdown
|
||||
end
|
||||
write memory
|
||||
|
||||
# Block C2 domains at DNS level
|
||||
# Add to DNS sinkhole or RPZ
|
||||
echo "attacker-c2-domain.com CNAME ." >> /etc/bind/rpz.local
|
||||
rndc reload
|
||||
```
|
||||
|
||||
### Step 4: Isolate Compromised Endpoints
|
||||
```bash
|
||||
# CrowdStrike - Network contain host via API
|
||||
curl -X POST "https://api.crowdstrike.com/devices/entities/devices-actions/v2?action_name=contain" \
|
||||
-H "Authorization: Bearer $FALCON_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"ids": ["device_id_1", "device_id_2"]}'
|
||||
|
||||
# Microsoft Defender for Endpoint - Isolate machine
|
||||
curl -X POST "https://api.securitycenter.microsoft.com/api/machines/{machineId}/isolate" \
|
||||
-H "Authorization: Bearer $MDE_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"Comment": "IR-2024-001: Active breach containment", "IsolationType": "Full"}'
|
||||
|
||||
# SentinelOne - Disconnect from network
|
||||
curl -X POST "https://usea1.sentinelone.net/web/api/v2.1/agents/actions/disconnect" \
|
||||
-H "Authorization: ApiToken $S1_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"filter": {"ids": ["agent_id"]}, "data": {}}'
|
||||
```
|
||||
|
||||
### Step 5: Preserve Volatile Evidence Before Full Isolation
|
||||
```bash
|
||||
# Capture live memory from compromised Windows host
|
||||
winpmem_mini_x64.exe memdump_hostname_$(date +%Y%m%d).raw
|
||||
|
||||
# Capture network connections and running processes
|
||||
netstat -anob > netstat_capture_$(date +%Y%m%d_%H%M).txt
|
||||
tasklist /V /FO CSV > process_list_$(date +%Y%m%d_%H%M).csv
|
||||
wmic process list full > process_detail_$(date +%Y%m%d_%H%M).txt
|
||||
|
||||
# Linux volatile evidence collection
|
||||
dd if=/proc/kcore of=/mnt/forensics/memory_$(hostname)_$(date +%Y%m%d).raw bs=1M
|
||||
ss -tulnp > /mnt/forensics/network_$(hostname).txt
|
||||
ps auxwwf > /mnt/forensics/processes_$(hostname).txt
|
||||
```
|
||||
|
||||
### Step 6: Disable Compromised Accounts
|
||||
```bash
|
||||
# Disable compromised Active Directory accounts
|
||||
Import-Module ActiveDirectory
|
||||
Disable-ADAccount -Identity "compromised_user"
|
||||
Set-ADUser -Identity "compromised_user" -Description "Disabled - IR-2024-001 $(Get-Date)"
|
||||
|
||||
# Revoke all active sessions
|
||||
Revoke-AzureADUserAllRefreshToken -ObjectId "user_object_id"
|
||||
|
||||
# Reset service account credentials
|
||||
Set-ADAccountPassword -Identity "svc_compromised" -Reset -NewPassword (ConvertTo-SecureString "TempP@ss$(Get-Random)" -AsPlainText -Force)
|
||||
```
|
||||
|
||||
### Step 7: Validate Containment Effectiveness
|
||||
```bash
|
||||
# Verify no active C2 communications
|
||||
tcpdump -i eth0 host attacker_ip -c 100 -w verification_capture.pcap
|
||||
|
||||
# Check for new lateral movement attempts
|
||||
index=security sourcetype=wineventlog EventCode=4624 LogonType=3
|
||||
earliest=-15m
|
||||
| stats count by src_ip, dest_ip
|
||||
| where src_ip IN ("compromised_hosts")
|
||||
|
||||
# Validate endpoint isolation status
|
||||
curl -X GET "https://api.crowdstrike.com/devices/entities/devices/v2?ids=device_id" \
|
||||
-H "Authorization: Bearer $FALCON_TOKEN" | jq '.resources[].status'
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
| Concept | Description |
|
||||
|---------|-------------|
|
||||
| Short-term Containment | Immediate actions to stop active damage (network isolation, account disable) |
|
||||
| Long-term Containment | Sustainable measures while investigation continues (VLAN segmentation, enhanced monitoring) |
|
||||
| Evidence Preservation | Capturing volatile data before containment actions destroy forensic artifacts |
|
||||
| Blast Radius | Total scope of systems, accounts, and data affected by the breach |
|
||||
| Containment Boundary | Network and logical perimeter established to prevent further spread |
|
||||
| Kill Chain Disruption | Breaking the attacker's operational chain at the earliest possible stage |
|
||||
| Business Continuity | Maintaining critical operations while containing the threat |
|
||||
|
||||
## Tools & Systems
|
||||
|
||||
| Tool | Purpose |
|
||||
|------|---------|
|
||||
| CrowdStrike Falcon | Endpoint detection, network containment of hosts |
|
||||
| Microsoft Defender for Endpoint | Endpoint isolation and automated investigation |
|
||||
| Palo Alto NGFW | Perimeter firewall rules for IP/domain blocking |
|
||||
| Splunk/Elastic SIEM | Real-time alert correlation and scope analysis |
|
||||
| Zeek (Bro) | Network traffic analysis for C2 identification |
|
||||
| Velociraptor | Remote forensic collection and endpoint querying |
|
||||
| Active Directory | Account management and authentication control |
|
||||
|
||||
## Common Scenarios
|
||||
|
||||
1. **Ransomware Pre-Encryption**: Attacker has deployed ransomware binary but encryption hasn't started. Isolate patient zero, block C2, and prevent lateral deployment.
|
||||
2. **Active Data Exfiltration**: Data is being exfiltrated to external server. Block egress to C2, capture network evidence, isolate affected systems.
|
||||
3. **Compromised Domain Controller**: Attacker has DC access. Isolate DC from network, reset KRBTGT twice, rotate all privileged credentials.
|
||||
4. **Supply Chain Compromise**: Malicious update deployed across environment. Block update server, isolate systems that received the update, assess scope.
|
||||
5. **Insider Threat - Active Exfil**: Employee actively copying sensitive data. Disable account, block USB access, preserve evidence chain.
|
||||
|
||||
## Output Format
|
||||
- Containment action log with timestamps (who, what, when)
|
||||
- Network isolation verification report
|
||||
- List of compromised/isolated systems with justification
|
||||
- Evidence preservation checksums and chain of custody records
|
||||
- Containment effectiveness validation results
|
||||
- Stakeholder notification with current status and next steps
|
||||
@@ -0,0 +1,130 @@
|
||||
# Breach Containment Action Report
|
||||
|
||||
## Incident Information
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Incident ID | IR-YYYY-NNN |
|
||||
| Date/Time Detected | YYYY-MM-DD HH:MM UTC |
|
||||
| Containment Started | YYYY-MM-DD HH:MM UTC |
|
||||
| Containment Completed | YYYY-MM-DD HH:MM UTC |
|
||||
| Incident Commander | [Name] |
|
||||
| Severity Level | [Critical/High/Medium/Low] |
|
||||
|
||||
## Incident Summary
|
||||
[Brief description of the breach - what was detected, initial indicators, how the breach was discovered]
|
||||
|
||||
## Scope of Compromise
|
||||
|
||||
### Affected Systems
|
||||
| Hostname | IP Address | Role | Compromise Evidence | Containment Action |
|
||||
|----------|-----------|------|--------------------|--------------------|
|
||||
| | | | | |
|
||||
|
||||
### Compromised Accounts
|
||||
| Account Name | Account Type | Last Logon | Containment Action | Status |
|
||||
|-------------|-------------|------------|-------------------|--------|
|
||||
| | | | | |
|
||||
|
||||
### Affected Data
|
||||
| Data Classification | Data Type | Volume | Exfiltration Confirmed | Evidence |
|
||||
|--------------------|-----------|--------|----------------------|----------|
|
||||
| | | | | |
|
||||
|
||||
## Attack Timeline
|
||||
| Time (UTC) | Event | Source | Details |
|
||||
|-----------|-------|--------|---------|
|
||||
| | Initial access detected | | |
|
||||
| | Lateral movement observed | | |
|
||||
| | Containment initiated | | |
|
||||
| | Containment verified | | |
|
||||
|
||||
## Containment Actions Taken
|
||||
|
||||
### Network Containment
|
||||
- [ ] Attacker IPs blocked at perimeter firewall
|
||||
- IPs blocked: [list]
|
||||
- Firewall rule name/ID: [reference]
|
||||
- [ ] C2 domains sinkholed
|
||||
- Domains: [list]
|
||||
- Method: [DNS sinkhole/RPZ/hosts file]
|
||||
- [ ] Compromised network segments isolated
|
||||
- VLANs/subnets: [list]
|
||||
- Method: [ACL/VLAN shutdown/firewall rule]
|
||||
|
||||
### Endpoint Containment
|
||||
- [ ] Compromised hosts network-contained via EDR
|
||||
- EDR platform: [CrowdStrike/SentinelOne/MDE]
|
||||
- Hosts isolated: [list]
|
||||
- [ ] Malicious processes terminated
|
||||
- Processes: [list with PIDs]
|
||||
- [ ] Unauthorized software quarantined
|
||||
- Files: [list with hashes]
|
||||
|
||||
### Identity Containment
|
||||
- [ ] Compromised user accounts disabled
|
||||
- Accounts: [list]
|
||||
- [ ] Active sessions revoked
|
||||
- Method: [Azure AD/On-prem AD]
|
||||
- [ ] Service account credentials rotated
|
||||
- Accounts: [list]
|
||||
- [ ] MFA tokens reset
|
||||
- Users: [list]
|
||||
|
||||
### DNS/Web Containment
|
||||
- [ ] Malicious domains blocked at DNS
|
||||
- [ ] Web proxy rules updated
|
||||
- [ ] SSL certificates revoked (if applicable)
|
||||
|
||||
## Evidence Preserved
|
||||
|
||||
### Volatile Evidence (Collected Before Isolation)
|
||||
| Evidence Type | Host | Collection Time | SHA256 Hash | Collector |
|
||||
|--------------|------|-----------------|-------------|-----------|
|
||||
| Memory dump | | | | |
|
||||
| Network connections | | | | |
|
||||
| Process list | | | | |
|
||||
| DNS cache | | | | |
|
||||
|
||||
### Network Evidence
|
||||
| Capture Type | Source | Time Range | File Size | SHA256 Hash |
|
||||
|-------------|--------|------------|-----------|-------------|
|
||||
| PCAP | | | | |
|
||||
| NetFlow | | | | |
|
||||
|
||||
## Containment Verification
|
||||
|
||||
### Verification Checks
|
||||
- [ ] No active C2 communications detected post-containment
|
||||
- [ ] No new lateral movement attempts observed
|
||||
- [ ] All compromised accounts confirmed disabled
|
||||
- [ ] Isolated systems confirmed unreachable from network
|
||||
- [ ] Business-critical services tested and operational
|
||||
- [ ] Enhanced monitoring deployed on adjacent systems
|
||||
|
||||
### Monitoring Status
|
||||
| Monitor Type | Scope | Status | Alert Threshold |
|
||||
|-------------|-------|--------|----------------|
|
||||
| Network traffic | Compromised segments | Active/Pending | |
|
||||
| EDR alerts | All endpoints | Active/Pending | |
|
||||
| Authentication logs | Domain-wide | Active/Pending | |
|
||||
| Data loss prevention | Sensitive repositories | Active/Pending | |
|
||||
|
||||
## Business Impact Assessment
|
||||
| Service/System | Impact Level | Workaround Available | Estimated Restore |
|
||||
|---------------|-------------|---------------------|-------------------|
|
||||
| | | | |
|
||||
|
||||
## Next Steps
|
||||
1. [ ] Complete forensic imaging of all compromised systems
|
||||
2. [ ] Begin eradication phase - remove attacker persistence
|
||||
3. [ ] Conduct root cause analysis
|
||||
4. [ ] Prepare for recovery phase
|
||||
5. [ ] Schedule stakeholder briefing
|
||||
|
||||
## Approvals
|
||||
| Role | Name | Signature | Date |
|
||||
|------|------|-----------|------|
|
||||
| Incident Commander | | | |
|
||||
| CISO | | | |
|
||||
| IT Director | | | |
|
||||
| Legal Counsel | | | |
|
||||
@@ -0,0 +1,66 @@
|
||||
# Standards and Framework References
|
||||
|
||||
## NIST SP 800-61 Rev. 3 - Incident Response Recommendations
|
||||
- **Respond (RS) Function**: Containment falls under RS.MI (Incident Mitigation)
|
||||
- RS.MI-01: Incidents are contained
|
||||
- RS.MI-02: Incidents are eradicated
|
||||
- **Detect (DE) Function**: Scope identification maps to DE.AE (Adverse Event Analysis)
|
||||
- DE.AE-02: Potentially adverse events are analyzed to better understand associated activities
|
||||
- DE.AE-03: Information is correlated from multiple sources
|
||||
- Reference: https://csrc.nist.gov/pubs/sp/800/61/r3/final
|
||||
|
||||
## NIST SP 800-61 Rev. 2 - Computer Security Incident Handling Guide
|
||||
- **Section 3.3**: Containment, Eradication, and Recovery
|
||||
- 3.3.1: Choosing a Containment Strategy
|
||||
- 3.3.2: Evidence Gathering and Handling
|
||||
- 3.3.3: Identifying the Attacking Hosts
|
||||
- Containment strategy criteria: potential damage, evidence preservation needs, service availability, time/resources, effectiveness duration, solution scope
|
||||
- Reference: https://csrc.nist.gov/pubs/sp/800/61/r2/final
|
||||
|
||||
## SANS PICERL Framework
|
||||
- **Phase 3 - Containment**: The SANS Incident Handler's Handbook defines containment as actions to limit damage from an incident
|
||||
- Short-term containment: Immediate response to stop the bleeding
|
||||
- System back-up: Forensic image before remediation
|
||||
- Long-term containment: Temporary fixes allowing production use
|
||||
- Reference: https://www.sans.org/white-papers/33901
|
||||
|
||||
## MITRE ATT&CK Framework - Relevant Techniques to Contain
|
||||
|
||||
### Initial Access (TA0001)
|
||||
| Technique ID | Name | Containment Action |
|
||||
|-------------|------|-------------------|
|
||||
| T1566 | Phishing | Block sender, quarantine messages |
|
||||
| T1190 | Exploit Public-Facing Application | Patch/WAF rule, isolate service |
|
||||
| T1133 | External Remote Services | Disable VPN/RDP access |
|
||||
| T1078 | Valid Accounts | Disable/reset compromised accounts |
|
||||
|
||||
### Lateral Movement (TA0008)
|
||||
| Technique ID | Name | Containment Action |
|
||||
|-------------|------|-------------------|
|
||||
| T1021 | Remote Services | Block SMB/RDP/WinRM between segments |
|
||||
| T1550 | Use Alternate Authentication Material | Reset tokens, rotate KRBTGT |
|
||||
| T1570 | Lateral Tool Transfer | Block file sharing protocols |
|
||||
|
||||
### Command and Control (TA0011)
|
||||
| Technique ID | Name | Containment Action |
|
||||
|-------------|------|-------------------|
|
||||
| T1071 | Application Layer Protocol | Block C2 domains/IPs at firewall |
|
||||
| T1573 | Encrypted Channel | SSL inspection, block non-standard TLS |
|
||||
| T1572 | Protocol Tunneling | Block DNS tunneling, inspect traffic |
|
||||
|
||||
### Exfiltration (TA0010)
|
||||
| Technique ID | Name | Containment Action |
|
||||
|-------------|------|-------------------|
|
||||
| T1041 | Exfiltration Over C2 Channel | Sinkhole C2 domains |
|
||||
| T1048 | Exfiltration Over Alternative Protocol | Block DNS/ICMP exfil |
|
||||
| T1567 | Exfiltration Over Web Service | Block cloud storage uploads |
|
||||
|
||||
## CISA Incident Response Playbooks
|
||||
- Federal Government Cybersecurity Incident and Vulnerability Response Playbooks
|
||||
- Containment actions aligned with federal response guidelines
|
||||
- Reference: https://www.cisa.gov/sites/default/files/publications/Federal_Government_Cybersecurity_Incident_and_Vulnerability_Response_Playbooks_508C.pdf
|
||||
|
||||
## ISO/IEC 27035 - Information Security Incident Management
|
||||
- Part 2: Guidelines to plan and prepare for incident response
|
||||
- Containment classified as part of "Response" phase
|
||||
- Emphasis on proportional response and business impact consideration
|
||||
@@ -0,0 +1,107 @@
|
||||
# Containing an Active Security Breach - Detailed Workflow
|
||||
|
||||
## Pre-Containment Decision Framework
|
||||
|
||||
### Containment Strategy Selection Matrix
|
||||
| Factor | Low Impact | Medium Impact | High Impact |
|
||||
|--------|-----------|---------------|-------------|
|
||||
| Data sensitivity | Monitor and assess | Partial isolation | Full network isolation |
|
||||
| Active exfiltration | Block egress IPs | Block + isolate segment | Air-gap + full isolation |
|
||||
| Lateral movement | Enhanced monitoring | Segment isolation | Domain-wide lockdown |
|
||||
| Business criticality | Targeted containment | Phased containment | Emergency containment with DR |
|
||||
| Ransomware deployment | Isolate patient zero | Segment + block C2 | Enterprise-wide isolation |
|
||||
|
||||
## Step-by-Step Procedure
|
||||
|
||||
### Phase 1: Incident Validation (0-15 minutes)
|
||||
1. Receive alert from SIEM/EDR/SOC analyst
|
||||
2. Verify alert is true positive by correlating multiple data sources
|
||||
3. Classify incident severity using organization's severity matrix
|
||||
4. Activate incident response team based on severity level
|
||||
5. Establish incident communication channel (war room or Slack/Teams channel)
|
||||
6. Assign Incident Commander and document in ticketing system
|
||||
|
||||
### Phase 2: Scope Assessment (15-45 minutes)
|
||||
1. Query SIEM for all related alerts in the past 72 hours
|
||||
2. Identify all compromised hosts using EDR telemetry
|
||||
3. Map network connections from compromised hosts to identify lateral movement
|
||||
4. Check authentication logs for compromised account usage across systems
|
||||
5. Identify affected data repositories and assess data classification
|
||||
6. Document the attack timeline and current threat actor position
|
||||
7. Determine the attack vector (how did they get in)
|
||||
|
||||
### Phase 3: Short-Term Containment (30-60 minutes)
|
||||
1. **Network Level**:
|
||||
- Block attacker external IPs at perimeter firewall
|
||||
- Sinkhole C2 domains at DNS level
|
||||
- Apply ACLs to isolate compromised network segments
|
||||
- Enable enhanced packet capture on affected segments
|
||||
|
||||
2. **Endpoint Level**:
|
||||
- Network-contain compromised hosts via EDR
|
||||
- Disable compromised user accounts in Active Directory
|
||||
- Revoke OAuth tokens and API keys
|
||||
- Kill malicious processes identified by EDR
|
||||
|
||||
3. **Identity Level**:
|
||||
- Force password reset on compromised accounts
|
||||
- Disable MFA bypass methods used by attacker
|
||||
- Revoke VPN certificates for compromised users
|
||||
- Block compromised service account authentication
|
||||
|
||||
### Phase 4: Evidence Preservation (During Containment)
|
||||
1. Capture live memory from key compromised systems before full isolation
|
||||
2. Export relevant SIEM logs to secure evidence storage
|
||||
3. Take forensic disk images of critical compromised systems
|
||||
4. Preserve network capture data (PCAP) from affected segments
|
||||
5. Screenshot active sessions and running process trees
|
||||
6. Hash all evidence files and create chain of custody documentation
|
||||
|
||||
### Phase 5: Long-Term Containment (1-24 hours)
|
||||
1. Implement network microsegmentation around affected areas
|
||||
2. Deploy additional monitoring sensors in compromised zones
|
||||
3. Set up honeypots to detect continued attacker activity
|
||||
4. Apply temporary firewall rules with logging for affected segments
|
||||
5. Enable enhanced audit logging on systems adjacent to compromise
|
||||
6. Implement file integrity monitoring on critical systems
|
||||
7. Set up network traffic baseline comparison
|
||||
|
||||
### Phase 6: Containment Verification (Ongoing)
|
||||
1. Monitor for new alerts from previously compromised systems
|
||||
2. Verify no new C2 communications from any internal host
|
||||
3. Check for new account creation or privilege escalation attempts
|
||||
4. Validate that isolated systems cannot reach external networks
|
||||
5. Test that critical business services remain functional
|
||||
6. Brief stakeholders on containment status and next steps
|
||||
|
||||
## Escalation Criteria
|
||||
- Containment fails (attacker regains access): Escalate to CISO, consider external IR firm
|
||||
- Business-critical systems affected: Engage business continuity team
|
||||
- Data exfiltration confirmed: Engage legal and compliance teams
|
||||
- Nation-state indicators: Engage FBI/CISA
|
||||
- Ransomware spreading despite containment: Consider full network shutdown
|
||||
|
||||
## Communication Templates
|
||||
|
||||
### Internal Escalation (Initial)
|
||||
```
|
||||
SUBJECT: [SEVERITY-CRITICAL] Active Security Breach - Containment in Progress
|
||||
INCIDENT ID: IR-YYYY-NNN
|
||||
TIME DETECTED: YYYY-MM-DD HH:MM UTC
|
||||
CURRENT STATUS: Containment in progress
|
||||
AFFECTED SYSTEMS: [count] hosts, [count] accounts
|
||||
INCIDENT COMMANDER: [Name]
|
||||
NEXT UPDATE: [time]
|
||||
```
|
||||
|
||||
### Status Update (During Containment)
|
||||
```
|
||||
SUBJECT: [UPDATE] IR-YYYY-NNN - Containment Status
|
||||
CONTAINMENT STATUS: [Partial/Complete/Pending]
|
||||
SYSTEMS ISOLATED: [count]
|
||||
ACCOUNTS DISABLED: [count]
|
||||
C2 COMMUNICATIONS: [Blocked/Active/Unknown]
|
||||
BUSINESS IMPACT: [Description]
|
||||
NEXT STEPS: [Actions]
|
||||
NEXT UPDATE: [time]
|
||||
```
|
||||
@@ -0,0 +1,517 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Active Security Breach Containment Automation Script
|
||||
|
||||
Automates containment actions during an active security breach:
|
||||
- Queries SIEM for scope assessment
|
||||
- Isolates endpoints via EDR API
|
||||
- Blocks IPs/domains at firewall
|
||||
- Disables compromised AD accounts
|
||||
- Generates containment action log
|
||||
|
||||
Requirements:
|
||||
pip install requests ldap3 python-dateutil pyyaml
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
print("Install requests: pip install requests")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
from ldap3 import Server, Connection, MODIFY_REPLACE, ALL
|
||||
except ImportError:
|
||||
ldap3_available = False
|
||||
else:
|
||||
ldap3_available = True
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s [%(levelname)s] %(message)s",
|
||||
handlers=[
|
||||
logging.StreamHandler(),
|
||||
logging.FileHandler(f"containment_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"),
|
||||
],
|
||||
)
|
||||
logger = logging.getLogger("breach_containment")
|
||||
|
||||
|
||||
class ContainmentActionLog:
|
||||
"""Tracks all containment actions with timestamps for audit trail."""
|
||||
|
||||
def __init__(self, incident_id: str):
|
||||
self.incident_id = incident_id
|
||||
self.actions = []
|
||||
self.start_time = datetime.now(timezone.utc)
|
||||
|
||||
def log_action(self, action_type: str, target: str, result: str, details: str = ""):
|
||||
entry = {
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"incident_id": self.incident_id,
|
||||
"action_type": action_type,
|
||||
"target": target,
|
||||
"result": result,
|
||||
"details": details,
|
||||
"operator": os.getenv("USERNAME", os.getenv("USER", "unknown")),
|
||||
}
|
||||
self.actions.append(entry)
|
||||
logger.info(f"[{action_type}] {target}: {result} - {details}")
|
||||
|
||||
def export_csv(self, filepath: str):
|
||||
if not self.actions:
|
||||
logger.warning("No actions to export")
|
||||
return
|
||||
with open(filepath, "w", newline="") as f:
|
||||
writer = csv.DictWriter(f, fieldnames=self.actions[0].keys())
|
||||
writer.writeheader()
|
||||
writer.writerows(self.actions)
|
||||
logger.info(f"Containment log exported to {filepath}")
|
||||
|
||||
def export_json(self, filepath: str):
|
||||
report = {
|
||||
"incident_id": self.incident_id,
|
||||
"containment_start": self.start_time.isoformat(),
|
||||
"containment_end": datetime.now(timezone.utc).isoformat(),
|
||||
"total_actions": len(self.actions),
|
||||
"actions": self.actions,
|
||||
}
|
||||
with open(filepath, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
logger.info(f"Containment report exported to {filepath}")
|
||||
|
||||
|
||||
class CrowdStrikeContainment:
|
||||
"""CrowdStrike Falcon endpoint containment via API."""
|
||||
|
||||
def __init__(self, client_id: str, client_secret: str, base_url: str = "https://api.crowdstrike.com"):
|
||||
self.base_url = base_url
|
||||
self.client_id = client_id
|
||||
self.client_secret = client_secret
|
||||
self.token = None
|
||||
|
||||
def authenticate(self):
|
||||
resp = requests.post(
|
||||
f"{self.base_url}/oauth2/token",
|
||||
data={"client_id": self.client_id, "client_secret": self.client_secret},
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
self.token = resp.json()["access_token"]
|
||||
logger.info("Authenticated to CrowdStrike Falcon API")
|
||||
|
||||
def _headers(self):
|
||||
return {"Authorization": f"Bearer {self.token}", "Content-Type": "application/json"}
|
||||
|
||||
def get_device_id_by_hostname(self, hostname: str) -> Optional[str]:
|
||||
resp = requests.get(
|
||||
f"{self.base_url}/devices/queries/devices/v1",
|
||||
headers=self._headers(),
|
||||
params={"filter": f"hostname:'{hostname}'"},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
resources = resp.json().get("resources", [])
|
||||
return resources[0] if resources else None
|
||||
|
||||
def contain_host(self, device_id: str) -> dict:
|
||||
resp = requests.post(
|
||||
f"{self.base_url}/devices/entities/devices-actions/v2",
|
||||
headers=self._headers(),
|
||||
params={"action_name": "contain"},
|
||||
json={"ids": [device_id]},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def lift_containment(self, device_id: str) -> dict:
|
||||
resp = requests.post(
|
||||
f"{self.base_url}/devices/entities/devices-actions/v2",
|
||||
headers=self._headers(),
|
||||
params={"action_name": "lift_containment"},
|
||||
json={"ids": [device_id]},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def get_detections(self, severity: str = "Critical") -> list:
|
||||
resp = requests.get(
|
||||
f"{self.base_url}/detects/queries/detects/v1",
|
||||
headers=self._headers(),
|
||||
params={"filter": f"max_severity_displayname:'{severity}'+status:'new'", "limit": 100},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("resources", [])
|
||||
|
||||
|
||||
class SentinelOneContainment:
|
||||
"""SentinelOne endpoint containment via API."""
|
||||
|
||||
def __init__(self, api_token: str, base_url: str):
|
||||
self.base_url = base_url
|
||||
self.api_token = api_token
|
||||
|
||||
def _headers(self):
|
||||
return {"Authorization": f"ApiToken {self.api_token}", "Content-Type": "application/json"}
|
||||
|
||||
def disconnect_agent(self, agent_id: str) -> dict:
|
||||
resp = requests.post(
|
||||
f"{self.base_url}/web/api/v2.1/agents/actions/disconnect",
|
||||
headers=self._headers(),
|
||||
json={"filter": {"ids": [agent_id]}, "data": {}},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def reconnect_agent(self, agent_id: str) -> dict:
|
||||
resp = requests.post(
|
||||
f"{self.base_url}/web/api/v2.1/agents/actions/connect",
|
||||
headers=self._headers(),
|
||||
json={"filter": {"ids": [agent_id]}, "data": {}},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
|
||||
class ActiveDirectoryContainment:
|
||||
"""Active Directory account containment via LDAP."""
|
||||
|
||||
def __init__(self, server_addr: str, domain: str, username: str, password: str):
|
||||
if not ldap3_available:
|
||||
raise ImportError("ldap3 package required: pip install ldap3")
|
||||
self.server = Server(server_addr, get_info=ALL)
|
||||
self.domain = domain
|
||||
self.conn = Connection(self.server, user=f"{domain}\\{username}", password=password, auto_bind=True)
|
||||
|
||||
def disable_account(self, sam_account_name: str) -> bool:
|
||||
search_base = ",".join([f"DC={part}" for part in self.domain.split(".")])
|
||||
self.conn.search(
|
||||
search_base,
|
||||
f"(sAMAccountName={sam_account_name})",
|
||||
attributes=["userAccountControl", "distinguishedName"],
|
||||
)
|
||||
if not self.conn.entries:
|
||||
logger.warning(f"Account {sam_account_name} not found in AD")
|
||||
return False
|
||||
|
||||
dn = self.conn.entries[0].distinguishedName.value
|
||||
current_uac = int(self.conn.entries[0].userAccountControl.value)
|
||||
# Set ACCOUNTDISABLE flag (bit 1, value 2)
|
||||
new_uac = current_uac | 0x0002
|
||||
self.conn.modify(dn, {"userAccountControl": [(MODIFY_REPLACE, [str(new_uac)])]})
|
||||
logger.info(f"Disabled AD account: {sam_account_name}")
|
||||
return True
|
||||
|
||||
def reset_password(self, sam_account_name: str, new_password: str) -> bool:
|
||||
search_base = ",".join([f"DC={part}" for part in self.domain.split(".")])
|
||||
self.conn.search(search_base, f"(sAMAccountName={sam_account_name})", attributes=["distinguishedName"])
|
||||
if not self.conn.entries:
|
||||
return False
|
||||
dn = self.conn.entries[0].distinguishedName.value
|
||||
encoded_pw = f'"{new_password}"'.encode("utf-16-le")
|
||||
self.conn.modify(dn, {"unicodePwd": [(MODIFY_REPLACE, [encoded_pw])]})
|
||||
logger.info(f"Reset password for AD account: {sam_account_name}")
|
||||
return True
|
||||
|
||||
|
||||
class FirewallContainment:
|
||||
"""Block IPs and domains at network perimeter."""
|
||||
|
||||
@staticmethod
|
||||
def block_ips_iptables(ip_list: list, chain: str = "INPUT") -> list:
|
||||
results = []
|
||||
for ip in ip_list:
|
||||
try:
|
||||
cmd = ["iptables", "-A", chain, "-s", ip, "-j", "DROP"]
|
||||
subprocess.run(cmd, capture_output=True, text=True, check=True)
|
||||
cmd_out = ["iptables", "-A", "OUTPUT", "-d", ip, "-j", "DROP"]
|
||||
subprocess.run(cmd_out, capture_output=True, text=True, check=True)
|
||||
results.append({"ip": ip, "status": "blocked", "method": "iptables"})
|
||||
logger.info(f"Blocked IP via iptables: {ip}")
|
||||
except subprocess.CalledProcessError as e:
|
||||
results.append({"ip": ip, "status": "failed", "error": str(e)})
|
||||
logger.error(f"Failed to block IP {ip}: {e}")
|
||||
return results
|
||||
|
||||
@staticmethod
|
||||
def block_ips_windows_firewall(ip_list: list) -> list:
|
||||
results = []
|
||||
for ip in ip_list:
|
||||
try:
|
||||
rule_name = f"IR_Block_{ip.replace('.', '_')}"
|
||||
cmd = [
|
||||
"netsh", "advfirewall", "firewall", "add", "rule",
|
||||
f"name={rule_name}", "dir=in", "action=block",
|
||||
f"remoteip={ip}", "protocol=any",
|
||||
]
|
||||
subprocess.run(cmd, capture_output=True, text=True, check=True)
|
||||
cmd_out = [
|
||||
"netsh", "advfirewall", "firewall", "add", "rule",
|
||||
f"name={rule_name}_out", "dir=out", "action=block",
|
||||
f"remoteip={ip}", "protocol=any",
|
||||
]
|
||||
subprocess.run(cmd_out, capture_output=True, text=True, check=True)
|
||||
results.append({"ip": ip, "status": "blocked", "method": "windows_firewall"})
|
||||
logger.info(f"Blocked IP via Windows Firewall: {ip}")
|
||||
except subprocess.CalledProcessError as e:
|
||||
results.append({"ip": ip, "status": "failed", "error": str(e)})
|
||||
logger.error(f"Failed to block IP {ip}: {e}")
|
||||
return results
|
||||
|
||||
@staticmethod
|
||||
def block_domains_hosts_file(domain_list: list) -> list:
|
||||
results = []
|
||||
hosts_path = r"C:\Windows\System32\drivers\etc\hosts" if os.name == "nt" else "/etc/hosts"
|
||||
try:
|
||||
with open(hosts_path, "a") as f:
|
||||
for domain in domain_list:
|
||||
f.write(f"\n0.0.0.0 {domain} # IR Containment Block")
|
||||
results.append({"domain": domain, "status": "sinkholed", "method": "hosts_file"})
|
||||
logger.info(f"Sinkholed domain: {domain}")
|
||||
except PermissionError:
|
||||
logger.error("Insufficient permissions to modify hosts file. Run as administrator.")
|
||||
for domain in domain_list:
|
||||
results.append({"domain": domain, "status": "failed", "error": "permission_denied"})
|
||||
return results
|
||||
|
||||
|
||||
class SplunkScopeAssessment:
|
||||
"""Query Splunk SIEM for incident scope assessment."""
|
||||
|
||||
def __init__(self, base_url: str, token: str):
|
||||
self.base_url = base_url
|
||||
self.token = token
|
||||
|
||||
def _headers(self):
|
||||
return {"Authorization": f"Bearer {self.token}", "Content-Type": "application/json"}
|
||||
|
||||
def search(self, query: str, earliest: str = "-24h", latest: str = "now") -> dict:
|
||||
resp = requests.post(
|
||||
f"{self.base_url}/services/search/jobs",
|
||||
headers=self._headers(),
|
||||
data={
|
||||
"search": f"search {query}",
|
||||
"earliest_time": earliest,
|
||||
"latest_time": latest,
|
||||
"output_mode": "json",
|
||||
},
|
||||
verify=False,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def find_related_hosts(self, attacker_ip: str) -> dict:
|
||||
query = f"""index=security (src_ip="{attacker_ip}" OR dest_ip="{attacker_ip}")
|
||||
| stats count values(dest_ip) as targets values(src_ip) as sources by sourcetype
|
||||
| sort -count"""
|
||||
return self.search(query)
|
||||
|
||||
def find_compromised_accounts(self, host_list: list) -> dict:
|
||||
hosts_filter = " OR ".join([f'src="{h}"' for h in host_list])
|
||||
query = f"""index=security EventCode=4624 ({hosts_filter})
|
||||
| stats count values(src) as source_hosts by Account_Name, Logon_Type
|
||||
| where Logon_Type IN ("3","10")
|
||||
| sort -count"""
|
||||
return self.search(query)
|
||||
|
||||
|
||||
def collect_volatile_evidence(output_dir: str) -> dict:
|
||||
"""Collect volatile evidence from current system before containment."""
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
evidence = {}
|
||||
|
||||
# Network connections
|
||||
try:
|
||||
if os.name == "nt":
|
||||
result = subprocess.run(["netstat", "-anob"], capture_output=True, text=True)
|
||||
else:
|
||||
result = subprocess.run(["ss", "-tulnp"], capture_output=True, text=True)
|
||||
netconn_file = os.path.join(output_dir, "network_connections.txt")
|
||||
with open(netconn_file, "w") as f:
|
||||
f.write(result.stdout)
|
||||
evidence["network_connections"] = {
|
||||
"file": netconn_file,
|
||||
"sha256": hashlib.sha256(result.stdout.encode()).hexdigest(),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to collect network connections: {e}")
|
||||
|
||||
# Running processes
|
||||
try:
|
||||
if os.name == "nt":
|
||||
result = subprocess.run(["tasklist", "/V", "/FO", "CSV"], capture_output=True, text=True)
|
||||
else:
|
||||
result = subprocess.run(["ps", "auxwwf"], capture_output=True, text=True)
|
||||
proc_file = os.path.join(output_dir, "running_processes.txt")
|
||||
with open(proc_file, "w") as f:
|
||||
f.write(result.stdout)
|
||||
evidence["running_processes"] = {
|
||||
"file": proc_file,
|
||||
"sha256": hashlib.sha256(result.stdout.encode()).hexdigest(),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to collect process list: {e}")
|
||||
|
||||
# DNS cache
|
||||
try:
|
||||
if os.name == "nt":
|
||||
result = subprocess.run(["ipconfig", "/displaydns"], capture_output=True, text=True)
|
||||
else:
|
||||
dns_cache_file = "/var/cache/nscd/hosts" if os.path.exists("/var/cache/nscd/hosts") else ""
|
||||
result = subprocess.run(["cat", dns_cache_file], capture_output=True, text=True) if dns_cache_file else None
|
||||
if result and result.stdout:
|
||||
dns_file = os.path.join(output_dir, "dns_cache.txt")
|
||||
with open(dns_file, "w") as f:
|
||||
f.write(result.stdout)
|
||||
evidence["dns_cache"] = {
|
||||
"file": dns_file,
|
||||
"sha256": hashlib.sha256(result.stdout.encode()).hexdigest(),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to collect DNS cache: {e}")
|
||||
|
||||
# ARP table
|
||||
try:
|
||||
result = subprocess.run(["arp", "-a"], capture_output=True, text=True)
|
||||
arp_file = os.path.join(output_dir, "arp_table.txt")
|
||||
with open(arp_file, "w") as f:
|
||||
f.write(result.stdout)
|
||||
evidence["arp_table"] = {
|
||||
"file": arp_file,
|
||||
"sha256": hashlib.sha256(result.stdout.encode()).hexdigest(),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to collect ARP table: {e}")
|
||||
|
||||
# Logged-in users
|
||||
try:
|
||||
if os.name == "nt":
|
||||
result = subprocess.run(["query", "user"], capture_output=True, text=True)
|
||||
else:
|
||||
result = subprocess.run(["who"], capture_output=True, text=True)
|
||||
users_file = os.path.join(output_dir, "logged_in_users.txt")
|
||||
with open(users_file, "w") as f:
|
||||
f.write(result.stdout)
|
||||
evidence["logged_in_users"] = {
|
||||
"file": users_file,
|
||||
"sha256": hashlib.sha256(result.stdout.encode()).hexdigest(),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to collect logged-in users: {e}")
|
||||
|
||||
return evidence
|
||||
|
||||
|
||||
def run_containment(args):
|
||||
"""Execute the full containment workflow."""
|
||||
action_log = ContainmentActionLog(args.incident_id)
|
||||
logger.info(f"Starting containment for incident: {args.incident_id}")
|
||||
|
||||
# Step 1: Collect volatile evidence if requested
|
||||
if args.collect_evidence:
|
||||
evidence_dir = os.path.join(args.output_dir, "evidence", args.incident_id)
|
||||
logger.info(f"Collecting volatile evidence to {evidence_dir}")
|
||||
evidence = collect_volatile_evidence(evidence_dir)
|
||||
for etype, edata in evidence.items():
|
||||
action_log.log_action("evidence_collection", etype, "collected", f"SHA256: {edata['sha256']}")
|
||||
|
||||
# Step 2: Block IPs at firewall
|
||||
if args.block_ips:
|
||||
ip_list = [ip.strip() for ip in args.block_ips.split(",")]
|
||||
logger.info(f"Blocking {len(ip_list)} IPs at firewall")
|
||||
if os.name == "nt":
|
||||
results = FirewallContainment.block_ips_windows_firewall(ip_list)
|
||||
else:
|
||||
results = FirewallContainment.block_ips_iptables(ip_list)
|
||||
for r in results:
|
||||
action_log.log_action("ip_block", r["ip"], r["status"], r.get("method", r.get("error", "")))
|
||||
|
||||
# Step 3: Block domains
|
||||
if args.block_domains:
|
||||
domain_list = [d.strip() for d in args.block_domains.split(",")]
|
||||
logger.info(f"Sinkholing {len(domain_list)} domains")
|
||||
results = FirewallContainment.block_domains_hosts_file(domain_list)
|
||||
for r in results:
|
||||
action_log.log_action("domain_block", r["domain"], r["status"], r.get("method", ""))
|
||||
|
||||
# Step 4: Isolate endpoints via CrowdStrike
|
||||
if args.crowdstrike_isolate and args.cs_client_id and args.cs_client_secret:
|
||||
cs = CrowdStrikeContainment(args.cs_client_id, args.cs_client_secret)
|
||||
try:
|
||||
cs.authenticate()
|
||||
action_log.log_action("edr_auth", "crowdstrike", "success", "API authenticated")
|
||||
hostnames = [h.strip() for h in args.crowdstrike_isolate.split(",")]
|
||||
for hostname in hostnames:
|
||||
device_id = cs.get_device_id_by_hostname(hostname)
|
||||
if device_id:
|
||||
cs.contain_host(device_id)
|
||||
action_log.log_action("endpoint_isolation", hostname, "contained", f"Device ID: {device_id}")
|
||||
else:
|
||||
action_log.log_action("endpoint_isolation", hostname, "failed", "Device not found in Falcon")
|
||||
except Exception as e:
|
||||
action_log.log_action("edr_auth", "crowdstrike", "failed", str(e))
|
||||
logger.error(f"CrowdStrike containment failed: {e}")
|
||||
|
||||
# Step 5: Disable AD accounts
|
||||
if args.disable_accounts and args.ad_server and ldap3_available:
|
||||
try:
|
||||
ad = ActiveDirectoryContainment(
|
||||
args.ad_server, args.ad_domain, args.ad_username, args.ad_password
|
||||
)
|
||||
accounts = [a.strip() for a in args.disable_accounts.split(",")]
|
||||
for account in accounts:
|
||||
result = ad.disable_account(account)
|
||||
action_log.log_action(
|
||||
"account_disable", account, "disabled" if result else "failed",
|
||||
"AD account disabled" if result else "Account not found",
|
||||
)
|
||||
except Exception as e:
|
||||
action_log.log_action("account_disable", "AD", "failed", str(e))
|
||||
logger.error(f"AD containment failed: {e}")
|
||||
|
||||
# Export containment action log
|
||||
os.makedirs(args.output_dir, exist_ok=True)
|
||||
csv_path = os.path.join(args.output_dir, f"containment_log_{args.incident_id}.csv")
|
||||
json_path = os.path.join(args.output_dir, f"containment_report_{args.incident_id}.json")
|
||||
action_log.export_csv(csv_path)
|
||||
action_log.export_json(json_path)
|
||||
|
||||
logger.info(f"Containment workflow completed for {args.incident_id}")
|
||||
logger.info(f"Total actions taken: {len(action_log.actions)}")
|
||||
return action_log
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Active Security Breach Containment Automation")
|
||||
parser.add_argument("--incident-id", required=True, help="Incident tracking ID (e.g., IR-2024-001)")
|
||||
parser.add_argument("--output-dir", default="./containment_output", help="Output directory for logs and reports")
|
||||
parser.add_argument("--collect-evidence", action="store_true", help="Collect volatile evidence before containment")
|
||||
parser.add_argument("--block-ips", help="Comma-separated list of IPs to block at firewall")
|
||||
parser.add_argument("--block-domains", help="Comma-separated list of domains to sinkhole")
|
||||
parser.add_argument("--crowdstrike-isolate", help="Comma-separated hostnames to isolate via CrowdStrike")
|
||||
parser.add_argument("--cs-client-id", default=os.getenv("CS_CLIENT_ID"), help="CrowdStrike API client ID")
|
||||
parser.add_argument("--cs-client-secret", default=os.getenv("CS_CLIENT_SECRET"), help="CrowdStrike API client secret")
|
||||
parser.add_argument("--disable-accounts", help="Comma-separated AD accounts to disable")
|
||||
parser.add_argument("--ad-server", default=os.getenv("AD_SERVER"), help="Active Directory server address")
|
||||
parser.add_argument("--ad-domain", default=os.getenv("AD_DOMAIN"), help="Active Directory domain")
|
||||
parser.add_argument("--ad-username", default=os.getenv("AD_USERNAME"), help="AD admin username")
|
||||
parser.add_argument("--ad-password", default=os.getenv("AD_PASSWORD"), help="AD admin password")
|
||||
|
||||
args = parser.parse_args()
|
||||
run_containment(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user