Automating CrowdStrike Network Containment

In a previous post, we have shown how Velociraptor and CrowdStrike can work together to speed up the deep‑dive phase of an investigation. One topic left open was containment. When an EDR flags genuinely high‑risk behaviour, isolating the host is often the safest move, and—if your rules are well tuned—doing it automatically is even better. What follows is how we do it: we tag every endpoint, then let Fusion SOAR decide, in real time, whether a particular machine may be quarantined, whether a human must approve, or whether that system is off‑limits altogether. At the end, the user sees a custom pop‑up explaining why the network cable vanished.

Requirements

You need permission to upload custom response scripts and create Fusion SOAR workflows to reproduce the workflow. The most straightforward approach is to give yourself the Real‑Time Responder Administrator and Workflow Author roles.

Tagging Systems

Starting off, we define three Falcon grouping tags by hand on which we will decide if containment is allowed or not. SOARGreen is applied to endpoints that may be isolated automatically when critical detection fires. SOAROrange marks assets whose isolation must be approved manually: application servers, terminal servers, and any host with a maintenance window. SOARRed is reserved for systems that are never isolated, such as domain controllers. Tag assignment lives in Host Setup and Management > Host Management and can be applied by OU, operating system build, or explicit hostname list. Automating this phase is possible for example via the Falcon API or by using a dedicated workflow, but in practice, a spreadsheet, a change‑control ticket, and a two‑person review catch far more classification errors.

CrowdStrike Falcon endpoint tagging
CrowdStrike Falcon Endpoint Tagging

Building the Fusion SOAR Workflow

Once tagging is complete, a Fusion SOAR workflow can query those tags and contain a device only when the SOARGreen tag is present. Create a new workflow under Next‑Gen SIEM > Workflows.

  • Trigger: Alert > EPP Detection so that endpoint detections activate the workflow.
  • First action: Get device details; this exposes the host’s tag to subsequent conditions.
  • Condition: the workflow proceeds only if the tag list contains FalconGroupingTags/SOARGreen and the detection severity is Critical or higher. During onboarding, we often lower the threshold once rules have been tuned and false positives have been reduced.
  • Final actions: Contain device, followed by Add comment to alert. The containment note is stored in the log repository; the comment becomes part of the detection record.
CrowdStrike containment SOAR workflow trigger and condition
CrowdStrike containment SOAR workflow trigger and condition

YAML Export of the Workflow

Below is an exported workflow that you can import directly.

# This is an exported workflow. Editing this file is not recommended.

name: Triggered - Remediation - Network Containment
trigger:
    next:
        - get_device_details_6647fac2
    event: Investigatable/EPP
    type: Signal
actions:
    add_comment_to_alert_e6158820:
        id: 7b77cb5d5ff2651cc51c7c4c610d54d1
        properties:
            comment: System ${get_device_details_6647fac2.Device.GetDetails.Hostname} isolated by workflow ${Workflow.Definition.Name}, ${Workflow.Execution.ID}.
            investigatable_id: ${Trigger.Category.Investigatable.InvestigatableID}
    contain_device_33fb3581:
        next:
            - add_comment_to_alert_e6158820
        id: bec9fbeb4999d207937854fd56088107
        properties:
            device_id: ${Trigger.Category.Investigatable.Product.EPP.Sensor.SensorID}
    get_device_details_6647fac2:
        next:
            - host_tags_includes_falcongroupingtagssoargreen_severity_is_greater_than_or_equal_to_critical_a1fcd203
        id: 6265dc947cc2252f74a5f25261ac36a9
        properties:
            device_id: ${Trigger.Category.Investigatable.Product.EPP.Sensor.SensorID}
conditions:
    host_tags_includes_falcongroupingtagssoargreen_severity_is_greater_than_or_equal_to_critical_a1fcd203:
        next:
            - contain_device_33fb3581
        expression: get_device_details_6647fac2.Device.GetDetails.Tags:['FalconGroupingTags/SOARGreen']+Trigger.Category.Investigatable.Severity:>=5
        display:
            - Host tags includes FalconGroupingTags/SOARGreen
            - Severity is greater than or equal to Critical

