Crowdstrike's Real Time Response module allows you to establish a session and execute scripts on remote hosts. This makes it a great tools for deploying Canarytokens to endpoints, using tools the security team likely already manage.
Crowdstrike enables automation through it's API and various SDK's, in this article we'll explore it's Python implementation FalconPy.
To get started, we'll first need to prepare our Crowdstrike portal for programmatic and automated access. This means we'll need some credentials to authenticate with the API.
Step 1: Crowdstrike API Key
To get a set of API keys, head over to your CrowdStrike dashboard, then browse to Support and resources, then API clients and keys.
Alternatively, you can head directly there by following the appropriate link for your region.
Select the Create API client button, then enter a descriptive name for your API Key.
Next we'll need to assign the keys appropriate scope to work with the API.
The breakdown of permissions needed are as follows:
Scope: | Permission: | Reason: |
Hosts | Read | Query endpoint ID from host. |
Host Groups | Read | Query endpoint ID's from Host group. |
Real time response | Read & Write | Establish RTR sessions. |
Real time response (admin) | Write | Upload, list and execute cloud scripts. |
When ready, select the Create button, to generate your API keys. You'll want to note down both the Client ID and Secret for use later in the script.
Step 2: Picking out an appropriate script
We offer a number of helpful scripts over at our public Github repository here in bash(Linux / MacOS), powershell (Windows) and Python.(Universal).
Crowdstrike supports Bash(Linux), Zsh(MacOS) and Powershell(Windows) for it's script uploads and execution.
A good starting point for CanaryTokens is our "Multi-Dropper" scripts available in Powershell and Bash, however any script you'd like to deploy will do.
In this example, we'll keep things simple and start with a script that will create a timestamped file on the C:\ drive.
Go ahead and save this powershell script as test_token.ps1.
# Define the file name with a timestamp
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$filePath = "C:\token_test_$timestamp.txt"
# Create the file
New-Item -ItemType File -Path $filePath -Force | Out-Null
# Confirm creation
Write-Host "File created: $filePath"
With a script in hand, lets get it deployed!
Step 3: Deploying the script using the RTR wrapper.
The Crowdstrike wrapper script can be found in the python section of our repository here.
Grab a copy of it, and we can start building it's launch command.
The wrapper's 2 main functions is being able to 1) upload or select a cloud script, and 2) deploy to a target host, group or list of hosts.
Running the script with it's help switch will show us the various parameters it supports and it's permutations.
=== 🦜 Thinkst Canary RTR API Wrapper ===
usage: crowdstrike_rtr_api_wrapper.py [-h] --client-id CLIENT_ID --client-secret CLIENT_SECRET [--script-path SCRIPT_PATH] [--script-name SCRIPT_NAME] [--group-name GROUP_NAME] [--hosts-file HOSTS_FILE] [--host HOST] [--queue-offline]
Execute a script via CrowdStrike RTR on multiple hosts. You can specify a single host (--host), a list of hosts (--hosts-file), or a group (--group-name).
options:
-h, --help show this help message and exit
--client-id CLIENT_ID
CrowdStrike API Client ID (required).
--client-secret CLIENT_SECRET
CrowdStrike API Client Secret (required).
--script-path SCRIPT_PATH
Path to the script file. Required if --script-name is not provided.
--script-name SCRIPT_NAME
Name of an existing script in CrowdStrike. Required if --script-path is not provided.
--group-name GROUP_NAME
CrowdStrike host group name. Optional. Limited to 5000 hosts.
--hosts-file HOSTS_FILE
Path to a text file containing a list of hostnames (one per line).
--host HOST Specify a single hostname to target. Overrides --hosts-file and --group-name.
--queue-offline If set, queues script execution for offline devices (execution persists for 7 days).
Example usage:
python script.py --client-id YOUR_ID --client-secret YOUR_SECRET --script-path script.ps1 --host my-hostname
python script.py --client-id YOUR_ID --client-secret YOUR_SECRET --script-path script.ps1 --hosts-file hosts.txt
python script.py --client-id YOUR_ID --client-secret YOUR_SECRET --script-name 'My Uploaded Script' --group-name 'My Group'
python script.py --client-id YOUR_ID --client-secret YOUR_SECRET --script-name 'My Uploaded Script' --host single-hostname
python script.py --client-id YOUR_ID --client-secret YOUR_SECRET --script-name 'My Uploaded Script' --host single-hostname --queue-offline
python script.py --client-id YOUR_ID --client-secret YOUR_SECRET --script-name 'My Uploaded Script' --group-name 'My Group' --queue-offline
For now, we're going to deploy our test_token.ps1 script to a single host
To do that, we'll want to specify our API keys, the script path, and the host we're targeting.
% python3 crowdstrike_rtr_api_wrapper.py --client-id 5f41d5b2839a426385b939752f824698 --client-secret REDACTED --script-path test_token.ps1 --host DESKTOP-JA8NNV1
=== 🦜 Thinkst Canary RTR API Wrapper ===
🦅 Initializing CrowdStrike Modules...
🔵 `queue_offline` is DISABLED: Commands will only run on currently online hosts.
📦 Preparing to upload script...
Please specify the target platform for this script. (windows, mac, linux): windows
📂 Script uploaded successfully.
🔍 Fetching list of available Scripts...
📜 Available Scripts:
1. Detect and downgrade xz
2. test_token.ps1
Enter the number of the script to execute: 2
🎯 Selected Script: test_token.ps1
🔍 Looking up device ID for single host: DESKTOP-JA8NNV1
✅ Found Device ID for DESKTOP-JA8NNV1: 98325d4d2fd948fb867eb588bc79c0af
✅ Found 1 target devices.
🔄 Initializing RTR sessions for 1 hosts...
⚠️ No offline hosts were successfully queued. Check your CrowdStrike RTR permissions.
🚀 Executing 'test_token.ps1' on target devices...
🚀 Running 'test_token.ps1' on all online hosts...
✅ Successfully executed 'test_token.ps1' on all hosts in batch
🎉 Execution complete.
Checking our target host, we see the script executed correctly, and we're all set.
You're Done! ;)