-
Notifications
You must be signed in to change notification settings - Fork 69
Basic Scripts
The examples provided below are for example purposes only and are offered 'as is' with no support.
- Add a list of hostnames to a host group
- Hide hosts based on last_seen time
- Find duplicate hosts and hide them
- Network contain a device by Hostname
- Network contain a list of Hostnames from a CSV file
- Output selected Host info and replace ids with names
- Get host information from multiple Falcon instances
- Create a host group and add a list of devices by hostname
- Verify that a list of Host Groups exist within Child CIDs
- Modify all Sensor Visibility Exclusions to include an additional Host Group
- Assign a list of Host Group names to a specific Policy Id within a list of Child CIDs
- Output a list of assigned Host Groups for designated Policy ids within child CIDs
- Add a list of combined_id exceptions to a Device Control policy
- Create CSVs containing Device Control policy details and exceptions
- Run a command against a group of devices
- Upload and execute a local script
- Upload and execute a local script as a secondary process
- Download the installer package assigned to a Sensor Update policy
- Download the installer package assigned to your default Sensor Update policy
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true,
Position = 1)]
[string] $Username,
[Parameter(Mandatory = $true,
Position = 2)]
[string] $Filename
)
# Get User identifier
$Uuid = Get-FalconUser -Usernames $Username -ErrorAction SilentlyContinue
if (-not $Uuid) {
throw "Invalid username: '$Username'"
}
# Get Detection identifiers involving $Filename
$Ids = Get-FalconDetection -Filter "behaviors.filename:'$Filename'" -All
if (-not $Ids) {
throw "No detections found matching '$Filename'"
}
# Notify user that detections are being assigned
Write-Host "Assigning $($Ids.count) detections involving '$Filename' to '$Username'..."
# Modify detections
Edit-FalconDetection -Ids $Ids -Status in_progress -AssignedToUuid $Uuid
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true)]
[string] $Filename
)
do {
# Gather up to 1,000 detections (maximum for an edit request) involving $Filename
$Ids = Get-FalconDetection -Filter "behaviors.filename:'$Filename'" -Limit 1000
if ($Ids) {
# Export list of ids being hidden
$Ids | Out-File -FilePath $pwd\hidden_detections.txt -Append -Force
# Hide group of detections
Edit-FalconDetection -Ids $Ids -ShowInUi $false
# Pause to give the API time to clear them out before the next request
Start-Sleep -Seconds 5
}
} while (
# Exit once no more detections are available
$Ids
)
NOTE: This script expects a text file that contains case-sensitive hostnames (one per line) for the -Path
parameter.
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true,
Position = 1)]
[ValidatePattern('\.txt$')]
[string] $Path,
[Parameter(Mandatory = $true,
Position = 2)]
[ValidatePattern('^\w{32}$')]
[string] $GroupId
)
$Hostnames = (Get-Content $Path).Normalize()
$Hosts = for ($i = 0; $i -lt $Hostnames.count; $i += 20) {
# Retrieve the device_id for hostnames in groups of 20
$Filter = ($Hostnames[$i..($i + 19)] | ForEach-Object {
if ($_ -ne '') {
"hostname:['$_']"
}
}) -join ','
Get-FalconHost -Filter $Filter
}
# Add hosts to group
Invoke-FalconHostGroupAction -Name add-hosts -Id $GroupId -HostIds $Hosts
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true)]
[int] $Days
)
$Param = @{
Filter = "last_seen:<'Last $Days days'"
All = $true
}
$Hosts = Get-FalconHost @Param
if ($Hosts) {
$Param = @{
Name = 'hide_host'
Ids = $Hosts
}
Invoke-FalconHostAction @Param
} else {
"No hosts found using filter: $Filter"
}
WARNING: Find-FalconDuplicate
only determines whether or not a device is a "duplicate" by hostname in this example. There may be a legitimate reason that two devices have the same hostname in your environment. It is your responsibility to determine whether or not the hosts reported by Find-FalconDuplicate
are correct. This script does not provide you with an opportunity to review those hosts before they are hidden, but it does output a list after the hiding is complete. If devices are hidden incorrectly they will continue to communicate with Falcon and can be restored from the trash using their aid
value and Invoke-FalconHostAction
.
#Requires -Version 5.1 -Modules @{ModuleName="PSFalcon";ModuleVersion='2.1'}
param(
[switch] $Confirm
)
try {
# Use Find-FalconDuplicate to find duplicate hosts
$Duplicates = Find-FalconDuplicate
if ($Duplicates.device_id -and $Confirm) {
# Output duplicate list to CSV
$Duplicates | Export-Csv -Path .\duplicates.csv -NoTypeInformation
# Use Invoke-FalconHostAction to hide hosts
Invoke-FalconHostAction -Name hide_host -Ids $Duplicates.device_id
} elseif ($Duplicates) {
# Output list of duplicates
Write-Output "Found $($Duplicates.count) potential duplicate hosts"
Write-Output $Duplicates
} else {
Write-Output "No duplicates found."
}
} catch {
Write-Error $_
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true)]
[string] $Hostname
)
# Get identifier for target system and choose the most recently seen (in case of duplicates)
$HostId = Get-FalconHost -Filter "hostname:'$Hostname'" -Sort last_seen.desc -Limit 1
if ($HostId) {
# Contain host
Invoke-FalconHostAction -Name contain -Ids $HostId
} else {
throw "No identifier found for '$Hostname'"
}
NOTE: This example requires a CSV with a column labeled Hostname
. It will create a new CSV with that includes the hostname, device_id and containment request status.
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('\.csv$')]
[string] $Path
)
$OutputFile = "Containment_$(Get-Date -Format FileDateTime).csv"
[array] $Hostnames = (Import-Csv $Path).Hostname
$Hosts = for ($i = 0; $i -lt $Hostnames.count; $i += 20) {
# Retrieve the device_id for hostnames in groups of 20
$Filter = ($Hostnames[$i..($i + 19)] | ForEach-Object {
if ($_ -ne '') {
"hostname:['$_']"
}
}) -join ','
$Output = Get-FalconHost -Filter $Filter -Detailed | Select-Object hostname, device_id
$Output | ForEach-Object {
# Add property for each host to update after containment request
$_.PSObject.Properties.Add((New-Object PSNoteProperty('Contain_Requested', $false)))
}
$Output
}
# Contain hosts and add status
Invoke-FalconHostAction -Name contain -Ids $Hosts.device_id | ForEach-Object {
$Id = $_.id
($Hosts | Where-Object { $_.device_id -eq $Id }).Contain_Requested = $true
}
$Hosts | Export-Csv -Path $OutputFile -NoTypeInformation
if (Test-Path $OutputFile) {
Get-ChildItem $OutputFile
}
Designed to replace all 'ids' with the related 'name', under each Host result. The fields you'd like to include from each host result can be added to the $Fields
variable.
#Requires -Version 5.1 -Modules @{ModuleName="PSFalcon";ModuleVersion='2.1.2'}
[CmdletBinding()]
param()
begin {
# Fields to include with the export to CSV (host group and policy data is automatically added)
$Fields = @('device_id', 'hostname', 'last_seen', 'first_seen', 'local_ip', 'external_ip', 'agent_version')
}
process {
# Retrieve all host information and filter to selected fields
$Fields += 'device_policies', 'groups'
$HostInfo = Get-FalconHost -Detailed -All | Select-Object $Fields
if ($HostInfo) {
# Create hashtable to store object detail for hosts
$Related = @{
DeviceControlPolicy = @{}
FirewallPolicy = @{}
IoaGroup = @{}
PreventionPolicy = @{}
ResponsePolicy = @{}
SensorUpdatePolicy = @{}
HostGroup = @{}
}
foreach ($ItemType in $Related.Keys) {
# Match policy type to the label used with hosts
$HostLabel = switch ($ItemType) {
'DeviceControlPolicy' { 'device_control' }
'HostGroup' { 'groups' }
'IoaGroup' { 'rule_groups' }
'ResponsePolicy' { 'remote_response' }
'SensorUpdatePolicy' { 'sensor_update' }
default { ($_ -replace 'Policy', $null).ToLower() }
}
$Ids = if ($ItemType -eq 'IoaGroup') {
# Collect IOA rule group identifiers
($HostInfo.device_policies.prevention.rule_groups | Group-Object).Name
} elseif ($ItemType -match 'Policy$') {
# Collect policy identifiers
($HostInfo.device_policies.$HostLabel.policy_id | Group-Object).Name
} else {
# Collect host group identifiers
($HostInfo.groups | Group-Object).Name
}
# Collect names and identifiers for each item in hashtable
$Content = & "Get-Falcon$($ItemType)" -Ids $Ids | Select-Object id, name
if ($Content) {
$Content | ForEach-Object {
$Related.$ItemType["$($_.id)"] = "$($_.name)"
}
} else {
Write-Error "Unable to collect '$ItemType' information. Check permissions."
}
$HostInfo | ForEach-Object {
# Define new property names to add to output
$Name = if ($ItemType -eq 'HostGroup') {
"host_$($HostLabel)"
} elseif ($ItemType -eq 'IoaGroup') {
"ioa_$($HostLabel)"
} else {
"$($HostLabel)_policy"
}
$Value = if ($ItemType -eq 'HostGroup') {
# Replace host group identifiers with names and remove 'groups'
($_.groups | ForEach-Object { $Related.$ItemType.$_ }) -join ','
[void] $_.PSObject.Properties.Remove('groups')
} elseif ($ItemType -eq 'IoaGroup') {
# Replace IOA rule group identifiers with names
($_.device_policies.prevention.rule_groups | ForEach-Object {
$Related.$ItemType.$_ }) -join ','
} else {
# Replace policy identifiers with names and add as '<type>_policy'
$Related.$ItemType.($_.device_policies.$HostLabel.policy_id)
}
$_.PSObject.Properties.Add((New-Object PSNoteProperty($Name, $Value)))
}
}
$HostInfo | Where-Object { $_.device_policies } | ForEach-Object {
# Remove redundant 'device_policies' property
[void] $_.PSObject.Properties.Remove('device_policies')
}
$HostInfo
} else {
Write-Error "Unable to collect Host information. Check permissions."
}
}
NOTE: This example requires that you input values for <client_id>
, <client_secret>
, and each <member_cid>
. To avoid hard-coding credentials you could pass them as parameters instead.
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
# ClientId, ClientSecret and MemberCids
$ClientId = '<client_id>'
$ClientSecret = '<client_secret>'
$CIDs = @('<member_cid>', '<member_cid>')
# Enumerate $CIDs
$CIDs | ForEach-Object {
$Param = @{
ClientId = $ClientId
ClientSecret = $ClientSecret
MemberCid = ($_).ToLower()
}
# Authenticate with CID
Request-FalconToken @Param
try {
# Gather and export Host data
Get-FalconHost -Detailed -All | Export-FalconReport ".\Hosts_for_MemberCid_$($_).csv"
} catch {
# Break 'foreach' loop if host retrieval/export fails
throw $_
} finally {
# Remove authentication token and credentials for next CID
Revoke-FalconToken
}
}
#Requires -Version 5.1 -Modules @{ModuleName="PSFalcon";ModuleVersion='2.1'}
param(
[Parameter(Mandatory = $true, Position = 1)]
[ValidatePattern('\.txt$')]
[ValidateScript({
if (Test-Path -Path $_ -PathType Leaf) {
$true
} else {
throw "Cannot find path '$_' because it does not exist or is a directory."
}
})]
[string] $Path,
[Parameter(Mandatory = $true, Position = 2)]
[string] $Name,
[Parameter(Position = 3)]
[string] $Description
)
process {
try {
# Import hostnames and create host group
$Hostnames = (Get-Content -Path $PSBoundParameters.Path).Normalize()
$Param = @{
GroupType = 'static'
Name = $PSBoundParameters.Name
}
if ($PSBoundParameters.Description) {
$Param['Description'] = $PSBoundParameters.Description
}
$Group = New-FalconHostGroup @Param
[array] $HostIds = for ($i = 0; $i -lt $Hostnames.count; $i += 20) {
# Retrieve the device_id for hostnames in groups of 20
$Filter = ($Hostnames[$i..($i + 19)] | ForEach-Object {
if ($_ -ne '') {
"hostname:['$_']"
}
}) -join ','
,(Get-FalconHost -Filter $Filter)
}
# Add hosts to group
Invoke-FalconHostGroupAction -Name add-hosts -Id $Group.id -HostIds $HostIds
} catch {
throw $_
}
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{32}$')]
[string] $ClientId,
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{40}$')]
[string] $ClientSecret,
[Parameter()]
[ValidateSet('eu-1', 'us-gov-1', 'us-1', 'us-2')]
[string] $Cloud,
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{32}$')]
[array] $MemberCIDs,
[Parameter(Mandatory = $true)]
[array] $GroupNames
)
begin {
# Log file name and output location
$OutputFile = "VerifyGroup_$(Get-Date -Format FileDateTime).csv"
$OutputPath = "$(Join-Path -Path ([Environment]::CurrentDirectory) -ChildPath $OutputFile)"
}
process {
foreach ($CID in $MemberCIDs) {
$Param = @{
ClientId = $ClientId
ClientSecret = $ClientSecret
MemberCid = ($CID).ToLower()
}
if ($Cloud) {
$Param.Add('Cloud', $Cloud)
}
# Authenticate with Member CID
Request-FalconToken @Param
try {
# Get group information
$Groups = for ($i = 0; $i -lt $GroupNames.count; $i += 20) {
[array] $NameFilter = ($GroupNames[$i..($i + 19)]).foreach{
"name:'$(($_).ToLower())'"
}
Get-FalconHostGroup -Filter ($NameFilter -join ',') -Detailed | Select-Object id, name
}
# Create output object
$Output = [PSCustomObject] @{
CID = $CID
}
foreach ($GroupName in $GroupNames) {
# Add each group name and id
$IdValue = if ($Groups.name -contains $GroupName) {
($Groups | Where-Object { $_.name -eq $GroupName }).id
} else {
$null
}
$Output.PSObject.Properties.Add((New-Object PSNoteProperty($GroupName, $IdValue)))
}
# Output to CSV
$Output | Export-Csv -Path $OutputPath -NoTypeInformation -Append
Write-Host "Output Host Groups for CID: $CID"
} catch {
# Output error and end script
$_
break
} finally {
# Remove authentication token and credentials for next CID
Revoke-FalconToken
# Sleep for 5 seconds to avoid rate limiting on token request
Start-Sleep -Seconds 5
}
}
}
end {
if (Test-Path -Path $OutputPath) {
Get-ChildItem -Path $OutputPath
}
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true,
Position = 1)]
[ValidatePattern('^\w{32}$')]
[string] $GroupId
)
$SVEs = Get-FalconSVExclusion -Detailed -All
foreach ($SVE in $SVEs) {
Edit-FalconSVExclusion -Id $SVE.id -GroupIds @($SVE.groups.id, $GroupId)
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{32}$')]
[string] $ClientId,
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{40}$')]
[string] $ClientSecret,
[Parameter()]
[ValidateSet('eu-1', 'us-gov-1', 'us-1', 'us-2')]
[string] $Cloud,
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{32}$')]
[array] $MemberCIDs,
[Parameter(Mandatory = $true)]
[array] $GroupNames,
[Parameter(Mandatory = $true)]
[ValidateSet('DeviceControl', 'Firewall', 'Prevention', 'Response', 'SensorUpdate')]
[string] $PolicyType,
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{32}$')]
[string] $PolicyId
)
begin {
# Log file name and output location
$LogName = "AssignGroup_$(Get-Date -Format FileDateTime).log"
$LogLocation = "$(Join-Path -Path ([Environment]::CurrentDirectory) -ChildPath $LogName)"
function Write-LogEntry ([string] $Source, [string] $Message) {
# Write output and add to log file
"[$(Get-Date -Format 'yyyy-MM-dd hh:mm:ss') $Source] $Message" | Tee-Object -FilePath $LogLocation -Append
}
}
process {
foreach ($CID in $MemberCIDs) {
$Param = @{
ClientId = $ClientId
ClientSecret = $ClientSecret
MemberCid = ($CID).ToLower()
}
if ($Cloud) {
$Param.Add('Cloud', $Cloud)
}
# Authenticate with Member CID
Request-FalconToken @Param
try {
($GroupNames).foreach{
# Get Host Group Id
$GroupId = Get-FalconHostGroup -Filter "name:'$(($_).ToLower())'"
if ($GroupId) {
# Assign Host Group to policy
$InvokeCommand = "Invoke-Falcon$($PolicyType)PolicyAction"
$Param = @{
Name = 'add-host-group'
Id = $PolicyId
GroupId = $GroupId
}
$Assigned = & $InvokeCommand @Param
if ($Assigned) {
$Param = @{
Source = $InvokeCommand
Message = "Assigned group $($GroupId) to $($PolicyType) policy" +
" $($Assigned.id) in CID $($CID)"
}
Write-LogEntry @Param
} else {
$Param = @{
Source = $InvokeCommand
Message = "Failed to assign group $($GroupId) to $($PolicyId) in CID $($CID)"
}
Write-LogEntry @Param
}
} else {
$Param = @{
Source = 'Get-FalconHostGroup'
Message = "No results for group name '$_' in CID $($CID)"
}
Write-LogEntry @Param
}
}
} catch {
# Output error and end script
$_
break
} finally {
# Remove authentication token and credentials for next CID
Revoke-FalconToken
# Sleep for 5 seconds to avoid rate limiting on token request
Start-Sleep -Seconds 5
}
}
}
end {
if (Test-Path -Path $LogLocation) {
# Output log file and path
Get-ChildItem -Path $LogLocation
}
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{32}$')]
[string] $ClientId,
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{40}$')]
[string] $ClientSecret,
[Parameter()]
[ValidateSet('eu-1', 'us-gov-1', 'us-1', 'us-2')]
[string] $Cloud,
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{32}$')]
[array] $MemberCIDs,
[Parameter(Mandatory = $true)]
[ValidateSet('DeviceControl', 'Firewall', 'Prevention', 'Response', 'SensorUpdate')]
[string] $PolicyType,
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{32}$')]
[array] $PolicyIds
)
begin {
$Filename = "$($PolicyType)PolicyAssignments_$(Get-Date -Format FileDate).csv"
$OutputPath = "$(Join-Path -Path ([Environment]::CurrentDirectory) -ChildPath $Filename)"
}
process {
foreach ($CID in $MemberCIDs) {
$Param = @{
ClientId = $ClientId
ClientSecret = $ClientSecret
MemberCid = ($CID).ToLower()
}
if ($Cloud) {
$Param.Add('Cloud', $Cloud)
}
# Authenticate with Member CID
Request-FalconToken @Param
try {
# Get policy information
$InvokeCommand = "Get-Falcon$($PolicyType)Policy"
& $InvokeCommand -Ids $PolicyIds | Select-Object id, groups | ForEach-Object {
[PSCustomObject] @{
# Output with CID, policy id and assigned groups
CID = $CID
PolicyId = "$($_.id)"
Groups = $_.groups.id -join ', '
} | Export-Csv -Path $OutputPath -NoTypeInformation -Append
}
Write-Host "Output assigned Host Groups for policies in CID: $CID"
} catch {
# Output error and end script
$_
break
} finally {
# Remove authentication token and credentials for next CID
Revoke-FalconToken
# Sleep for 5 seconds to avoid rate limiting on token request
Start-Sleep -Seconds 5
}
}
}
end {
if (Test-Path -Path $OutputPath) {
Get-ChildItem -Path $OutputPath
}
}
NOTE: This script will create 'FULL_ACCESS' exceptions for the 'MASS_STORAGE' class within an existing policy. You can modify the hashtable created in $Exceptions
to add key/value pairs like vendor_name
or product_name
.
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 1)]
[ValidatePattern('^\w{32}$')]
[string] $PolicyId,
[Parameter(Mandatory = $true, Position = 2)]
[array] $CombinedIds
)
begin {
# Maximum number of exceptions to add per request
$Max = 50
}
process {
for ($i = 0; $i -lt ($CombinedIds | Measure-Object).Count; $i += $Max) {
# Create exceptions in groups of $Max
$IdGroup = $CombinedIds[$i..($i + ($Max - 1))]
[array] $Exceptions = $IdGroup | ForEach-Object {
@{
action = 'FULL_ACCESS'
combined_id = $_
}
}
$Settings = @{
classes = @(
@{
id = 'MASS_STORAGE'
exceptions = $Exceptions
}
)
}
Edit-FalconDeviceControlPolicy -Id $PolicyId -Settings $Settings | ForEach-Object {
# Validate presence of 'combined_id' in policy
$PolicyExceptions = ($_.settings.classes | Where-Object { $_.id -eq 'MASS_STORAGE' }).exceptions
($IdGroup).foreach{
if ($PolicyExceptions.combined_id -contains $_) {
Write-Output "OK: $_"
}
}
}
}
}
This script will create a series of CSV files containing information about a given Device Control policy (settings, members, groups, exceptions, etc.).
#Requires -Version 5.1
using module @{
ModuleName = 'PSFalcon'
ModuleVersion = '2.1'
}
[CmdletBinding(DefaultParameterSetName = 'Id')]
param(
[Parameter(ParameterSetName = 'Id', Mandatory = $true, Position = 1)]
[Parameter(ParameterSetName = 'Name', Mandatory = $true, Position = 1)]
[ValidatePattern('^\w{32}$')]
[string] $ClientId,
[Parameter(ParameterSetName = 'Id', Mandatory = $true, Position = 2)]
[Parameter(ParameterSetName = 'Name', Mandatory = $true, Position = 2)]
[ValidatePattern('^\w{40}$')]
[string] $ClientSecret,
[Parameter(ParameterSetName = 'Id', Position = 3)]
[Parameter(ParameterSetName = 'Name', Position = 3)]
[ValidateSet('eu-1', 'us-gov-1', 'us-1', 'us-2')]
[string] $Cloud,
[Parameter(ParameterSetName = 'Id', Mandatory = $true, Position = 4)]
[ValidatePattern('^\w{32}$')]
[string] $Id,
[Parameter(ParameterSetName = 'Name', Mandatory = $true, Position = 5)]
[string] $Name,
[Parameter(ParameterSetName = 'Id', Position = 6)]
[Parameter(ParameterSetName = 'Name', Position = 6)]
[ValidateScript({
if ((Test-Path $_) -eq $false) {
throw "Cannot find path '$_' because it does not exist."
} elseif ((Test-Path $_ -PathType Container) -eq $false) {
throw "'Path' must specify a folder."
} else {
$true
}
})]
[string] $Path
)
begin {
function Write-Output ([object] $Content, [string] $Type) {
if ($Content) {
$Param = @{
Path = Join-Path -Path $OutputFolder -ChildPath "$(Get-Date -Format FileDate)_$(
$Id)_$($Type).csv"
NoTypeInformation = $true
Append = $true
Force = $true
}
$Content | Export-Csv @Param
}
}
$OutputFolder = if (!$Path) {
(Get-Location).Path
} else {
$Path
}
$Param = @{
ClientId = $ClientId
ClientSecret = $ClientSecret
}
if ($Cloud) {
$Param['Cloud'] = $Cloud
}
Request-FalconToken @Param
$VerbosePreference = 'Continue'
}
process {
$PolicyId = if ((Test-FalconToken).Token -eq $true) {
if ($Name) {
try {
Get-FalconDeviceControlPolicy -Filter "name:'$($Name.ToLower())'" -Detailed
} catch {
throw "No Device Control policy found matching '$($Name.ToLower())'."
}
} else {
$Id
}
}
if ($PolicyId) {
foreach ($Item in (Get-FalconDeviceControlPolicy -Ids $PolicyId)) {
$Item.settings.PSObject.Members.Where({ $_.MemberType -eq 'NoteProperty' }).foreach{
if ($_.Name -eq 'classes') {
Write-Output ($_.Value | Select-Object id, action) 'classes'
foreach ($Exception in ($_.Value).Where({ $_.exceptions }).exceptions) {
Write-Output $Exception 'exceptions'
}
} else {
$Item.PSObject.Properties.Add((New-Object PSNoteProperty($_.Name, $_.Value)))
}
}
foreach ($Property in @('groups', 'settings')) {
if ($Item.$Property -and $Property -eq 'groups') {
Write-Output ($Item.$Property | Select-Object id, name) $Property
}
$Item.PSObject.Properties.Remove($Property)
}
Write-Output $Item 'settings'
Write-Output (Get-FalconDeviceControlPolicyMember -Id $PolicyId -Detailed -All |
Select-Object device_id, hostname) 'members'
}
}
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true,
Position = 1)]
[string] $GroupName,
[Parameter(Mandatory = $true,
Position = 2)]
[string] $Command,
[Parameter(Position = 3)]
[string] $Arguments,
[boolean] $QueueOffline
)
# Find group identifier using 'name' filter
$GroupId = Get-FalconHostGroup -Filter "name:'$($GroupName.ToLower())'"
if ($GroupId) {
# Get host identifiers for members of $GroupId
$Members = Get-FalconHostGroupMember -Id $GroupId -All
} else {
throw "No host group found matching '$GroupName'"
}
if ($Members) {
# Set filename for CSV export
$ExportName = "$pwd\rtr_$($Command -replace ' ','_')_$GroupId.csv"
# Set base parameters for Invoke-FalconRTR
$Param = @{
Command = $Command
HostIds = $Members
}
switch ($PSBoundParameters.Keys) {
# Append parameters from user input that match Invoke-FalconRTR
{ $_ -ne 'GroupName' } {
$Param[$_] = $PSBoundParameters.$_
}
}
# Issue command and export results to CSV
Invoke-FalconRTR @Param | Export-Csv -Path $ExportName
if (Test-Path $ExportName) {
# Display CSV file
Get-ChildItem $ExportName
}
} else {
throw "No members found in host group '$GroupName' [$GroupId]"
}
NOTE: This will get the content of a script from the local administrator computer, encode it (to minimize potential errors due to quotation marks) and run it as a "Raw" script using Invoke-FalconRTR
.
[CmdletBinding()]
param(
[Parameter(
Mandatory = $true,
Position = 1)]
[ValidateScript({ Test-Path $_ })]
[string] $Path,
[Parameter(
Mandatory = $true,
Position = 2)]
[ValidatePattern('^\w{32}$')]
[array] $HostIds,
[Parameter(Position = 3)]
[int] $Timeout
)
begin {
$EncodedScript = [Convert]::ToBase64String(
[System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw)))
}
process {
$Param = @{
Command = 'runscript'
Arguments = '-Raw=```powershell.exe -Enc ' + $EncodedScript + '```'
HostIds = $HostIds
}
if ($HostIds.count -gt 1 -and $Timeout) {
$Param['Timeout'] = $Timeout
}
Invoke-FalconRTR @Param
}
NOTE: Similar to the other example this will run a script as a secondary PowerShell process on the target device, which helps when scripts are expected to exceed the Real-time Response timeout limit. The downside is that you will not be able to return results from the script unless you write them to a local file on the target host that you access later.
[CmdletBinding()]
param(
[Parameter(
Mandatory = $true,
Position = 1)]
[ValidateScript({ Test-Path $_ })]
[string] $Path,
[Parameter(
Mandatory = $true,
Position = 2)]
[ValidatePattern('^\w{32}$')]
[array] $HostIds,
[Parameter(Position = 3)]
[int] $Timeout
)
begin {
$EncodedScript = [Convert]::ToBase64String(
[System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw)))
}
process {
$Param = @{
Command = 'runscript'
Arguments = '-Raw=```Start-Process -FilePath powershell.exe -ArgumentList "-Enc ' + $EncodedScript + '"```'
HostIds = $HostIds
}
if ($HostIds.count -gt 1 -and $Timeout) {
$Param['Timeout'] = $Timeout
}
Invoke-FalconRTR @Param
}
This is a simple one-line script that will download the most recent scheduled report results into your current directory.
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.1.6' }
(Get-FalconScheduledReport -Detailed -All).last_execution | ForEach-Object {
Receive-FalconScheduledReport -Id $_.id -Path "$($_.result_metadata.report_file_name)"
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true)]
[ValidatePattern('^\w{32}$')]
[string] $PolicyId
)
try {
# Retrieve Sensor Update policy detail
$Policy = Get-FalconSensorUpdatePolicy -Ids $PolicyId
if ($Policy.platform_name -and $Policy.settings) {
# Use build and sensor_version to create regex pattern
[regex] $Pattern = "^($([regex]::Escape(
($Policy.settings.sensor_version -replace '\.\d+$',$null)))\.\d{1,}|\d\.\d{1,}\.$(
$Policy.settings.build.Split('|')[0]))$"
$Match = try {
# Select matching installer from list for 'platform_name' using regex pattern
Get-FalconInstaller -Filter "platform:'$($Policy.platform_name.ToLower())'" -Detailed |
Where-Object { $_.version -match $Pattern -and $_.description -match 'Falcon Sensor' }
} catch {
throw 'Unable to find installer through version match'
}
if ($Match.sha256 -and $Match.name) {
$Installer = Join-Path -Path (Get-Location).Path -ChildPath $Match.name
if ((Test-Path $Installer) -and ((Get-FileHash -Algorithm SHA256 -Path $Installer) -eq $Match.sha256)) {
# Abort if matching file already exists
throw "File exists with matching hash [$($Match.sha256)]"
} elseif (Test-Path $Installer) {
# Remove other versions
Remove-Item -Path $Installer -Force
}
# Download the installer package
Receive-FalconInstaller -Id $Match.sha256 -Path $Installer
} else {
throw "Properties 'sha256' or 'name' missing from installer result"
}
}
} catch {
throw $_
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 1)]
[ValidateScript({
if (Test-Path -Path $_ -PathType Container) {
$true
} else {
throw "Cannot find path '$_' because it does not exist or is not a directory."
}
})]
[string] $Path
)
begin {
# Ensure absolute path for output directory
$OutputDirectory = if (![IO.Path]::IsPathRooted($PSBoundParameters.Path)) {
$FullPath = Join-Path -Path (Get-Location).Path -ChildPath $PSBoundParameters.Path
$FullPath = Join-Path -Path $FullPath -ChildPath '.'
[IO.Path]::GetFullPath($FullPath)
} else {
$PSBoundParameters.Path
}
}
process {
try {
# Retrieve Sensor Update policy detail
$Policy = Get-FalconSensorUpdatePolicy -Filter "platform_name:'Windows'+name:'platform_default'" -Detailed
if ($Policy.platform_name -and $Policy.settings) {
# Use build and sensor_version to create regex pattern
[regex] $Pattern = "^($([regex]::Escape(
($Policy.settings.sensor_version -replace '\.\d+$',$null)))\.\d{1,}|\d\.\d{1,}\.$(
$Policy.settings.build.Split('|')[0]))$"
$Match = try {
# Select matching installer from list for 'platform_name' using regex pattern
Get-FalconInstaller -Filter "platform:'$($Policy.platform_name.ToLower())'" -Detailed |
Where-Object { $_.version -match $Pattern -and $_.description -match 'Falcon Sensor' }
} catch {
throw 'Unable to find installer through version match'
}
if ($Match.sha256 -and $Match.name) {
$Installer = Join-Path -Path $OutputDirectory -ChildPath $Match.name
if ((Test-Path $Installer) -and ((Get-FileHash -Algorithm SHA256 -Path $Installer) -eq $Match.sha256)) {
# Abort if matching file already exists
throw "File exists with matching hash [$($Match.sha256)]"
} elseif (Test-Path $Installer) {
# Remove other versions
Remove-Item -Path $Installer -Force
}
# Download the installer package
$Receive = Receive-FalconInstaller -Id $Match.sha256 -Path $Installer
if (Test-Path $Receive.FullName) {
$Match | ForEach-Object {
# Output installer information with 'file_path' of local file
$_.PSObject.Properties.Add((New-Object PSNoteProperty('file_path', $Receive.FullName)))
$_
}
} else {
throw "Installer download failed [$($Match.sha256)]"
}
} else {
throw "Properties 'sha256' or 'name' missing from installer result"
}
} else {
throw "Unable to retrieve default policy for Windows"
}
} catch {
throw $_
}
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
$UnixDate = [DateTimeOffset]::Now.AddDays(-7).ToUnixTimeSeconds()
$Param = @{
Filter = "(type:'ip_address',type:'domain')+last_updated:>$UnixDate"
Detailed = $true
All = $true
}
Get-FalconIndicator @Param | Select-Object indicator, type, malicious_confidence, labels | ForEach-Object {
[PSCustomObject] @{
value = $_.indicator
type = $_.type
confidence = $_.malicious_confidence
comment = "$(($_.Labels.name | Where-Object { $_ -notmatch 'MaliciousConfidence/*' }) -join ', ')"
} | Export-Csv -Path .\indicators.csv -NoTypeInformation -Append
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Mandatory = $true, Position = 1)]
[ValidateSet('https://api.crowdstrike.com', 'https://api.us-2.crowdstrike.com',
'https://api.laggar.gcw.crowdstrike.com', 'https://api.eu-1.crowdstrike.com')]
[string] $BaseAddress,
[Parameter(Mandatory = $true, Position = 2)]
[ValidatePattern('^\w{32}$')]
[string] $ClientId,
[Parameter(Mandatory = $true, Position = 3)]
[ValidatePattern('^\w{40}$')]
[string] $ClientSecret,
[Parameter(Position = 4)]
[ValidatePattern('^\w{32}$')]
[string] $MemberCid,
[Parameter(Mandatory = $true, Position = 5)]
[ValidatePattern('\.csv$')]
[ValidateScript({ Test-Path $_ })]
[string] $Path
)
$Param = @{
Hostname = $BaseAddress
ClientId = $ClientId
ClientSecret = $ClientSecret
}
if ($MemberCid) {
$Param['MemberCid'] = $MemberCid
}
Request-FalconToken @Param
if ((Test-FalconToken).Token -eq $true) {
$CSV = Import-Csv $Path
@($CSV).foreach{
@($_.PSObject.Properties.Name).foreach{
if ($_ -notmatch '^(Email|Firstname|Lastname|Roles)$') {
# Error if invalid columns exist
throw "Unexpected column. Ensure 'Email', 'Firstname', 'Lastname' and 'Roles' are present. ['$_']"
}
}
if ($_.Roles) {
# Convert Roles into an [array]
$_.Roles = ($_.Roles -Split ',').Trim()
}
}
if ($CSV.Roles -and $CSV.Roles -match '\s') {
# Replace 'Display Names' (from console output) with role IDs
$Roles = Get-FalconRole -Detailed
if ($Roles) {
@($CSV).foreach{
$_.Roles = @($_.Roles).foreach{
$_ -replace $_, ($Roles | Where-Object display_name -eq $_).id
}
}
}
}
$CSV | ForEach-Object {
# Create user
$User = New-FalconUser -Username $_.Email -Firstname $_.Firstname -Lastname $_.Lastname
if ($User.uuid -and $_.Roles) {
# Assign roles
Add-FalconRole -UserId $User.uuid -Ids $_.Roles
} elseif ($User.uuid) {
# Assign 'falcon_console_guest' if roles are not present
Add-FalconRole -UserId $User.uuid -Ids falcon_console_guest
}
}
}
#Requires -Version 5.1
using module @{ ModuleName = 'PSFalcon'; ModuleVersion = '2.0' }
param(
[Parameter(Position = 1)]
[int] $Days = 7,
[Parameter(Position = 2)]
[array] $Fields = @('last_seen', 'mac_address', 'serial_number', 'external_ip')
)
if ($Fields -notcontains 'device_id') {
# Force 'device_id' as a field to be used for matching results
$Fields += ,'device_id'
}
# Set filename for CSV export
$ExportName = "$pwd\Vulnerabilities_$((Get-Date).AddDays(-$Days).ToString('yyyyMMdd'))_to_$(Get-Date -Format FileDate).csv"
# Gather vulnerabilities within date range (default: last 7 days) and export to CSV
$Param = @{
Filter = "created_timestamp:>'last $Days days'"
Detailed = $true
All = $true
Verbose = $true
}
Get-FalconVulnerability @Param | Export-FalconReport -Path $ExportName
if (Test-Path $ExportName) {
# Import newly created vulnerability report
$CSV = Import-Csv -Path $ExportName
# Gather host ids
$HostIds = ($CSV | Group-Object aid).Name
# Get detailed information about hosts to append to CSV
$Param = @{
Ids = $HostIds
Verbose = $true
}
$HostInfo = Get-FalconHost @Param | Select-Object $Fields
foreach ($Item in $HostInfo) {
foreach ($Result in ($CSV | Where-Object { $_.aid -eq $Item.device_id })) {
foreach ($Property in ($Item.PSObject.Properties | Where-Object { $_.Name -ne 'device_id' })) {
# Add $Fields from Get-FalconHost, excluding 'device_id' (already present as 'aid')
$Result.PSObject.Properties.Add((New-Object PSNoteProperty($Property.Name, $Property.Value)))
}
}
}
# Re-export CSV with added fields
$CSV | Export-Csv -Path $ExportName -NoTypeInformation -Force
} else {
throw "No vulnerabilities created within the last $Days days"
}
The examples provided above are for example purposes only and are offered 'as is' with no support.
- Using PSFalcon
-
Commands and Permissions
- Configuration Import/Export
- Container Security
- Detection and Prevention Policies
- Discover for Cloud and Containers
- Discover
- Event Streams
- Falcon Complete Dashboards
- Falcon Complete Message Center
- Falcon Data Replicator
- Falcon Intelligence
- Falcon Intelligence Recon
- Falcon OverWatch Dashboards
- Falcon Sandbox
- FileVantage
- Firewall Management
- Flight Control
- Horizon
- Host and Host Group Management
- Identity Protection
- Image Assessment
- Incident and Detection Monitoring
- Installation Tokens
- Kubernetes Protection
- MalQuery
- Mobile Host Enrollment
- On-Demand Scanning
- Quarantine
- Real-time Response
- Real-time Response Policy
- Scheduled Reports and Searches
- Sensor Download
- Sensor Update Policy
- Spotlight
- Tailored Intelligence
- Third-party ingestion
- USB Device Control Policy
- Users and Roles
- Zero Trust Assessment
- Examples
-
CrowdStrike SDKs
- PSFalcon - PowerShell
- FalconPy - Python 3
- goFalcon - Go
- Rusty Falcon - Rust