Adding a Network Containment Notification

Adding a note to the containment action stores the information in the detection record, but the text never reaches the people sitting in front of the keyboard. Hiding detections from the local console is generally desirable—an intruder learns less about the security stack, although he could do so fairly simply—but isolation is different.

CrowdStrike endpoint containment note
CrowdStrike endpoint containment note

When a workstation loses network access, the user needs to know why. A straightforward way to deliver that explanation on Windows is the msg cmdlet, which shows a pop‑up in every active session. Navigate to Host Setup and Management > Response Scripts and Files, create a new script, and insert a single line such as msg * "CrowdStrike has quarantined this system. Stop work. Keep it on and online. SOC or CERT will message you via Teams when it’s safe. Need help? Call +49 (0) 123 123 12".

CrowdStrike PowerShell response script
CrowdStrike PowerShell response script

Saving the script makes it available to the workflow. When the isolation step executes, the script broadcasts the message so that each logged‑in user immediately sees why the endpoint has been taken off the network.

CrowdStrike containment SOAR workflow results
CrowdStrike containment SOAR workflow results

Improving the User Notifications

The workflow now isolates Windows hosts on critical detections, appends a note to the alert, and delivers a transient console message. The next step is to ensure the notice should is visually appealing and remains on‑screen until acknowledged.

The following screenshot shows what we’ve had so far.

CrowdStrike basic SOAR workflow
CrowdStrike basic SOAR workflow

Designing a Permanent Pop‑Up with HTA

A quick approach for richer Windows messages is relying for example on BurntToast, but that library requires installation, is Windows‑only, and disappears after a short while, just like msg. Instead, we will create a simple HTML Application (HTA) and launch it through mshta.exe. The file remains visible until the user closes it, provided a policy does not block the executable.

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>System Isolated by CrowdStrike Falcon</title>

    <!-- HTA settings -->
    <hta:application
        id="CSIsolationNotice"
        applicationname="CrowdStrikeIsolationNotice"
        border="thin"
        caption="yes"
        sysmenu="yes"
        scroll="no"
        singleinstance="yes"
        windowstate="maximize" />

    <style>
        html, body {
            height: 100%; /* make flex centering work */
            margin: 0;
        }
        body {
            font-family: "Segoe UI", Arial, sans-serif;
            background-color: #2d2d30;
            color: #ffffff;
            display: -ms-flexbox; /* IE10/11 */
            display: flex; /* modern */
            -ms-flex-pack: center; /* IE */
            justify-content: center; /* modern */
            -ms-flex-align: center; /* IE */
            align-items: center; /* modern */
            text-align: center;
        }
        #wrapper {
            max-width: 100%; /* keeps text from stretching too wide */
            padding: 1.5em;
        }
        h1 {
            font-size: 2.6em;
            text-transform: uppercase;
            margin: 0 0 .5em 0;
            color: #ff4141;
        }
        p {
            font-size: 1.15em;
            margin: .4em 0;
        }
        button {
            margin-top: 1.8em;
            font-size: 1em;
            padding: .6em 2.4em;
            border-radius: 9px;
            border: none;
            cursor: pointer;
        }
    </style>
</head>

<body>
    <div id="wrapper">
        <h1>System Isolated</h1>
        <p>Your endpoint has been isolated by <b>CrowdStrike Falcon</b> for security reasons.</p>
        <p>Network access is temporarily disabled. Stop work. Keep it on and online.</p>
        <p>You will be notified when the isolation has been lifted.</p>
    </div>
</body>
</html>

Save the file and test locally with mshta.exe ; a full‑screen dialogue should appear.

CrowdStrike HTA popup results
CrowdStrike HTA popup results

Staging the HTA for Delivery

The HTA can reside on a read‑only share that remains reachable even during containment, or it can be uploaded to Host Setup and Management > Response Scripts and Files so that the workflow deploys it on demand. The second option keeps everything inside Falcon.

