Functions/Mutations/Start-RSCThreatHunt.ps1
################################################ # Function - Start-RSCThreatHunt - Start a threat hunt for the specified objects & IOCs ################################################ Function Start-RSCThreatHunt { <# .SYNOPSIS A Rubrik Security Cloud (RSC) Reporting Module Function that starts a threat hunt using the variables configured. .DESCRIPTION This function validates all the ObjectIDs specified are valid, then starts a threat hunt using the IOCs and variables configured. .LINK GraphQL schema reference: https://rubrikinc.github.io/rubrik-api-documentation/schema/reference .PARAMETER ObjectIDs A single ObjectID or list in the format "ObjectID1,ObjectID2,ObjectID3" .PARAMETER ThreatHuntName The name of your threat hunt, ensure it is unique, check using Get-RSCThreatHunts. .PARAMETER IOCs The indicatorsOfCompromise to hunt for. For an example use Get-RSCSampleYARARules .PARAMETER IOCType Enter or select IOC_YARA or IOC_HASH depending on whether you specified a yara rule in IOCs or hashes. .PARAMETER UseDemoIOCs Use this if you just want to search for the Rubrik backup agent as a demonstration and don't want to enter any IOCs. .PARAMETER FileExclude Optional, leave as null for the default which is none. .PARAMETER FileException Optional, leave as null for the default which is none. .PARAMETER IOCMaxSizeBytes Optional, leave as null for the default which is 10000000 bytes (10MB). .PARAMETER IOCMinSizeBytes Optional, leave as null for the default which is 256000 bytes (256KB). .PARAMETER MaxSnapshotsPerObject Optional, leave as null for the default which is 1, just the last backup. .PARAMETER MaxMatchesPerSnapshot Optional, leave as null for the default which is 100. .PARAMETER FileInclude Optional, leave as null for the default which is all files. .OUTPUTS Returns an array of all the available information on the GraphQL endpoint in a uniform and usable format. .EXAMPLE Start-RSCThreatHunt -ObjectIDs "ObjectID1,ObjectID2,ObjectID3" -ThreatHuntName "Test From SDK" -IOCType IOC_YARA -UseDemoIOCs This example starts a threat hunt for the objects IDs specified with the built-in YARA sample. .NOTES Author: Joshua Stenhouse Date: 05/11/2023 #> ################################################ # Paramater Config ################################################ Param ( [Parameter(Mandatory=$true)] $ObjectIDs, [Parameter(Mandatory=$true)] [String]$ThreatHuntName, [Parameter(Mandatory=$false)] [String]$IOCs, [Parameter(Mandatory=$false)] [ValidateSet("IOC_YARA","IOC_HASH")] $IOCType, [switch]$UseDemoIOCs, $FileExclude, $FileException, $IOCMaxSizeBytes, $IOCMinSizeBytes, $MaxSnapshotsPerObject, $MaxMatchesPerSnapshot, $FileInclude ) # Setting defaults if null IF($FileExclude -eq $null){$FileExclude = ""} IF($FileException -eq $null){$FileException = ""} IF($IOCMaxSizeBytes -eq $null){$IOCMaxSizeBytes = 10000000} IF($IOCMinSizeBytes -eq $null){$IOCMinSizeBytes = 256000} IF($MaxSnapshotsPerObject -eq $null){$MaxSnapshotsPerObject = 1} IF($MaxMatchesPerSnapshot -eq $null){$MaxMatchesPerSnapshot = 100} IF($FileInclude -eq $null){$FileInclude = "**"} # Checking function hasn't been passed multiple To ObjectIs in a string, formatting if so IF($ObjectIDs -match ","){$ObjectIDs = $ObjectIDs.Split(",")} # Getting RSC Protected Object list $RSCObjects = Get-RSCProtectedObjects # Verifying all object IDs are valid $ObjectIDCheck = [System.Collections.ArrayList]@() ForEach($ObjectID in $ObjectIDs) { # Checking if exists in list $ObjectIDList = $RSCObjects | Where-Object {$_.ObjectID -eq $ObjectID} # Validating IF($ObjectIDList -eq $null){$ObjectIDInList = $FALSE}ELSE{$ObjectIDInList = $TRUE} # Getting Rubrik cluster ID $RubrikClusterID = $ObjectIDList.RubrikClusterID # Adding To Array $Object = New-Object PSObject $Object | Add-Member -MemberType NoteProperty -Name "ObjectID" -Value $ObjectID $Object | Add-Member -MemberType NoteProperty -Name "ObjectIDInList" -Value $ObjectIDInList $Object | Add-Member -MemberType NoteProperty -Name "RubrikClusterID" -Value $RubrikClusterID $ObjectIDCheck.Add($Object) | Out-Null } # Exiting if not objects found $ObjectIDCheckCount = $ObjectIDCheck | Where-Object {$_.ObjectIDInList -eq $FALSE} | Measure-Object | Select-Object -ExpandProperty Count IF($ObjectIDCheckCount -gt 0) { Write-Error "ERROR: One or more ObjectIDs not found in Get-RSCProtectedObjects, check and try again.." Start-Sleep 2 Break } # Exiting if all objects not on same Rubrik cluster $RubrikClusterID = $ObjectIDCheck | Select-Object -ExpandProperty RubrikClusterID -Unique $RubrikClusterIDCheckCount = $RubrikClusterID | Measure-Object | Select-Object -ExpandProperty Count IF($RubrikClusterIDCheckCount -gt 0) { Write-Error "ERROR: One or more ObjectIDs not on the same RubrikClusterID, ensure all ObjectIDs specified are on the same Rubrik cluster and try again.." Start-Sleep 2 Break } # Creating demo has IF($UseDemoIOCs) {$IOCType = "IOC_YARA" $IOCs = "import `"hash`" rule StringMatch : Example Rubrik { meta: description = `"string and regular expression matching`" strings: `$wide_and_ascii_string = `"Borland`" wide ascii `$re = /state: (on|off)/ condition: `$re and `$wide_and_ascii_string and filesize > 200KB } rule MatchByHash : Example Rubrik { meta: description = `"hash matching`" condition: filesize == 12345 and hash.md5(0, filesize) == `"e30299799c4ece3b53f4a7b8897a35b6`" }" } # Validating an IOC is specified by this point otherwise exiting IF($IOCs -eq $null) { Write-Error "ERROR: No IOCs specified, check your variables and try again.." Start-Sleep 2 Break } ################################################ # Importing Module & Running Required Functions ################################################ Import-Module RSCReporting # Checking connectivity, exiting function with error if not Test-RSCConnection ################################################ # Requesting Generic On Demand Snapshot ################################################ # Building GraphQL query $RSCGraphQL = @{"operationName" = "StartThreatHuntMutation"; "variables" = @{ "input" = @{ "clusterUuid" = "$RubrikClusterID" "indicatorsOfCompromise" = @{ "iocKind" = "$IOCType" "iocValue" = "$IOCs" } "objectFids" = $ObjectIDs "maxMatchesPerSnapshot" = $MaxMatchesPerSnapshot "shouldTrustFilesystemTimeInfo" = $true "name" = "$ThreatHuntName" "fileScanCriteria" = @{ "fileSizeLimits" = @{ "maximumSizeInBytes" = $IOCMaxSizeBytes } "pathFilter"= @{ "includes" = "**" "excludes"= "$FileExclude" "exceptions" = "$FileException " } } "snapshotScanLimit" = @{ "maxSnapshotsPerObject" = $MaxSnapshotsPerObject } } }; "query" = "mutation StartThreatHuntMutation(`$input: StartThreatHuntInput!) { startThreatHunt(input: `$input) { huntId isSyncSuccessful } }" } # Querying API $RSCResponse = Invoke-RestMethod -Method POST -Uri $RSCGraphqlURL -Body $($RSCGraphQL | ConvertTo-JSON -Depth 20) -Headers $RSCSessionHeader # Checking for errors IF($RSCResponse.errors.message){$RSCResponse.errors.message} # Getting result $ThreatHuntStarted = $RSCResponse.data.startThreatHunt.isSyncSuccessful $ThreatHuntID = $RSCResponse.data.startThreatHunt.huntId ################################################ # Returing array ################################################ $Object = New-Object PSObject $Object | Add-Member -MemberType NoteProperty -Name "RSCInstance" -Value $RSCInstance $Object | Add-Member -MemberType NoteProperty -Name "RubrikClusterID" -Value $RubrikClusterID $Object | Add-Member -MemberType NoteProperty -Name "ObjectIDs" -Value $ObjectIDs $Object | Add-Member -MemberType NoteProperty -Name "ThreatHuntStarted" -Value $ThreatHuntStarted $Object | Add-Member -MemberType NoteProperty -Name "ThreatHuntID" -Value $ThreatHuntID $Object | Add-Member -MemberType NoteProperty -Name "Errors" -Value $RSCResponse.errors.message # Returning array Return $Object # End of function } |