Using Powershell to extract the Detections information from the Datalake

Disclaimer: This information is provided as-is for the benefit of the Community. Please contact Sophos Professional Services if you require assistance with your specific environment.


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)
    }

}




Updated disclaimer
[edited by: Qoosh at 9:41 PM (GMT -7) on 31 Mar 2023]