The tricky part is creating an interactive process that displays the pop-up for all users. Although it would be possible to create an interactive scheduled task for every interactive user session on the system or create a new service, both are far beyond the scope of this post as, for example, creating a new service that runs interactively in another user session requires some token creation and juggling that we won’t cover in this post. Alternatively, we could run interactive applications with COM, which is beyond this post’s scope too.

The biggest problem is that while it is possible to run MSHTA and deploy the HTA file with a PowerShell script that we can deploy with Falcon, the CrowdStrike agent is running as SYSTEM, and we need to make sure that every potentially logged-in user sees the isolation pop-up. Therefore, our first idea was to run PsExec for each session:

# Config
$psexec = 'C:\Program Files\CrowdStrike\Rtr\PutRun\PsExec.exe'                                
$hta    = 'C:\Program Files\CrowdStrike\Rtr\PutRun\ cs_containment_notification.hta'

# Ensure PsExec EULA is silently accepted (idempotent)
& $psexec -accepteula | Out-Null

# Collect interactive session IDs (exclude session 0)
$sessionIds = (quser) | ForEach-Object {
    if ($_ -match '^\s*>\s*(\S+)\s+(\S+)\s+(\d+)\s')        { $matches[3] }   # current session gets a leading >
    elseif ($_ -match '^\s*(\S+)\s+(\S+)\s+(\d+)\s')        { $matches[3] }
} | Where-Object { $_ -ne 0 } | Sort-Object -Unique

# Inject the HTA into every session
foreach ($sid in $sessionIds) {
    Start-Process -FilePath $psexec `
        -ArgumentList "-i $sid mshta.exe `"$hta`"" `
        -NoNewWindow -Wait
}

Deploying ServiceUI.exe in Place of PsExec

Because the ADMIN$ share is disabled in our environment, PsExec cannot run; it relies on that share to copy psexesvc.exe and create the transient PSEXESVC service. We therefore switch to the Microsoft Deployment Toolkit utility ServiceUI.exe. A typical command looks like "C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64\ServiceUI.exe" -process:explorer.exe "C:\Windows\System32\mshta.exe" "\"C:\Program Files\CrowdStrike\Rtr\PutRun\cs_containment_notification.hta\"".

In this case, ServiceUI.exe enumerates every session that owns explorer.exe and launches mshta.exe within each one, passing the HTA notification file as an argument so that the isolation banner appears for every logged‑in user. To make this work inside Falcon, upload ServiceUI.exe under Host Setup and Management > Response Scripts and Files > Put Files and extend the workflow so that it writes both ServiceUI.exe and the HTA to the target system.

CrowdStrike SOAR workflow extended with the HTA file
CrowdStrike SOAR workflow extended with the HTA file

Handling Repeated Executions Without File‑Name Collisions

A second obstacle appears once the workflow triggers more than once. Falcon refuses to overwrite files already in C:\Program Files\CrowdStrike\Rtr\PutRun, so a subsequent run fails when it tries to write the HTA or ServiceUI.exe again. The fix is placing the payloads in a unique sub‑folder created dynamically for each execution.

A short PowerShell helper script solves the problem. It receives the workflow‑execution ID as an input parameter, verifies that the base PutRun directory exists, and then creates a child folder whose name is the execution ID, which guarantees uniqueness across runs.

$basePath = 'C:\Program Files\CrowdStrike\Rtr\PutRun'

# Ensure the CrowdStrike put and run directory exists
if (-not (Test-Path $basePath)) {
    New-Item -Path $basePath -ItemType Directory -Force | Out-Null
}

# Pull workflow execution ID
try {
    $workflowID = $args[0] | ConvertFrom-Json | Select-Object -ExpandProperty workflow_id
}
catch {
    exit 1
}

if (-not $workflowID) {
    exit 1
}

# Create alert specific directory
$workflowPath = Join-Path $basePath $workflowID
if (-not (Test-Path $workflowPath)) {
    New-Item -Path $workflowPath -ItemType Directory -Force | Out-Null
}

The script expects its parameter in JSON form. A minimal input schema passes the value from Fusion SOAR:

