PowerShell script connecting to the Central API to collect all relevant detections (risk level > 6) from the xdr_ti_data table. The output is displayed in table format on the console, and we also create a CSV export of the information.
---------------------
By using or accessing the Software below, you agree to be bound by the terms of the Sophos End User License Agreement.
CentralAPI_XDR_Detections_Notification.ps1
<# Description: Check whether relevant detections (Risk Level > 6) are within Sophos Central Results are displayed in the console and exported to a CSV files Note: If you want to access all risk levels you should add the column detection_item to the console / CSV output #> cls Write-Host("=================================================================") Write-Host("Sophos Central XDR Detection Notification") Write-Host("=================================================================`n") Write-Host("This scripts automatically checks the Sophos Central Data Lake for relevant detections (Risk Level > 6) within your environment.`nIf detections are present, the scripts creates an output to the console and to a CSV file.`nUse this script as a starting point to add other functionality, e.g. sending notifications via E-mail.`n") # Check if Central API Credentials have been stored, if not then prompt the user to add them if ((Test-Path $env:userprofile\sophos_central_admin.json) -eq $false){ # Prompt for Credentials Write-Host("=================================================================") Write-Host("Sophos Central API Authentication:") Write-Host("=================================================================") $clientId = Read-Host "Please Enter your Client ID" $clientSecret = Read-Host "Please Enter your Client Secret" -AsSecureString | ConvertFrom-SecureString # Out to JSON Config File ConvertTo-Json $ClientID, $ClientSecret | Out-File $env:userprofile\sophos_central_admin.json -Force } # Read Credentials from JSON Config File $credentials = Get-Content $env:userprofile\sophos_central_admin.json | ConvertFrom-Json $clientId = $credentials[0] $clientSecret = $credentials[1] | ConvertTo-SecureString # Create PSCredential Object for Credentials $SecureCredentials = New-Object System.Management.Automation.PSCredential -ArgumentList $clientId , $clientSecret #Write-Host("[API] Authenticate to Sophos Central...") # SOPHOS OAuth URL $TokenURI = "https://id.sophos.com/api/v2/oauth2/token" # TokenRequestBody for oAuth2 $TokenRequestBody = @{ "grant_type" = "client_credentials"; "client_id" = $SecureCredentials.GetNetworkCredential().Username; "client_secret" = $SecureCredentials.GetNetworkCredential().Password; "scope" = "token"; } $TokenRequestHeaders = @{ "content-type" = "application/x-www-form-urlencoded"; } # Set TLS Version [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # Post Request to SOPHOS OAuth2 token: $APIAuthResult = (Invoke-RestMethod -Method Post -Uri $TokenURI -Body $TokenRequestBody -Headers $TokenRequestHeaders -ErrorAction SilentlyContinue -ErrorVariable ScriptError) # If there's an error requesting the token, say so, display the error, and break: if ($ScriptError) { Write-Output "FAILED - Unable to retreive SOPHOS API Authentication Token - $($ScriptError)" Break } # Set the Token for use later on: $script:Token = $APIAuthResult.access_token #Write-Host("[API] Get tenant details...") # SOPHOS Whoami URI: $WhoamiURI = "https://api.central.sophos.com/whoami/v1" # SOPHOS Whoami Headers: $WhoamiRequestHeaders = @{ "Content-Type" = "application/json"; "Authorization" = "Bearer $script:Token"; } # Get Request SOPHOS Whoami Details: $APIWhoamiResult = (Invoke-RestMethod -Method Get -Uri $WhoamiURI -Headers $WhoamiRequestHeaders -ErrorAction SilentlyContinue -ErrorVariable ScriptError) # Set TenantID and ApiHost for use later on: $script:ApiTenantId = $APIWhoamiResult.id $script:ApiHost = $APIWhoamiResult.apiHosts.dataRegion # SOPHOS XDR API Headers: $XDRAPIHeaders = @{ "Authorization" = "Bearer $script:Token"; "X-Tenant-ID" = "$script:ApiTenantId"; "Content-Type" = "application/json"; } if ($apihost -ne $null){ ################################################################################################################################### # Check if detections are available in Sophos Central with Risk Level larger than 6 ################################################################################################################################### Write-Host("`n=================================================================") Write-Host("[Data Lake] Check for detections with Risk Level > 6:") Write-Host("=================================================================") $vulnerableDevices = @() $XDR_Response = (Invoke-RestMethod -Method POST -Uri $script:ApiHost"/xdr-query/v1/queries/runs" -Headers $XDRAPIHeaders -Body '{ "adHocQuery": { "template": "SELECT ioc_detection_weight RISK, meta_hostname, ioc_detection_attack, ioc_detection_description, sophos_pid, detection_item, name, cmdline, calendar_time, username FROM xdr_ti_data WHERE ioc_detection_weight > 6 ORDER BY ioc_detection_weight DESC" }}') While ($XDR_Response.status -ne "finished") { start-sleep -s 1 $XDR_Response = (Invoke-RestMethod -Method Get -Uri $script:ApiHost"/xdr-query/v1/queries/runs/$($XDR_Response.id)" -Headers $XDRAPIHeaders -ErrorAction SilentlyContinue -ErrorVariable ScriptError) } if ($XDR_Response.result -eq "succeeded") { $XDR_Response = (Invoke-RestMethod -Method Get -Uri $script:ApiHost"/xdr-query/v1/queries/runs/$($XDR_Response.id)/results?maxSize=1000" -Headers $XDRAPIHeaders -ErrorAction SilentlyContinue -ErrorVariable ScriptError) # Display results in the console $XDR_Response.items | Format-Table -Property RISK, meta_hostname, ioc_detection_attack, sophos_pid, name, calendar_time, username, cmdline # Store detections in a CSV file $XDR_Response.items | Export-Csv -Path $env:userprofile\detections.csv } else { Write-Output ("Request failed!") Write-Output ($XDR_Response) } }
Thanks a lot for the base of this script. I'll post soon a cleanup script for sophos central which makes use of line 1 till 95. Regards