SCENARIO
This document provides comprehensive procedures for forensic evidence collection, ransomware rollback, and threat remediation using SentinelOne Complete SKU capabilities. These procedures are critical for MSP security operations teams conducting incident response, preserving evidence for legal proceedings, recovering from ransomware attacks, and ensuring complete threat eradication.
Use this documentation when:
- Conducting forensic investigations requiring evidence preservation
- Responding to ransomware incidents requiring file recovery
- Performing comprehensive threat remediation across endpoints
- Building incident response playbooks for your SOC team
- Training analysts on SentinelOne Complete capabilities
- Preparing evidence packages for legal or compliance requirements
SKU Requirement: SentinelOne Singularity Complete is required for most features documented here. Control SKU lacks Deep Visibility, Remote Shell, File Fetch, and 1-Click Rollback capabilities.
MITRE ATT&CK Framework References:
- Evidence Collection: Supports investigation of all ATT&CK tactics
- Rollback: Mitigates T1486 (Data Encrypted for Impact)
- Remediation: Addresses T1059 (Command and Scripting Interpreter), T1053 (Scheduled Task/Job), T1547 (Boot or Logon Autostart Execution)
REQUIREMENTS & ASSUMPTIONS
Prerequisites
Console Access:
- SentinelOne Management Console with Admin or SOC role
- API token with appropriate permissions for automation scripts
- Access to Deep Visibility, Remote Shell, and forensic features
Endpoint Requirements:
- SentinelOne agent version 21.5+ (recommended: latest GA release)
- Agent online and communicating with console
- Volume Shadow Copy Service (VSS) enabled for rollback capability
- Sufficient disk space for VSS snapshots (minimum 10% free space recommended)
Infrastructure:
- Secure storage location for forensic evidence
- Chain of custody documentation templates
- Incident ticketing system integration
- SIEM integration for log correlation (optional)
Assumed Knowledge
- Basic incident response procedures
- SentinelOne console navigation
- PowerShell scripting fundamentals
- Understanding of Windows/Linux file systems
- MITRE ATT&CK framework familiarity
SECTION 1: FORENSIC EVIDENCE COLLECTION
1.1 Threat Storyline Analysis and Timeline Reconstruction
The Storyline feature automatically correlates all related events into a coherent attack narrative, essential for forensic analysis.
Accessing Storyline:
- Navigate to Sentinels > Threats
- Click on the threat to investigate
- Select the Storyline tab
- Review the visual attack chain
Storyline Components:
Timeline View Elements:
├── Process Tree: Parent-child process relationships
├── File Operations: Created, modified, deleted, renamed files
├── Registry Changes: Keys and values modified
├── Network Connections: Outbound communications with IPs/domains
├── DNS Queries: Domain resolution attempts
├── Login Events: User authentication activities
├── Cross-Process Events: Code injection, memory manipulation
└── Module Loads: DLLs and drivers loaded
Timeline Reconstruction Process:
-
Identify Initial Access Point (MITRE T1566, T1189, T1078)
- Review the earliest event in the Storyline
- Note the triggering application (browser, email client, document)
- Document the user context and timestamp
-
Map Execution Chain (MITRE T1059, T1204)
- Trace process spawning relationships
- Document command-line arguments (often contain IOCs)
- Identify interpreter abuse (PowerShell, cmd, wscript, mshta)
-
Document Persistence Mechanisms (MITRE T1547, T1053, T1543)
- Registry Run keys
- Scheduled tasks
- Services created or modified
- Startup folder items
-
Capture Network IOCs (MITRE T1071, T1041)
- C2 server IP addresses and domains
- Ports and protocols used
- Data exfiltration destinations
- DNS queries for DGA domains
Deep Visibility Query for Timeline:
-- Reconstruct timeline for specific endpoint
EndpointName = "WORKSTATION-001" AND
CreatedAt >= "2026-01-07T00:00:00Z" AND
CreatedAt <= "2026-01-08T23:59:59Z"
| sort by CreatedAt ascExport Storyline for Documentation:
- In Storyline view, click Export
- Select format: JSON (for analysis) or PDF (for reports)
- Include all related events
- Save to secure forensic evidence storage
1.2 Artifact Collection from Deep Visibility
Deep Visibility provides comprehensive endpoint telemetry for forensic artifact collection.
Key Forensic Queries:
-- All process executions on compromised endpoint
EventType = "Process Creation" AND
EndpointName = "WORKSTATION-001" AND
CreatedAt >= "2026-01-07T00:00:00Z"
| columns ProcessName, ProcessCmd, ParentProcessName, User, CreatedAt, SHA256
-- File operations during incident window
EventType IN ("File Creation", "File Modification", "File Deletion") AND
EndpointName = "WORKSTATION-001" AND
CreatedAt >= "2026-01-07T12:00:00Z" AND
CreatedAt <= "2026-01-07T14:00:00Z"
| columns FilePath, EventType, ProcessName, CreatedAt
-- Network connections to external IPs
EventType = "IP Connect" AND
EndpointName = "WORKSTATION-001" AND
DstIP NOT STARTSWITH "10." AND
DstIP NOT STARTSWITH "192.168." AND
DstIP NOT STARTSWITH "172."
| columns SrcProcName, DstIP, DstPort, CreatedAt
-- Registry modifications (persistence indicators)
EventType IN ("Registry Key Create", "Registry Value Create", "Registry Value Modified") AND
EndpointName = "WORKSTATION-001" AND
(RegistryPath CONTAINS "Run" OR
RegistryPath CONTAINS "Services" OR
RegistryPath CONTAINS "Winlogon")
| columns RegistryPath, RegistryValue, ProcessName, CreatedAt
-- DNS queries for threat intelligence
EventType = "DNS" AND
EndpointName = "WORKSTATION-001" AND
CreatedAt >= "2026-01-07T00:00:00Z"
| columns DNSRequest, SrcProcName, CreatedAtExporting Deep Visibility Data:
- Run the query in Deep Visibility console
- Click Export button
- Select format:
- CSV: For spreadsheet analysis
- JSON: For programmatic processing
- STIX: For threat intelligence platforms
- Download and store in evidence repository
Evidence Preservation Best Practice:
- Hash all exported files immediately (SHA256)
- Document export timestamp and analyst name
- Store in write-once media or evidence management system
- Maintain chain of custody log
1.3 Memory Dump Collection
Memory forensics captures volatile data including encryption keys, credentials, and malware that only exists in RAM.
Initiating Memory Dump via Console:
- Navigate to Sentinels > Endpoints
- Select the target endpoint
- Click Actions > Fetch Files
- Select Full Memory Dump
- Wait for collection (can take 10-30 minutes depending on RAM size)
- Download password-protected ZIP when ready
Memory Dump via Remote Shell:
# Connect to endpoint via Remote Shell
# Navigate to Sentinels > [Endpoint] > Actions > Remote Shell
# Option 1: Use Windows built-in (requires admin)
# Creates minidump of specific process
$processId = (Get-Process -Name "suspicious_process").Id
rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump $processId C:\Temp\memory.dmp full
# Option 2: Full memory dump using winpmem (if deployed)
# Deploy winpmem to endpoint first via File Fetch upload
C:\Tools\winpmem_mini_x64.exe C:\Temp\full_memory.raw
# Option 3: Using procdump (Sysinternals)
procdump.exe -ma lsass.exe C:\Temp\lsass.dmpMemory Dump Analysis Tools:
- Volatility 3: Open-source memory forensics framework
- Rekall: Advanced memory analysis
- WinDbg: Microsoft debugging tools
MITRE ATT&CK Relevance:
- T1003 (OS Credential Dumping): Recover cached credentials
- T1055 (Process Injection): Identify injected code
- T1620 (Reflective Code Loading): Find fileless malware
1.4 Disk Image Collection
For severe incidents or legal requirements, full disk imaging preserves all evidence.
Remote Disk Imaging Considerations:
SentinelOne does not perform full disk imaging natively. Use these approaches:
Option 1: Targeted File Collection via File Fetch
Critical Windows Artifacts:
System Files:
- C:\Windows\System32\config\SAM
- C:\Windows\System32\config\SYSTEM
- C:\Windows\System32\config\SOFTWARE
- C:\Windows\System32\config\SECURITY
- C:\$MFT (Master File Table)
- C:\$LogFile (NTFS journal)
- C:\$UsnJrnl:$J (USN Journal)
Event Logs:
- C:\Windows\System32\winevt\Logs\Security.evtx
- C:\Windows\System32\winevt\Logs\System.evtx
- C:\Windows\System32\winevt\Logs\Application.evtx
- C:\Windows\System32\winevt\Logs\PowerShell*.evtx
- C:\Windows\System32\winevt\Logs\Microsoft-Windows-Sysmon*.evtx
User Artifacts:
- C:\Users\*\NTUSER.DAT
- C:\Users\*\AppData\Local\Microsoft\Windows\UsrClass.dat
- C:\Users\*\AppData\Roaming\Microsoft\Windows\Recent\*
- C:\Users\*\AppData\Local\Microsoft\Windows\WebCache\*
Execution Artifacts:
- C:\Windows\Prefetch\*.pf
- C:\Windows\AppCompat\Programs\Amcache.hve
- C:\Windows\AppCompat\Programs\RecentFileCache.bcfOption 2: Remote Imaging via Remote Shell
# Using FTK Imager CLI (if deployed)
ftkimager.exe \\.\PhysicalDrive0 C:\Evidence\disk_image --e01 --compress 6
# Using dd for Windows
dd.exe if=\\.\PhysicalDrive0 of=C:\Evidence\disk.raw bs=64K
# Targeted logical collection
robocopy C:\Users C:\Evidence\Users /E /COPYALL /LOG:C:\Evidence\users_copy.logOption 3: Physical Collection For legal proceedings requiring full disk images:
- Network quarantine the endpoint via SentinelOne
- Dispatch technician with write-blocker
- Create forensic image using FTK Imager or dd
- Maintain chain of custody documentation
1.5 Evidence Preservation and Chain of Custody
Proper evidence handling ensures admissibility in legal proceedings.
Chain of Custody Documentation:
# Evidence Chain of Custody Form
## Case Information
- Case ID: INC-2026-0108-001
- Case Title: Ransomware Incident - ACME Corp
- Lead Investigator: [Name]
- Date Opened: 2026-01-08
## Evidence Item
- Evidence ID: EVD-001
- Description: Memory dump from WORKSTATION-001
- Collection Method: SentinelOne File Fetch
- Collection Date/Time: 2026-01-08 14:32:00 UTC
- Collected By: [Analyst Name]
- Original Location: WORKSTATION-001 (192.168.1.50)
- File Hash (SHA256): [hash value]
- File Size: 16,384 MB
## Chain of Custody Log
| Date/Time | Released By | Received By | Purpose | Location |
|-----------|-------------|-------------|---------|----------|
| 2026-01-08 14:35 | SentinelOne | J. Smith | Collection | S1 Console |
| 2026-01-08 14:40 | J. Smith | Evidence Server | Storage | \\evidence\cases\ |
| 2026-01-08 16:00 | Evidence Server | M. Jones | Analysis | Forensic WS |
## Integrity Verification
- [ ] Hash verified on receipt
- [ ] Stored in tamper-evident container
- [ ] Access logged and monitoredEvidence Storage Requirements:
-
Immediate Actions:
- Calculate SHA256 hash upon collection
- Document collection method and timestamp
- Store on write-protected or WORM storage
-
Storage Location:
- Encrypted network share with access logging
- Cloud evidence management platform (e.g., Axon Evidence)
- Air-gapped forensic workstation for analysis
-
Retention Policy:
- Minimum 7 years for compliance (varies by regulation)
- Legal hold may extend indefinitely
- Document destruction when retention expires
1.6 Exporting Threat Data for Legal/Compliance
Generate Comprehensive Threat Report:
- Navigate to Threats > [Select Threat]
- Click Export > Full Report
- Include:
- Threat details and classification
- Complete Storyline with timestamps
- All IOCs (hashes, IPs, domains)
- Remediation actions taken
- Analyst notes
API Export for SIEM/Legal:
# Export threat data via API
$threatId = "1234567890"
$headers = @{
"Authorization" = "ApiToken $apiToken"
"Content-Type" = "application/json"
}
# Get threat details
$threat = Invoke-RestMethod -Uri "$consoleUrl/web/api/v2.1/threats/$threatId" -Headers $headers
# Get timeline events
$timeline = Invoke-RestMethod -Uri "$consoleUrl/web/api/v2.1/threats/$threatId/timeline" -Headers $headers
# Export to JSON for legal
$evidencePackage = @{
exportDate = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")
exportedBy = $env:USERNAME
threatDetails = $threat.data
timeline = $timeline.data
}
$evidencePackage | ConvertTo-Json -Depth 20 | Out-File "C:\Evidence\Threat-$threatId-Export.json"
# Calculate hash for integrity
$hash = Get-FileHash "C:\Evidence\Threat-$threatId-Export.json" -Algorithm SHA256
"SHA256: $($hash.Hash)" | Out-File "C:\Evidence\Threat-$threatId-Export.json.sha256"SECTION 2: ROLLBACK CAPABILITIES (Complete SKU)
2.1 How Ransomware Rollback Works
SentinelOne's 1-Click Rollback leverages Windows Volume Shadow Copy Service (VSS) to restore files encrypted or modified by ransomware.
Technical Architecture:
Rollback Process Flow:
┌─────────────────────────────────────────────────────────────────┐
│ Normal Operations │
│ [Files] ──write──> [VSS Snapshot] ──monitor──> [S1 Agent] │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Ransomware Attack │
│ [Ransomware] ──encrypt──> [Files] ──detect──> [S1 Behavioral AI]│
│ │
│ Detection Triggers: │
│ • Mass file modifications │
│ • Encryption entropy changes │
│ • Known ransomware behaviors │
│ • File extension changes (.encrypted, .locked) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Automatic Response │
│ 1. Kill ransomware process │
│ 2. Quarantine malicious files │
│ 3. Block persistence mechanisms │
│ 4. Initiate rollback from VSS snapshots │
│ 5. Restore files to pre-encryption state │
└─────────────────────────────────────────────────────────────────┘
VSS Integration Details:
- SentinelOne monitors VSS snapshots continuously
- Agent tracks file modifications with associated snapshots
- Rollback queries VSS for pre-modification versions
- Files restored to exact state before malicious changes
- Works independently of Windows System Restore
MITRE ATT&CK Mitigation:
- T1486 (Data Encrypted for Impact): Primary mitigation
- T1485 (Data Destruction): Partial mitigation via VSS
- T1490 (Inhibit System Recovery): Detection of VSS deletion attempts
2.2 Prerequisites and Requirements
Endpoint Requirements:
| Requirement | Details | Verification Command |
|---|---|---|
| OS Support | Windows 7 SP1+, Server 2008 R2+ | [System.Environment]::OSVersion |
| VSS Enabled | Volume Shadow Copy service running | Get-Service -Name VSS |
| VSS Space | Minimum 10% disk space for shadows | vssadmin list shadowstorage |
| Agent Version | 21.5+ recommended | Check console or SentinelCtl.exe version |
| Policy Setting | Rollback enabled in site policy | Console: Settings > Policy |
Verification Script:
# Run on endpoint to verify rollback readiness
Write-Host "=== SentinelOne Rollback Readiness Check ===" -ForegroundColor Cyan
# Check VSS Service
$vss = Get-Service -Name VSS
Write-Host "`n[VSS Service]" -ForegroundColor Yellow
Write-Host " Status: $($vss.Status)"
Write-Host " StartType: $($vss.StartType)"
# Check Shadow Storage
Write-Host "`n[Shadow Storage]" -ForegroundColor Yellow
$shadowStorage = vssadmin list shadowstorage 2>&1
if ($shadowStorage -match "No shadow copies") {
Write-Host " WARNING: No shadow storage configured" -ForegroundColor Red
} else {
$shadowStorage | ForEach-Object { Write-Host " $_" }
}
# Check Available Shadows
Write-Host "`n[Shadow Copies]" -ForegroundColor Yellow
$shadows = vssadmin list shadows 2>&1
if ($shadows -match "No shadow copies") {
Write-Host " WARNING: No shadow copies available" -ForegroundColor Red
} else {
$shadowCount = ($shadows | Select-String "Shadow Copy ID").Count
Write-Host " Available shadow copies: $shadowCount"
}
# Check Disk Space
Write-Host "`n[Disk Space]" -ForegroundColor Yellow
Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" | ForEach-Object {
$freePercent = [math]::Round(($_.FreeSpace / $_.Size) * 100, 2)
$status = if ($freePercent -lt 10) { "[LOW]" } else { "[OK]" }
Write-Host " $($_.DeviceID) - Free: $freePercent% $status"
}
# Check SentinelOne Agent
Write-Host "`n[SentinelOne Agent]" -ForegroundColor Yellow
$s1Service = Get-Service -Name "SentinelAgent" -ErrorAction SilentlyContinue
if ($s1Service) {
Write-Host " Agent Status: $($s1Service.Status)"
} else {
Write-Host " WARNING: SentinelOne agent not found" -ForegroundColor Red
}Policy Configuration:
- Navigate to Settings > Policy > [Site Policy]
- Under Agent Settings > Remediation:
- Enable Rollback toggle
- Configure Automatic Rollback for ransomware threats
- Under Protection > Ransomware:
- Enable Behavioral AI - Ransomware
- Set action to Kill & Quarantine
2.3 Initiating Manual Rollback
Via Console:
- Navigate to Threats
- Select the ransomware threat
- Verify threat is mitigated (killed/quarantined)
- Click Actions > Rollback
- Confirm the rollback action
- Monitor progress in threat details
Via API:
# Initiate rollback via API
$threatId = "1234567890"
$headers = @{
"Authorization" = "ApiToken $apiToken"
"Content-Type" = "application/json"
}
$rollbackBody = @{
data = @{
ids = @($threatId)
}
} | ConvertTo-Json
$result = Invoke-RestMethod `
-Uri "$consoleUrl/web/api/v2.1/threats/actions/rollback" `
-Method POST `
-Headers $headers `
-Body $rollbackBody
if ($result.data.affected -gt 0) {
Write-Host "[SUCCESS] Rollback initiated for threat $threatId" -ForegroundColor Green
} else {
Write-Host "[FAILED] Rollback could not be initiated" -ForegroundColor Red
}Rollback Status Monitoring:
# Monitor rollback progress
$threatId = "1234567890"
do {
$threat = Invoke-RestMethod `
-Uri "$consoleUrl/web/api/v2.1/threats/$threatId" `
-Headers $headers
$rollbackStatus = $threat.data.threatInfo.rollbackStatus
Write-Host "Rollback Status: $rollbackStatus - $(Get-Date -Format 'HH:mm:ss')"
if ($rollbackStatus -eq "completed") {
Write-Host "[SUCCESS] Rollback completed successfully" -ForegroundColor Green
break
} elseif ($rollbackStatus -eq "failed") {
Write-Host "[FAILED] Rollback failed - check threat details" -ForegroundColor Red
break
}
Start-Sleep -Seconds 30
} while ($true)2.4 Automatic Rollback Configuration
Enable Automatic Rollback:
- Navigate to Settings > Policy > [Site Policy]
- Select Remediation section
- Configure:
Automatic Rollback Settings:
Enabled: Yes
Trigger Conditions:
- Ransomware detected by Behavioral AI
- Threat classified as ransomware
- Automatic mitigation successful
Rollback Scope:
- All files modified by threat process
- Files modified by child processes
- Registry changes associated with threatPolicy JSON (via API):
{
"data": {
"policy": {
"agentSettings": {
"remediation": {
"rollback": {
"enabled": true,
"automaticRollback": true,
"rollbackOnRansomware": true
}
}
}
}
}
}2.5 Rollback Limitations and Considerations
What Rollback CAN Restore:
- Files encrypted by detected ransomware
- Files deleted by malware
- Registry changes made by threat
- Files modified in the attack chain
What Rollback CANNOT Restore:
| Limitation | Explanation | Workaround |
|---|---|---|
| Deleted VSS Snapshots | Some ransomware deletes shadow copies before encrypting | Enable VSS protection; detect T1490 with STAR rules |
| Network Shares | VSS only covers local volumes | Use backup solution for network storage |
| Cloud-Synced Files | OneDrive/Dropbox may sync encrypted files | Use cloud provider's version history |
| Pre-Existing Damage | Only restores from point of snapshot | Regular backup strategy |
| Undetected Threats | Must be detected by S1 to trigger rollback | Enable all detection engines |
| macOS/Linux | VSS is Windows-only technology | Use platform-specific backup tools |
| Large Time Gaps | Long-running encryption may exceed snapshot retention | Increase VSS storage allocation |
STAR Rule for VSS Deletion Detection:
-- Detect attempts to delete shadow copies (T1490)
EventType = "Process Creation" AND
(ProcessCmd CONTAINS "vssadmin delete shadows" OR
ProcessCmd CONTAINS "wmic shadowcopy delete" OR
ProcessCmd CONTAINS "bcdedit /set" AND ProcessCmd CONTAINS "recoveryenabled no" OR
ProcessCmd CONTAINS "wbadmin delete catalog")2.6 Testing Rollback Procedures
Safe Testing Methodology:
-
Create Test Environment:
- Isolated VM or test endpoint
- Known-good baseline snapshot
- Test files in designated folder
-
Simulate Ransomware Behavior (Safe):
# SAFE SIMULATION - Only modifies test files
# Run in isolated test environment only
$testFolder = "C:\RollbackTest"
New-Item -Path $testFolder -ItemType Directory -Force
# Create test files
1..10 | ForEach-Object {
$content = "Original content for file $_"
$content | Out-File "$testFolder\TestFile$_.txt"
}
Write-Host "Test files created. Verify in SentinelOne console before proceeding."
Read-Host "Press Enter to simulate file modification (simulated encryption)"
# Simulate encryption (actually just modifies files)
Get-ChildItem "$testFolder\*.txt" | ForEach-Object {
$encrypted = "ENCRYPTED: " + (Get-Content $_.FullName)
$encrypted | Out-File $_.FullName
Rename-Item $_.FullName "$($_.FullName).locked"
}
Write-Host "Files 'encrypted'. Initiate rollback from SentinelOne console."- Verify Rollback:
- Initiate rollback from console
- Verify files restored to original content
- Document results
Rollback Test Checklist:
- VSS enabled and functional
- Test files created with known content
- Simulated modification detected by SentinelOne
- Manual rollback initiated successfully
- Files restored to original state
- Automatic rollback tested (if configured)
- Results documented for compliance
SECTION 3: REMEDIATION ACTIONS
3.1 Kill Process Remediation
Terminates malicious processes immediately.
Via Console:
- Navigate to threat or endpoint
- Click Actions > Kill
- Confirm termination
Via API:
# Kill threat processes
$threatId = "1234567890"
$killBody = @{
data = @{
ids = @($threatId)
}
} | ConvertTo-Json
$result = Invoke-RestMethod `
-Uri "$consoleUrl/web/api/v2.1/threats/actions/kill" `
-Method POST `
-Headers $headers `
-Body $killBody
Write-Host "Kill action affected $($result.data.affected) threat(s)"MITRE ATT&CK: Disrupts active execution (T1059, T1106)
3.2 Quarantine File Remediation
Moves malicious files to encrypted quarantine storage.
Via Console:
- Navigate to threat
- Click Actions > Quarantine
- File moved to
C:\ProgramData\Sentinel\Quarantine\
Via API:
# Quarantine threat
$threatId = "1234567890"
$quarantineBody = @{
data = @{
ids = @($threatId)
}
} | ConvertTo-Json
$result = Invoke-RestMethod `
-Uri "$consoleUrl/web/api/v2.1/threats/actions/quarantine" `
-Method POST `
-Headers $headers `
-Body $quarantineBody
Write-Host "Quarantine action affected $($result.data.affected) threat(s)"Quarantine Management:
# List quarantined items
$quarantined = Invoke-RestMethod `
-Uri "$consoleUrl/web/api/v2.1/threats?mitigationStatuses=quarantined" `
-Headers $headers
$quarantined.data | Select-Object `
@{N="ThreatName";E={$_.threatInfo.threatName}},
@{N="Computer";E={$_.agentRealtimeInfo.computerName}},
@{N="QuarantinedAt";E={$_.threatInfo.mitigatedAt}} |
Format-Table -AutoSize
# Restore from quarantine (false positive)
$unquarantineBody = @{
data = @{
ids = @($threatId)
}
} | ConvertTo-Json
Invoke-RestMethod `
-Uri "$consoleUrl/web/api/v2.1/threats/actions/un-quarantine" `
-Method POST `
-Headers $headers `
-Body $unquarantineBody3.3 Remediate & Kill Actions
Combined action that kills processes AND removes persistence mechanisms.
Full Remediation Includes:
- Kill all threat processes
- Quarantine malicious files
- Remove registry persistence
- Delete scheduled tasks
- Remove services
- Clean startup items
Via Console:
- Navigate to threat
- Click Actions > Remediate & Kill
- All associated artifacts cleaned
Via API:
# Full remediation
$threatId = "1234567890"
$remediateBody = @{
data = @{
ids = @($threatId)
}
} | ConvertTo-Json
$result = Invoke-RestMethod `
-Uri "$consoleUrl/web/api/v2.1/threats/actions/remediate" `
-Method POST `
-Headers $headers `
-Body $remediateBody
Write-Host "Remediation affected $($result.data.affected) threat(s)"3.4 Network Quarantine (Isolation)
Isolates endpoint from network while maintaining SentinelOne console communication.
When to Use:
- Active ransomware spreading laterally
- Data exfiltration in progress
- Compromised endpoint pending investigation
- Preventing C2 communication
Via Console:
- Navigate to Sentinels > Endpoints
- Select endpoint
- Click Actions > Network Quarantine
- Confirm isolation
Via API:
# Network quarantine endpoint
$agentId = "1234567890123456789"
$isolateBody = @{
data = @{
ids = @($agentId)
}
} | ConvertTo-Json
# Isolate
$result = Invoke-RestMethod `
-Uri "$consoleUrl/web/api/v2.1/agents/actions/disconnect" `
-Method POST `
-Headers $headers `
-Body $isolateBody
Write-Host "Isolated $($result.data.affected) endpoint(s)"
# Reconnect after investigation
$reconnectResult = Invoke-RestMethod `
-Uri "$consoleUrl/web/api/v2.1/agents/actions/connect" `
-Method POST `
-Headers $headers `
-Body $isolateBody
Write-Host "Reconnected $($reconnectResult.data.affected) endpoint(s)"Network Quarantine Behavior:
- All network traffic blocked except SentinelOne management
- User sees no network connectivity
- Remote Shell still accessible for investigation
- DNS queries blocked
- Persists across reboots until released
3.5 Custom Remediation Scripts via Remote Shell
For complex remediation requiring custom actions.
Common Remediation Commands:
# === PERSISTENCE REMOVAL ===
# Remove malicious Run key
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "MaliciousEntry" -Force
# Remove malicious scheduled task
Unregister-ScheduledTask -TaskName "MalwareTask" -Confirm:$false
# Remove malicious service
Stop-Service -Name "MaliciousService" -Force -ErrorAction SilentlyContinue
sc.exe delete "MaliciousService"
# Remove startup folder items
Remove-Item "C:\Users\*\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\malware.lnk" -Force
# === FILE CLEANUP ===
# Remove specific malware files
Remove-Item "C:\Users\Public\malware.exe" -Force
Remove-Item "C:\ProgramData\MalwareFolder" -Recurse -Force
# Remove files by pattern
Get-ChildItem -Path C:\ -Recurse -Include "*.encrypted" -ErrorAction SilentlyContinue | Remove-Item -Force
# === PROCESS TERMINATION ===
# Kill process by name
Stop-Process -Name "malicious_process" -Force
# Kill process by PID
Stop-Process -Id 1234 -Force
# Kill processes running from temp
Get-Process | Where-Object {$_.Path -like "*\Temp\*"} | Stop-Process -Force
# === NETWORK CLEANUP ===
# Remove malicious hosts file entries
$hostsFile = "C:\Windows\System32\drivers\etc\hosts"
$content = Get-Content $hostsFile | Where-Object {$_ -notmatch "malicious-domain.com"}
$content | Set-Content $hostsFile
# Reset DNS cache
Clear-DnsClientCache
# Block malicious IP via firewall
New-NetFirewallRule -DisplayName "Block Malicious IP" -Direction Outbound -RemoteAddress "192.0.2.100" -Action Block
# === CREDENTIAL HYGIENE ===
# Force password change on next logon (run as admin)
net user username /logonpasswordchg:yes
# Clear credential cache
cmdkey /list | ForEach-Object {
if ($_ -match "Target: (.+)") {
cmdkey /delete:$matches[1]
}
}3.6 Bulk Remediation Across Endpoints
For incidents affecting multiple endpoints.
Bulk Threat Remediation Script:
<#
.SYNOPSIS
Bulk remediation script for SentinelOne threats
.DESCRIPTION
Performs bulk remediation actions across multiple threats/endpoints
.PARAMETER Action
Remediation action: Kill, Quarantine, Remediate, Rollback
.PARAMETER ThreatFilter
Filter criteria for threats to remediate
#>
param(
[Parameter(Mandatory=$true)]
[ValidateSet('Kill','Quarantine','Remediate','Rollback')]
[string]$Action,
[Parameter(Mandatory=$false)]
[string]$Classification = "ransomware",
[Parameter(Mandatory=$false)]
[int]$DaysBack = 1,
[Parameter(Mandatory=$true)]
[string]$ApiToken,
[Parameter(Mandatory=$true)]
[string]$ConsoleUrl
)
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
# Build filter
$dateFilter = (Get-Date).AddDays(-$DaysBack).ToString("yyyy-MM-ddT00:00:00Z")
$endpoint = "/web/api/v2.1/threats?resolved=false&classifications=$Classification&createdAt__gte=$dateFilter"
Write-Host "=== SentinelOne Bulk Remediation ===" -ForegroundColor Cyan
Write-Host "Action: $Action"
Write-Host "Classification: $Classification"
Write-Host "Date Filter: Last $DaysBack day(s)"
# Get matching threats
$threats = Invoke-RestMethod -Uri "$ConsoleUrl$endpoint" -Headers $headers
$threatCount = $threats.pagination.totalItems
Write-Host "`nFound $threatCount threat(s) matching criteria" -ForegroundColor Yellow
if ($threatCount -eq 0) {
Write-Host "No threats to process. Exiting." -ForegroundColor Green
exit 0
}
# Display threats for confirmation
$threats.data | ForEach-Object {
Write-Host " - $($_.id): $($_.threatInfo.threatName) on $($_.agentRealtimeInfo.computerName)"
}
$confirm = Read-Host "`nProceed with $Action on $threatCount threat(s)? (yes/no)"
if ($confirm -ne "yes") {
Write-Host "Operation cancelled." -ForegroundColor Yellow
exit 0
}
# Perform remediation
$threatIds = $threats.data | Select-Object -ExpandProperty id
$actionBody = @{
data = @{
ids = $threatIds
}
} | ConvertTo-Json
$actionEndpoint = switch ($Action) {
'Kill' { "/web/api/v2.1/threats/actions/kill" }
'Quarantine' { "/web/api/v2.1/threats/actions/quarantine" }
'Remediate' { "/web/api/v2.1/threats/actions/remediate" }
'Rollback' { "/web/api/v2.1/threats/actions/rollback" }
}
try {
$result = Invoke-RestMethod `
-Uri "$ConsoleUrl$actionEndpoint" `
-Method POST `
-Headers $headers `
-Body $actionBody
Write-Host "`n[SUCCESS] $Action completed on $($result.data.affected) threat(s)" -ForegroundColor Green
}
catch {
Write-Host "`n[ERROR] $Action failed: $($_.Exception.Message)" -ForegroundColor Red
}
# Log results
$logEntry = @{
Timestamp = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
Action = $Action
ThreatCount = $threatCount
ThreatIds = $threatIds
Result = if ($result) { "Success" } else { "Failed" }
} | ConvertTo-Json
$logPath = "C:\BIN\LOGS\S1-BulkRemediation-$(Get-Date -Format 'yyyyMMdd-HHmmss').json"
$logEntry | Out-File $logPath
Write-Host "Log saved to: $logPath"SECTION 4: INCIDENT RESPONSE WORKFLOWS
4.1 Initial Triage Procedures
Triage Decision Tree:
┌─────────────────┐
│ Alert Received │
└────────┬────────┘
│
┌────────▼────────┐
│ Check Confidence│
│ Level │
└────────┬────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ HIGH │ │ MEDIUM │ │ LOW │
│ Immediate │ │ Review │ │ Monitor │
│ Action │ │ Required │ │ Only │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ • Isolate │ │ • Analyze │ │ • Log event │
│ • Preserve │ │ Storyline │ │ • Schedule │
│ • Escalate │ │ • Check VT │ │ review │
└─────────────┘ │ • Decide │ └─────────────┘
└─────────────┘
Initial Triage Script:
<#
.SYNOPSIS
Initial threat triage script for SentinelOne alerts
#>
param(
[Parameter(Mandatory=$true)]
[string]$ThreatId,
[string]$ApiToken,
[string]$ConsoleUrl
)
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
Write-Host "=== THREAT TRIAGE: $ThreatId ===" -ForegroundColor Cyan
# Get threat details
$threat = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId" -Headers $headers).data
# Display summary
Write-Host "`n[THREAT SUMMARY]" -ForegroundColor Yellow
Write-Host " Name: $($threat.threatInfo.threatName)"
Write-Host " Classification: $($threat.threatInfo.classification)"
Write-Host " Confidence: $($threat.threatInfo.confidenceLevel)"
Write-Host " Engine: $($threat.threatInfo.detectionEngines -join ', ')"
Write-Host " Status: $($threat.threatInfo.mitigationStatus)"
Write-Host "`n[ENDPOINT]" -ForegroundColor Yellow
Write-Host " Computer: $($threat.agentRealtimeInfo.computerName)"
Write-Host " User: $($threat.threatInfo.processUser)"
Write-Host " OS: $($threat.agentRealtimeInfo.osName)"
Write-Host " Agent: $($threat.agentRealtimeInfo.agentVersion)"
Write-Host "`n[FILE DETAILS]" -ForegroundColor Yellow
Write-Host " Path: $($threat.threatInfo.filePath)"
Write-Host " SHA256: $($threat.threatInfo.sha256)"
Write-Host " SHA1: $($threat.threatInfo.sha1)"
Write-Host " MD5: $($threat.threatInfo.md5)"
# VirusTotal lookup
Write-Host "`n[THREAT INTELLIGENCE]" -ForegroundColor Yellow
$vtUrl = "https://www.virustotal.com/gui/file/$($threat.threatInfo.sha256)"
Write-Host " VirusTotal: $vtUrl"
# Triage recommendation
Write-Host "`n[TRIAGE RECOMMENDATION]" -ForegroundColor Magenta
$confidence = $threat.threatInfo.confidenceLevel
$classification = $threat.threatInfo.classification
if ($confidence -eq "high" -and $classification -in @("ransomware", "trojan", "malware")) {
Write-Host " CRITICAL - Immediate isolation and remediation required" -ForegroundColor Red
Write-Host " Recommended Actions:"
Write-Host " 1. Network quarantine endpoint"
Write-Host " 2. Full remediation (Kill + Quarantine)"
Write-Host " 3. Check for lateral movement"
Write-Host " 4. Collect forensic evidence"
} elseif ($confidence -eq "medium") {
Write-Host " ELEVATED - Investigation required" -ForegroundColor Yellow
Write-Host " Recommended Actions:"
Write-Host " 1. Review Storyline for context"
Write-Host " 2. Check VirusTotal results"
Write-Host " 3. Determine if legitimate software"
} else {
Write-Host " LOW - Monitor and review" -ForegroundColor Green
Write-Host " Recommended Actions:"
Write-Host " 1. Document for trending analysis"
Write-Host " 2. Schedule periodic review"
}
# Output for ticket system
$triageReport = @{
ThreatId = $ThreatId
TriageTime = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
Analyst = $env:USERNAME
Confidence = $confidence
Classification = $classification
Endpoint = $threat.agentRealtimeInfo.computerName
Recommendation = if ($confidence -eq "high") { "CRITICAL" } elseif ($confidence -eq "medium") { "ELEVATED" } else { "LOW" }
}
$triageReport | ConvertTo-Json | Out-File "C:\BIN\LOGS\Triage-$ThreatId.json"
Write-Host "`nTriage report saved to: C:\BIN\LOGS\Triage-$ThreatId.json"4.2 Containment Strategies
Containment Matrix:
| Threat Type | Primary Containment | Secondary Containment | Notes |
|---|---|---|---|
| Ransomware (Active) | Network Quarantine | Kill + Rollback | Speed critical |
| Ransomware (Detected) | Kill + Quarantine | Rollback | Verify no spread |
| Trojan/RAT | Network Quarantine | Full Remediation | Prevent C2 |
| Cryptominer | Kill Process | Block Pool IPs | Lower priority |
| Lateral Movement | Network Quarantine All | Credential Reset | Scope critical |
| Data Exfiltration | Network Quarantine | Forensic Collection | Preserve evidence |
Containment Automation Script:
function Invoke-ThreatContainment {
param(
[string]$ThreatId,
[ValidateSet('Ransomware','Trojan','Cryptominer','DataExfil','LateralMovement')]
[string]$ThreatType,
[string]$ApiToken,
[string]$ConsoleUrl
)
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
# Get threat details
$threat = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId" -Headers $headers).data
$agentId = $threat.agentRealtimeInfo.agentId
Write-Host "Containing $ThreatType threat on $($threat.agentRealtimeInfo.computerName)" -ForegroundColor Cyan
switch ($ThreatType) {
'Ransomware' {
# Immediate network isolation
Write-Host " [1/4] Network quarantine..." -ForegroundColor Yellow
$isolateBody = @{data=@{ids=@($agentId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/agents/actions/disconnect" -Method POST -Headers $headers -Body $isolateBody
# Kill processes
Write-Host " [2/4] Killing threat processes..." -ForegroundColor Yellow
$killBody = @{data=@{ids=@($ThreatId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/kill" -Method POST -Headers $headers -Body $killBody
# Quarantine files
Write-Host " [3/4] Quarantining malicious files..." -ForegroundColor Yellow
$quarantineBody = @{data=@{ids=@($ThreatId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/quarantine" -Method POST -Headers $headers -Body $quarantineBody
# Initiate rollback
Write-Host " [4/4] Initiating rollback..." -ForegroundColor Yellow
$rollbackBody = @{data=@{ids=@($ThreatId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/rollback" -Method POST -Headers $headers -Body $rollbackBody
Write-Host "[CONTAINED] Ransomware containment complete" -ForegroundColor Green
}
'Trojan' {
Write-Host " [1/3] Network quarantine..." -ForegroundColor Yellow
$isolateBody = @{data=@{ids=@($agentId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/agents/actions/disconnect" -Method POST -Headers $headers -Body $isolateBody
Write-Host " [2/3] Full remediation..." -ForegroundColor Yellow
$remediateBody = @{data=@{ids=@($ThreatId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/remediate" -Method POST -Headers $headers -Body $remediateBody
Write-Host " [3/3] Endpoint remains isolated pending investigation" -ForegroundColor Yellow
Write-Host "[CONTAINED] Trojan containment complete - manual review required" -ForegroundColor Green
}
'Cryptominer' {
Write-Host " [1/2] Killing miner processes..." -ForegroundColor Yellow
$killBody = @{data=@{ids=@($ThreatId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/kill" -Method POST -Headers $headers -Body $killBody
Write-Host " [2/2] Quarantining miner files..." -ForegroundColor Yellow
$quarantineBody = @{data=@{ids=@($ThreatId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/quarantine" -Method POST -Headers $headers -Body $quarantineBody
Write-Host "[CONTAINED] Cryptominer stopped - no isolation required" -ForegroundColor Green
}
default {
Write-Host " Performing standard containment..." -ForegroundColor Yellow
$remediateBody = @{data=@{ids=@($ThreatId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/remediate" -Method POST -Headers $headers -Body $remediateBody
Write-Host "[CONTAINED] Standard containment complete" -ForegroundColor Green
}
}
}4.3 Eradication Steps
Comprehensive Eradication Checklist:
## Eradication Checklist
### Phase 1: Primary Threat Removal
- [ ] All malicious processes terminated
- [ ] Malicious files quarantined
- [ ] Registry persistence removed
- [ ] Scheduled tasks deleted
- [ ] Malicious services removed
- [ ] Startup items cleaned
### Phase 2: Secondary Cleanup
- [ ] Temp folders cleaned
- [ ] Browser cache cleared
- [ ] Downloaded malware removed
- [ ] Dropped payloads deleted
- [ ] Config files removed
### Phase 3: System Verification
- [ ] Full system scan completed
- [ ] Deep Visibility query shows no IOCs
- [ ] No suspicious processes running
- [ ] No unusual network connections
- [ ] Event logs reviewed
### Phase 4: Credential Hygiene
- [ ] Local admin password changed
- [ ] Domain credentials reset (if compromised)
- [ ] Service account passwords rotated
- [ ] Cached credentials cleared
- [ ] MFA verified/enabledAutomated Eradication Script:
function Invoke-ThreatEradication {
param(
[string]$ThreatId,
[string]$ApiToken,
[string]$ConsoleUrl
)
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
Write-Host "=== THREAT ERADICATION: $ThreatId ===" -ForegroundColor Cyan
# Get threat details
$threat = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId" -Headers $headers).data
# Phase 1: Primary removal
Write-Host "`n[Phase 1] Primary Threat Removal" -ForegroundColor Yellow
$remediateBody = @{data=@{ids=@($ThreatId)}} | ConvertTo-Json
$result = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/remediate" -Method POST -Headers $headers -Body $remediateBody
Write-Host " Remediation action completed: $($result.data.affected) threat(s)"
# Phase 2: Verify via Deep Visibility
Write-Host "`n[Phase 2] Verification Query" -ForegroundColor Yellow
$sha256 = $threat.threatInfo.sha256
$endpoint = $threat.agentRealtimeInfo.computerName
Write-Host " Query Deep Visibility for residual IOCs:"
Write-Host " EndpointName = `"$endpoint`" AND SHA256 = `"$sha256`""
# Phase 3: Mark resolved
Write-Host "`n[Phase 3] Resolution" -ForegroundColor Yellow
$resolveBody = @{
data = @{
threatIds = @($ThreatId)
resolution = "confirmed_threat"
analystNote = "Eradication completed $(Get-Date -Format 'yyyy-MM-dd HH:mm'). Remediation actions: Kill, Quarantine, Remove persistence. Verified via Deep Visibility."
}
} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/mark-as-resolved" -Method POST -Headers $headers -Body $resolveBody
Write-Host " Threat marked as resolved"
Write-Host "`n[ERADICATION COMPLETE]" -ForegroundColor Green
}4.4 Recovery Procedures
Recovery Workflow:
Recovery Process:
┌─────────────────────────────────────────────────────────────────┐
│ 1. VERIFY ERADICATION │
│ • Deep Visibility confirms no active IOCs │
│ • Full scan shows clean │
│ • No suspicious processes or connections │
└─────────────────────────────────┬───────────────────────────────┘
│
┌─────────────────────────────────▼───────────────────────────────┐
│ 2. RESTORE NETWORK ACCESS │
│ • Remove network quarantine │
│ • Verify connectivity │
│ • Test critical application access │
└─────────────────────────────────┬───────────────────────────────┘
│
┌─────────────────────────────────▼───────────────────────────────┐
│ 3. RESTORE DATA (if needed) │
│ • Rollback completed files verified │
│ • Restore from backup if rollback incomplete │
│ • Verify data integrity │
└─────────────────────────────────┬───────────────────────────────┘
│
┌─────────────────────────────────▼───────────────────────────────┐
│ 4. USER COMMUNICATION │
│ • Notify user of restoration │
│ • Provide security awareness guidance │
│ • Document any remaining actions │
└─────────────────────────────────┬───────────────────────────────┘
│
┌─────────────────────────────────▼───────────────────────────────┐
│ 5. MONITORING │
│ • Enable enhanced monitoring for 7 days │
│ • Create watchlist for endpoint │
│ • Schedule follow-up verification │
└─────────────────────────────────────────────────────────────────┘
Recovery Script:
function Invoke-EndpointRecovery {
param(
[string]$AgentId,
[string]$ThreatId,
[string]$ApiToken,
[string]$ConsoleUrl
)
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
Write-Host "=== ENDPOINT RECOVERY ===" -ForegroundColor Cyan
# Step 1: Verify clean state
Write-Host "`n[Step 1] Verifying endpoint clean state..." -ForegroundColor Yellow
$agent = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/agents?ids=$AgentId" -Headers $headers).data[0]
if ($agent.infected) {
Write-Host " WARNING: Endpoint still shows infected status" -ForegroundColor Red
Write-Host " Please complete eradication before recovery"
return
}
Write-Host " Endpoint shows clean" -ForegroundColor Green
# Step 2: Remove network quarantine
Write-Host "`n[Step 2] Removing network quarantine..." -ForegroundColor Yellow
if ($agent.networkStatus -eq "disconnected") {
$connectBody = @{data=@{ids=@($AgentId)}} | ConvertTo-Json
Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/agents/actions/connect" -Method POST -Headers $headers -Body $connectBody
Write-Host " Network access restored" -ForegroundColor Green
} else {
Write-Host " Endpoint already connected" -ForegroundColor Green
}
# Step 3: Verify rollback status
Write-Host "`n[Step 3] Checking rollback status..." -ForegroundColor Yellow
if ($ThreatId) {
$threat = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId" -Headers $headers).data
$rollbackStatus = $threat.threatInfo.rollbackStatus
Write-Host " Rollback status: $rollbackStatus"
if ($rollbackStatus -eq "completed") {
Write-Host " Files restored successfully" -ForegroundColor Green
} elseif ($rollbackStatus -eq "failed") {
Write-Host " Rollback failed - manual restoration required" -ForegroundColor Red
}
}
# Step 4: Generate recovery report
Write-Host "`n[Step 4] Generating recovery report..." -ForegroundColor Yellow
$recoveryReport = @{
RecoveryDate = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
Analyst = $env:USERNAME
AgentId = $AgentId
Endpoint = $agent.computerName
ThreatId = $ThreatId
NetworkRestored = $true
RollbackStatus = $rollbackStatus
VerificationStatus = "Clean"
}
$reportPath = "C:\BIN\LOGS\Recovery-$AgentId-$(Get-Date -Format 'yyyyMMdd').json"
$recoveryReport | ConvertTo-Json | Out-File $reportPath
Write-Host " Report saved: $reportPath"
Write-Host "`n[RECOVERY COMPLETE]" -ForegroundColor Green
Write-Host "Recommended: Monitor endpoint for 7 days"
}4.5 Post-Incident Analysis
Lessons Learned Template:
# Post-Incident Analysis Report
## Incident Summary
- **Incident ID:** INC-2026-0108-001
- **Date/Time Detected:** 2026-01-08 14:32 UTC
- **Date/Time Resolved:** 2026-01-08 16:45 UTC
- **Total Duration:** 2 hours 13 minutes
- **Affected Systems:** 1 endpoint (WORKSTATION-001)
- **Affected Users:** 1 (john.doe)
- **Data Impact:** None (rollback successful)
## Attack Summary
- **Initial Access:** Phishing email with malicious attachment
- **Execution:** User opened Word document, enabled macros
- **Persistence:** Scheduled task created
- **Impact:** Ransomware encryption attempt (blocked)
## Timeline
| Time (UTC) | Event |
|------------|-------|
| 14:30 | Phishing email received |
| 14:32 | User opened attachment |
| 14:32 | Macro executed PowerShell |
| 14:33 | SentinelOne detected ransomware behavior |
| 14:33 | Automatic kill and quarantine |
| 14:35 | SOC notified via alert |
| 14:40 | Analyst initiated network quarantine |
| 14:45 | Rollback initiated |
| 14:50 | Rollback completed |
| 15:30 | Investigation completed |
| 16:00 | Network quarantine removed |
| 16:30 | User notified |
| 16:45 | Incident closed |
## MITRE ATT&CK Mapping
- T1566.001 - Phishing: Spearphishing Attachment
- T1204.002 - User Execution: Malicious File
- T1059.001 - Command and Scripting Interpreter: PowerShell
- T1053.005 - Scheduled Task/Job: Scheduled Task
- T1486 - Data Encrypted for Impact
## Detection Analysis
- **Detection Method:** Behavioral AI
- **Detection Time:** < 1 minute from execution
- **False Positive:** No
- **Detection Gap:** None identified
## Response Effectiveness
- **Containment Time:** 8 minutes
- **Eradication Time:** 15 minutes
- **Recovery Time:** 2 hours
- **Data Loss:** None
## Lessons Learned
1. **What Worked:**
- Behavioral AI detected ransomware immediately
- Automatic kill prevented encryption spread
- Rollback restored affected files
- SOC response within SLA
2. **Improvement Areas:**
- User clicked despite phishing training
- Email gateway did not block attachment
- Need macro-blocking policy review
## Recommendations
1. Deploy email attachment sandboxing
2. Enable Office macro blocking by default
3. Schedule targeted phishing training for affected user
4. Create STAR rule for similar attack patterns
## Follow-Up Actions
- [ ] Block sending domain at email gateway
- [ ] Update firewall rules for C2 IPs
- [ ] Share IOCs with threat intelligence platform
- [ ] Schedule user security awareness training4.6 Documentation and Reporting
Incident Report Generation Script:
function New-IncidentReport {
param(
[Parameter(Mandatory=$true)]
[string]$ThreatId,
[string]$ApiToken,
[string]$ConsoleUrl,
[string]$OutputPath = "C:\BIN\LOGS"
)
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
# Gather data
$threat = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId" -Headers $headers).data
$timeline = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId/timeline" -Headers $headers).data
# Build report
$report = @"
# SentinelOne Incident Report
## Executive Summary
- **Incident ID:** $ThreatId
- **Generated:** $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
- **Analyst:** $env:USERNAME
## Threat Details
| Field | Value |
|-------|-------|
| Threat Name | $($threat.threatInfo.threatName) |
| Classification | $($threat.threatInfo.classification) |
| Confidence | $($threat.threatInfo.confidenceLevel) |
| Detection Engine | $($threat.threatInfo.detectionEngines -join ', ') |
| Status | $($threat.threatInfo.mitigationStatus) |
| Resolved | $($threat.threatInfo.resolved) |
## Affected Endpoint
| Field | Value |
|-------|-------|
| Computer | $($threat.agentRealtimeInfo.computerName) |
| Domain | $($threat.agentRealtimeInfo.domain) |
| OS | $($threat.agentRealtimeInfo.osName) |
| User | $($threat.threatInfo.processUser) |
| IP Address | $($threat.agentRealtimeInfo.externalIp) |
## File Information
| Field | Value |
|-------|-------|
| File Name | $($threat.threatInfo.originatorProcess) |
| File Path | $($threat.threatInfo.filePath) |
| SHA256 | $($threat.threatInfo.sha256) |
| SHA1 | $($threat.threatInfo.sha1) |
| MD5 | $($threat.threatInfo.md5) |
## Timeline Summary
| Time | Event Type | Details |
|------|------------|---------|
"@
# Add timeline events
$timeline | Select-Object -First 20 | ForEach-Object {
$report += "| $($_.createdAt) | $($_.eventType) | $($_.processName) |`n"
}
$report += @"
## Actions Taken
- Mitigation Status: $($threat.threatInfo.mitigationStatus)
- Rollback Status: $($threat.threatInfo.rollbackStatus)
## Recommendations
1. Review user security awareness
2. Update detection rules if needed
3. Share IOCs with threat intelligence
---
*Report generated by SentinelOne Automation*
"@
# Save report
$fileName = "IncidentReport-$ThreatId-$(Get-Date -Format 'yyyyMMdd-HHmmss').md"
$fullPath = Join-Path $OutputPath $fileName
$report | Out-File $fullPath -Encoding UTF8
Write-Host "Report saved to: $fullPath" -ForegroundColor Green
return $fullPath
}SECTION 5: POWERSHELL AUTOMATION SCRIPTS
5.1 Automated Evidence Collection Script
<#
.SYNOPSIS
Automated forensic evidence collection from SentinelOne
.DESCRIPTION
Collects threat data, storyline, Deep Visibility queries, and endpoint artifacts
.PARAMETER ThreatId
SentinelOne threat ID to investigate
.PARAMETER ApiToken
SentinelOne API token
.PARAMETER ConsoleUrl
SentinelOne console URL
.PARAMETER OutputPath
Path to save collected evidence
.EXAMPLE
.\Collect-S1Evidence.ps1 -ThreatId "123456" -ApiToken "token" -ConsoleUrl "https://tenant.sentinelone.net"
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$ThreatId,
[Parameter(Mandatory=$true)]
[string]$ApiToken,
[Parameter(Mandatory=$true)]
[string]$ConsoleUrl,
[string]$OutputPath = "C:\Evidence"
)
$ErrorActionPreference = 'Stop'
# Create evidence folder
$evidenceFolder = Join-Path $OutputPath "S1-Evidence-$ThreatId-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
New-Item -Path $evidenceFolder -ItemType Directory -Force | Out-Null
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
Write-Host "=== SentinelOne Evidence Collection ===" -ForegroundColor Cyan
Write-Host "Threat ID: $ThreatId"
Write-Host "Evidence Folder: $evidenceFolder`n"
# Initialize chain of custody
$chainOfCustody = @{
CaseId = "S1-$ThreatId"
CollectionStarted = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
Collector = $env:USERNAME
CollectorHost = $env:COMPUTERNAME
Items = @()
}
try {
# 1. Collect threat details
Write-Host "[1/5] Collecting threat details..." -ForegroundColor Yellow
$threat = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId" -Headers $headers
$threatFile = Join-Path $evidenceFolder "threat-details.json"
$threat | ConvertTo-Json -Depth 20 | Out-File $threatFile
$chainOfCustody.Items += @{
ItemId = "EVD-001"
Description = "Threat Details JSON"
FileName = "threat-details.json"
CollectedAt = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
SHA256 = (Get-FileHash $threatFile -Algorithm SHA256).Hash
}
Write-Host " Saved: threat-details.json" -ForegroundColor Green
# 2. Collect timeline/storyline
Write-Host "[2/5] Collecting threat timeline..." -ForegroundColor Yellow
$timeline = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId/timeline" -Headers $headers
$timelineFile = Join-Path $evidenceFolder "threat-timeline.json"
$timeline | ConvertTo-Json -Depth 20 | Out-File $timelineFile
$chainOfCustody.Items += @{
ItemId = "EVD-002"
Description = "Threat Timeline/Storyline"
FileName = "threat-timeline.json"
CollectedAt = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
SHA256 = (Get-FileHash $timelineFile -Algorithm SHA256).Hash
}
Write-Host " Saved: threat-timeline.json" -ForegroundColor Green
# 3. Collect agent details
Write-Host "[3/5] Collecting endpoint details..." -ForegroundColor Yellow
$agentId = $threat.data.agentRealtimeInfo.agentId
$agent = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/agents?ids=$agentId" -Headers $headers
$agentFile = Join-Path $evidenceFolder "endpoint-details.json"
$agent | ConvertTo-Json -Depth 20 | Out-File $agentFile
$chainOfCustody.Items += @{
ItemId = "EVD-003"
Description = "Endpoint Agent Details"
FileName = "endpoint-details.json"
CollectedAt = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
SHA256 = (Get-FileHash $agentFile -Algorithm SHA256).Hash
}
Write-Host " Saved: endpoint-details.json" -ForegroundColor Green
# 4. Run Deep Visibility queries
Write-Host "[4/5] Running Deep Visibility queries..." -ForegroundColor Yellow
$endpoint = $threat.data.agentRealtimeInfo.computerName
$sha256 = $threat.data.threatInfo.sha256
$detectionTime = $threat.data.threatInfo.createdAt
# Query for all activity around detection time
$dvQueryBody = @{
query = "EndpointName = `"$endpoint`" AND CreatedAt >= `"$detectionTime`""
fromDate = $detectionTime
toDate = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ssZ")
limit = 1000
} | ConvertTo-Json
try {
$dvResults = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/dv/query" -Method POST -Headers $headers -Body $dvQueryBody
$dvFile = Join-Path $evidenceFolder "deep-visibility-events.json"
$dvResults | ConvertTo-Json -Depth 20 | Out-File $dvFile
$chainOfCustody.Items += @{
ItemId = "EVD-004"
Description = "Deep Visibility Query Results"
FileName = "deep-visibility-events.json"
CollectedAt = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
SHA256 = (Get-FileHash $dvFile -Algorithm SHA256).Hash
}
Write-Host " Saved: deep-visibility-events.json" -ForegroundColor Green
}
catch {
Write-Host " WARNING: Deep Visibility query failed - $($_.Exception.Message)" -ForegroundColor Yellow
}
# 5. Generate summary report
Write-Host "[5/5] Generating evidence summary..." -ForegroundColor Yellow
$summary = @"
# Evidence Collection Summary
## Case Information
- **Threat ID:** $ThreatId
- **Collection Date:** $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
- **Collector:** $env:USERNAME
## Threat Summary
- **Name:** $($threat.data.threatInfo.threatName)
- **Classification:** $($threat.data.threatInfo.classification)
- **Confidence:** $($threat.data.threatInfo.confidenceLevel)
## Affected Endpoint
- **Computer:** $($threat.data.agentRealtimeInfo.computerName)
- **User:** $($threat.data.threatInfo.processUser)
## IOCs
- **SHA256:** $sha256
- **SHA1:** $($threat.data.threatInfo.sha1)
- **MD5:** $($threat.data.threatInfo.md5)
- **File Path:** $($threat.data.threatInfo.filePath)
## Collected Evidence
| Item ID | Description | SHA256 |
|---------|-------------|--------|
"@
foreach ($item in $chainOfCustody.Items) {
$summary += "| $($item.ItemId) | $($item.Description) | $($item.SHA256.Substring(0,16))... |`n"
}
$summaryFile = Join-Path $evidenceFolder "EVIDENCE-SUMMARY.md"
$summary | Out-File $summaryFile
Write-Host " Saved: EVIDENCE-SUMMARY.md" -ForegroundColor Green
# Save chain of custody
$chainOfCustody.CollectionCompleted = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
$cocFile = Join-Path $evidenceFolder "chain-of-custody.json"
$chainOfCustody | ConvertTo-Json -Depth 10 | Out-File $cocFile
Write-Host "`n[COLLECTION COMPLETE]" -ForegroundColor Green
Write-Host "Evidence folder: $evidenceFolder"
Write-Host "Items collected: $($chainOfCustody.Items.Count)"
}
catch {
Write-Host "[ERROR] Collection failed: $($_.Exception.Message)" -ForegroundColor Red
throw
}5.2 Bulk Remediation Script
<#
.SYNOPSIS
Bulk threat remediation across multiple endpoints
.DESCRIPTION
Performs automated remediation actions on threats matching specified criteria
.PARAMETER Action
Remediation action to perform
.PARAMETER Classification
Threat classification to filter
.PARAMETER DaysBack
Number of days to look back for threats
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[ValidateSet('Kill','Quarantine','Remediate','Rollback','NetworkQuarantine')]
[string]$Action,
[Parameter(Mandatory=$false)]
[ValidateSet('ransomware','trojan','malware','pua','cryptominer','all')]
[string]$Classification = 'all',
[int]$DaysBack = 1,
[switch]$Resolved,
[switch]$WhatIf,
[Parameter(Mandatory=$true)]
[string]$ApiToken,
[Parameter(Mandatory=$true)]
[string]$ConsoleUrl
)
$ErrorActionPreference = 'Stop'
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
Write-Host "=== SentinelOne Bulk Remediation ===" -ForegroundColor Cyan
Write-Host "Action: $Action"
Write-Host "Classification: $Classification"
Write-Host "Days Back: $DaysBack"
Write-Host "WhatIf Mode: $WhatIf`n"
# Build query
$dateFilter = (Get-Date).AddDays(-$DaysBack).ToString("yyyy-MM-ddT00:00:00Z")
$queryParams = "resolved=$($Resolved.ToString().ToLower())&createdAt__gte=$dateFilter"
if ($Classification -ne 'all') {
$queryParams += "&classifications=$Classification"
}
$endpoint = "/web/api/v2.1/threats?$queryParams&limit=1000"
# Get threats
Write-Host "Querying threats..." -ForegroundColor Yellow
$threats = Invoke-RestMethod -Uri "$ConsoleUrl$endpoint" -Headers $headers
$threatCount = $threats.pagination.totalItems
if ($threatCount -eq 0) {
Write-Host "No threats found matching criteria" -ForegroundColor Green
exit 0
}
Write-Host "Found $threatCount threat(s)`n" -ForegroundColor Yellow
# Display threats
$threats.data | ForEach-Object {
$status = if ($_.threatInfo.resolved) { "[RESOLVED]" } else { "[ACTIVE]" }
Write-Host " $status $($_.id): $($_.threatInfo.threatName) on $($_.agentRealtimeInfo.computerName)"
}
if ($WhatIf) {
Write-Host "`n[WHATIF] Would perform $Action on $threatCount threat(s)" -ForegroundColor Yellow
exit 0
}
# Confirm
$confirm = Read-Host "`nProceed with $Action on $threatCount threat(s)? (yes/no)"
if ($confirm -ne "yes") {
Write-Host "Operation cancelled" -ForegroundColor Yellow
exit 0
}
# Execute remediation
$threatIds = $threats.data | Select-Object -ExpandProperty id
$agentIds = $threats.data | Select-Object -ExpandProperty @{N="agentId";E={$_.agentRealtimeInfo.agentId}} -Unique
$results = @{
Action = $Action
StartTime = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
ThreatCount = $threatCount
Success = 0
Failed = 0
Details = @()
}
switch ($Action) {
'Kill' {
$body = @{data=@{ids=$threatIds}} | ConvertTo-Json
$result = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/kill" -Method POST -Headers $headers -Body $body
$results.Success = $result.data.affected
}
'Quarantine' {
$body = @{data=@{ids=$threatIds}} | ConvertTo-Json
$result = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/quarantine" -Method POST -Headers $headers -Body $body
$results.Success = $result.data.affected
}
'Remediate' {
$body = @{data=@{ids=$threatIds}} | ConvertTo-Json
$result = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/remediate" -Method POST -Headers $headers -Body $body
$results.Success = $result.data.affected
}
'Rollback' {
$body = @{data=@{ids=$threatIds}} | ConvertTo-Json
$result = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/actions/rollback" -Method POST -Headers $headers -Body $body
$results.Success = $result.data.affected
}
'NetworkQuarantine' {
$body = @{data=@{ids=$agentIds}} | ConvertTo-Json
$result = Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/agents/actions/disconnect" -Method POST -Headers $headers -Body $body
$results.Success = $result.data.affected
}
}
$results.EndTime = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
$results.Failed = $threatCount - $results.Success
Write-Host "`n[REMEDIATION COMPLETE]" -ForegroundColor Green
Write-Host "Success: $($results.Success)"
Write-Host "Failed: $($results.Failed)"
# Save log
$logPath = "C:\BIN\LOGS\S1-BulkRemediation-$(Get-Date -Format 'yyyyMMdd-HHmmss').json"
$results | ConvertTo-Json -Depth 10 | Out-File $logPath
Write-Host "Log saved: $logPath"5.3 Incident Report Generation Script
<#
.SYNOPSIS
Generates comprehensive incident report from SentinelOne threat data
.DESCRIPTION
Creates detailed incident documentation including timeline, IOCs, and MITRE mapping
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$ThreatId,
[string]$IncidentId = "INC-$(Get-Date -Format 'yyyyMMdd')-001",
[Parameter(Mandatory=$true)]
[string]$ApiToken,
[Parameter(Mandatory=$true)]
[string]$ConsoleUrl,
[string]$OutputPath = "C:\BIN\LOGS"
)
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
Write-Host "=== Generating Incident Report ===" -ForegroundColor Cyan
# Gather data
$threat = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId" -Headers $headers).data
$timeline = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$ThreatId/timeline" -Headers $headers).data
# MITRE mapping based on classification
$mitreMapping = switch ($threat.threatInfo.classification) {
'ransomware' { @("T1486 - Data Encrypted for Impact", "T1059 - Command and Scripting Interpreter") }
'trojan' { @("T1059 - Command and Scripting Interpreter", "T1071 - Application Layer Protocol") }
'malware' { @("T1059 - Command and Scripting Interpreter", "T1547 - Boot or Logon Autostart Execution") }
default { @("T1059 - Command and Scripting Interpreter") }
}
# Build report
$report = @"
# Incident Report: $IncidentId
## Executive Summary
| Field | Value |
|-------|-------|
| Incident ID | $IncidentId |
| SentinelOne Threat ID | $ThreatId |
| Report Generated | $(Get-Date -Format "yyyy-MM-dd HH:mm:ss UTC") |
| Analyst | $env:USERNAME |
| Status | $($threat.threatInfo.mitigationStatus) |
| Severity | $($threat.threatInfo.confidenceLevel) |
## Threat Classification
| Field | Value |
|-------|-------|
| Threat Name | $($threat.threatInfo.threatName) |
| Classification | $($threat.threatInfo.classification) |
| Confidence Level | $($threat.threatInfo.confidenceLevel) |
| Detection Engine | $($threat.threatInfo.detectionEngines -join ', ') |
| First Detected | $($threat.threatInfo.createdAt) |
| Mitigated At | $($threat.threatInfo.mitigatedAt) |
## Affected Endpoint
| Field | Value |
|-------|-------|
| Computer Name | $($threat.agentRealtimeInfo.computerName) |
| Domain | $($threat.agentRealtimeInfo.domain) |
| Operating System | $($threat.agentRealtimeInfo.osName) |
| Agent Version | $($threat.agentRealtimeInfo.agentVersion) |
| External IP | $($threat.agentRealtimeInfo.externalIp) |
| Affected User | $($threat.threatInfo.processUser) |
## Indicators of Compromise (IOCs)
### File Indicators
| Type | Value |
|------|-------|
| File Name | $($threat.threatInfo.originatorProcess) |
| File Path | $($threat.threatInfo.filePath) |
| SHA256 | ``$($threat.threatInfo.sha256)`` |
| SHA1 | ``$($threat.threatInfo.sha1)`` |
| MD5 | ``$($threat.threatInfo.md5)`` |
### Network Indicators
"@
# Add network IOCs from timeline
$networkEvents = $timeline | Where-Object { $_.eventType -match "Network|DNS|IP" }
if ($networkEvents) {
$report += "| Destination | Port | Protocol |`n|------------|------|----------|`n"
$networkEvents | Select-Object -First 10 | ForEach-Object {
$report += "| $($_.dstIp) | $($_.dstPort) | $($_.protocol) |`n"
}
} else {
$report += "*No network indicators captured*`n"
}
$report += @"
## MITRE ATT&CK Mapping
"@
foreach ($technique in $mitreMapping) {
$report += "- $technique`n"
}
$report += @"
## Attack Timeline
| Timestamp | Event Type | Process | Details |
|-----------|------------|---------|---------|
"@
$timeline | Select-Object -First 25 | ForEach-Object {
$report += "| $($_.createdAt) | $($_.eventType) | $($_.processName) | $($_.processCmd.Substring(0, [Math]::Min(50, $_.processCmd.Length)))... |`n"
}
$report += @"
## Response Actions
| Action | Status | Timestamp |
|--------|--------|-----------|
| Kill Process | $($threat.threatInfo.mitigationStatus) | $($threat.threatInfo.mitigatedAt) |
| Quarantine File | $($threat.threatInfo.mitigationStatus) | $($threat.threatInfo.mitigatedAt) |
| Rollback | $($threat.threatInfo.rollbackStatus) | N/A |
| Network Quarantine | $($threat.agentRealtimeInfo.networkStatus) | N/A |
## Recommendations
1. **Immediate Actions:**
- Verify complete remediation via Deep Visibility query
- Reset credentials for affected user
- Scan related endpoints for lateral movement
2. **Short-term Actions:**
- Update email filtering rules for similar attacks
- Create STAR rule for this attack pattern
- Brief security team on attack technique
3. **Long-term Actions:**
- Schedule security awareness training
- Review and update detection policies
- Add IOCs to threat intelligence platform
## Appendix
### Deep Visibility Query
``````sql
EndpointName = "$($threat.agentRealtimeInfo.computerName)" AND
SHA256 = "$($threat.threatInfo.sha256)"Related Documentation
Report generated by SentinelOne Incident Report Automation "@
Save report
$fileName = "IncidentReport-$IncidentId-$(Get-Date -Format 'yyyyMMdd-HHmmss').md" $fullPath = Join-Path $OutputPath $fileName $report | Out-File $fullPath -Encoding UTF8
Write-Host "[COMPLETE] Report saved: $fullPath" -ForegroundColor Green
---
### 5.4 Rollback Status Monitoring Script
```powershell
<#
.SYNOPSIS
Monitors rollback status for ransomware threats
.DESCRIPTION
Tracks rollback progress and sends notifications on completion or failure
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string[]]$ThreatIds,
[int]$PollIntervalSeconds = 30,
[int]$TimeoutMinutes = 30,
[Parameter(Mandatory=$true)]
[string]$ApiToken,
[Parameter(Mandatory=$true)]
[string]$ConsoleUrl,
[string]$NotificationWebhook # Optional Teams/Slack webhook
)
$headers = @{
"Authorization" = "ApiToken $ApiToken"
"Content-Type" = "application/json"
}
Write-Host "=== SentinelOne Rollback Monitor ===" -ForegroundColor Cyan
Write-Host "Monitoring $($ThreatIds.Count) threat(s)"
Write-Host "Poll Interval: $PollIntervalSeconds seconds"
Write-Host "Timeout: $TimeoutMinutes minutes`n"
$startTime = Get-Date
$timeout = $startTime.AddMinutes($TimeoutMinutes)
$rollbackStatus = @{}
foreach ($id in $ThreatIds) {
$rollbackStatus[$id] = @{
Status = "pending"
StartTime = $startTime
EndTime = $null
FilesRestored = 0
}
}
function Send-Notification {
param($Message, $Color = "good")
if ($NotificationWebhook) {
$body = @{
text = $Message
attachments = @(@{color = $Color})
} | ConvertTo-Json
try {
Invoke-RestMethod -Uri $NotificationWebhook -Method POST -Body $body -ContentType "application/json"
}
catch {
Write-Host "Failed to send notification: $($_.Exception.Message)" -ForegroundColor Yellow
}
}
}
$pending = $ThreatIds.Clone()
while ($pending.Count -gt 0 -and (Get-Date) -lt $timeout) {
foreach ($threatId in $pending.Clone()) {
try {
$threat = (Invoke-RestMethod -Uri "$ConsoleUrl/web/api/v2.1/threats/$threatId" -Headers $headers).data
$status = $threat.threatInfo.rollbackStatus
$currentStatus = $rollbackStatus[$threatId]
if ($status -ne $currentStatus.Status) {
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] Threat $threatId : $($currentStatus.Status) -> $status" -ForegroundColor Yellow
$rollbackStatus[$threatId].Status = $status
if ($status -eq "completed") {
$rollbackStatus[$threatId].EndTime = Get-Date
$duration = ($rollbackStatus[$threatId].EndTime - $rollbackStatus[$threatId].StartTime).TotalMinutes
Write-Host " [SUCCESS] Rollback completed in $([math]::Round($duration,2)) minutes" -ForegroundColor Green
Send-Notification "Rollback completed for threat $threatId on $($threat.agentRealtimeInfo.computerName)" "good"
$pending = $pending | Where-Object { $_ -ne $threatId }
}
elseif ($status -eq "failed") {
$rollbackStatus[$threatId].EndTime = Get-Date
Write-Host " [FAILED] Rollback failed - manual intervention required" -ForegroundColor Red
Send-Notification "Rollback FAILED for threat $threatId - manual intervention required" "danger"
$pending = $pending | Where-Object { $_ -ne $threatId }
}
}
}
catch {
Write-Host "[ERROR] Failed to check threat $threatId : $($_.Exception.Message)" -ForegroundColor Red
}
}
if ($pending.Count -gt 0) {
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] Waiting $PollIntervalSeconds seconds... ($($pending.Count) pending)" -ForegroundColor Gray
Start-Sleep -Seconds $PollIntervalSeconds
}
}
# Final summary
Write-Host "`n=== ROLLBACK MONITOR SUMMARY ===" -ForegroundColor Cyan
$completed = ($rollbackStatus.Values | Where-Object { $_.Status -eq "completed" }).Count
$failed = ($rollbackStatus.Values | Where-Object { $_.Status -eq "failed" }).Count
$pending = ($rollbackStatus.Values | Where-Object { $_.Status -notin @("completed", "failed") }).Count
Write-Host "Completed: $completed"
Write-Host "Failed: $failed"
Write-Host "Pending/Timeout: $pending"
if ($pending -gt 0) {
Write-Host "`n[WARNING] Some rollbacks did not complete within timeout" -ForegroundColor Yellow
Send-Notification "$pending rollback(s) did not complete within timeout - manual check required" "warning"
}
# Export results
$resultsPath = "C:\BIN\LOGS\RollbackMonitor-$(Get-Date -Format 'yyyyMMdd-HHmmss').json"
$rollbackStatus | ConvertTo-Json -Depth 5 | Out-File $resultsPath
Write-Host "`nResults saved: $resultsPath"
RELATED DOCUMENTATION
- HOWTO- SentinelOne Control vs Complete Feature Comparison
- HOWTO- SentinelOne Threat Investigation Workflow
- HOWTO- SentinelOne Deep Visibility Threat Hunting
- HOWTO- SentinelOne Remote Shell Operations
- HOWTO- SentinelOne STAR Custom Detection Rules
- HOWTO- SentinelOne PowerShell API Automation
SOURCES
- SentinelOne Documentation Portal
- SentinelOne API Documentation
- MITRE ATT&CK Framework
- NIST Computer Security Incident Handling Guide (SP 800-61)
- SANS Incident Response Process
REVISION HISTORY
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2026-01-08 | CosmicBytez | Initial creation |