{
  "$schema": "https://json-schema.org/draft-07/schema",
  "properties": {
    "workflow_id": {
      "type": "string"
    }
  },
  "required": [
    "workflow_id"
  ],
  "type": "object",
  "description": "This generated schema may need tweaking. In particular format fields are attempts at matching workflow field types but may not be correct."
}

Include this setup step immediately before the Put File actions. The HTA and ServiceUI.exe are then written to C:\Program Files\CrowdStrike\Rtr\PutRun\<workflow_exec_id> instead of the parent folder, so the workflow can run any number of times without encountering write errors.

CrowdStrike dynamic workflow variable
CrowdStrike dynamic workflow variable

After the helper script has created C:\Program Files\CrowdStrike\Rtr\PutRun\, edit each Put File action so that its Target directory field is the variable ${Workflow.Execution.ID} appended to the base path. Both the HTA and ServiceUI.exe are now copied into the fresh sub‑folder, guaranteeing that no overwrite error arises when the workflow fires again.

Launching mshta.exe in Every Active Session

Passing complex strings through the Put and Run action proved brittle because ServiceUI.exe needs quoted arguments, so a short PowerShell wrapper becomes the last workflow step. The wrapper receives the execution ID via the same JSON schema used earlier, builds the absolute paths for ServiceUI.exe, mshta.exe, and the HTA, verifies that each file exists, enumerates all interactive sessions, and finally starts ServiceUI.exe in every one.

# Pull workflow execution ID
try {
    $workflowID = $args[0] | ConvertFrom-Json | Select-Object -ExpandProperty workflow_id
}
catch {
    exit 1
}

$basePath = 'C:\Program Files\CrowdStrike\Rtr\PutRun'
$alertPath = Join-Path -Path $basePath -ChildPath $workflowID

$serviceUI = 'ServiceUI.exe'
$htaFile = 'cs_containment_notification.hta'

# Build paths safely
$serviceUIPath  = Join-Path -Path $alertPath -ChildPath $serviceUI
$htaFilePath = Join-Path -Path $alertPath -ChildPath $htaFile
$mshtaPath = "$env:WINDIR\System32\mshta.exe"

# Sanity checks
foreach ($item in $serviceUIPath, $mshtaPath, $htaFilePath) {
    if (-not (Test-Path $item)) {
        Write-Error "Required file not found: $item"
        exit 1
    }
}

# Get all active sessions
$sessionIds = @(quser 2>$null) |
              Select-String '\bActive\b' |
              ForEach-Object { ($_ -replace '\s{2,}', ',').Trim(',') } |
              ConvertFrom-Csv -Header 'User','Session','ID','State','Idle','Logon' |
              Select-Object -ExpandProperty ID -Unique

# Launch
foreach ($sid in $sessionIds) {
    # Build ServiceUI's argument list
    $svcArgs = @(
        "-session:$($sid)"
        "`"$mshtaPath`""
        "`\`"$htaFilePath`\`""
    ) -join ' '

    Start-Process -FilePath $serviceUIPath -ArgumentList $svcArgs -WindowStyle Hidden
}

Once this script runs, every user logged on and sees the full‑screen HTA that explains the containment action will stay open until closed manually. Our final workflow:

Final CrowdStrike SOAR workflow
Final CrowdStrike SOAR workflow

Final Thoughts

Should a hardening rule prevent the execution of mshta.exe, convert the notification to plain HTML, and start a browser that remains functional during isolation, for example, "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" "file:///C:/Program%20Files/CrowdStrike/Rtr/PutRun//cs_containment_notification.html".

The overall workflow now isolates the host, copies the notification assets into a collision‑free directory, and launches an unmistakable, persistent banner for every active session, without relying on the ADMIN$ share, PsExec, or mshta.exe.

Table of Contents

Our primary goal is to deliver reliable and secure IT solutions to our clients and contribute resources to creating a more secure world. Copyright © 2021 – 2025 Hexastrike Cybersecurity UG (haftungsbeschraenkt)