Cybereason
Endpoint detection and response to manage and query malops, connections and processes.
Endpoint · Cybereason
Details
| ID | Cybereason |
|---|---|
| Provider | LevelBlue |
| Category | Endpoint |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
Endpoint detection and response to manage and query malops, connections and processes.
This integration was integrated and tested with version 21.2 of Cybereason
Configure Cybereason in Cortex
| Parameter | Required |
|---|---|
| Server URL (e.g. https://192.168.0.1) | True |
| Credentials | False |
| Password | False |
| Trust any certificate (not secure) | False |
| Use system proxy settings | False |
| Fetch incidents | False |
| Incident type | False |
| First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days, 3 months, 1 year) | False |
| Fetch by “MALOP UPDATE TIME” (Fetching by Malop creation time is no longer supported) | False |
Cybereason MalOp to XSOAR Incident Map
This involves the mapping of response fields to XSOAR incidents, enhancing the ability to manage and track security incidents effectively.
Overview
- Incident Mapping: The integration maps specific response fields to corresponding incident fields within XSOAR, ensuring that all relevant information is captured accurately.
- Custom Fields: In addition to standard incident fields, custom fields have been introduced to accommodate unique data requirements specific to our workflow. These fields provide flexibility and enhance the granularity of the incident information.
malopcreationtimemalopupdatetimemaloprootcauseelementnamemaloprootcauseelementtypemalopseveritymalopdetectiontypemalopedrmalopurlmalopgroup
These custom fields provide flexibility and enhance the granularity of the incident information.
Usage
- Configure Custom Fields: Ensure that all custom fields are properly set up in XSOAR before running the fetch function.
- Enable Fetch Incidents: Functionality responsible to fetch Malops.
- Monitor Incidents: Once the MalOps are converted, they will appear as incidents in XSOAR, allowing for effective incident management.
Cybereason MalOp to XSOAR Incident Map
This involves the mapping of response fields to XSOAR incidents, enhancing the ability to manage and track security incidents effectively.
Overview
- Incident Mapping: The integration maps specific response fields to corresponding incident fields within XSOAR, ensuring that all relevant information is captured accurately.
- Custom Fields: In addition to standard incident fields, custom fields have been introduced to accommodate unique data requirements specific to our workflow. These fields provide flexibility and enhance the granularity of the incident information.
malopcreationtimemalopupdatetimemaloprootcauseelementnamemaloprootcauseelementtypemalopseveritymalopdetectiontypemalopedrmalopurlmalopgroup
These custom fields provide flexibility and enhance the granularity of the incident information.
Fetchin MalOps
The functionality for fetching MalOps is implemented through the fetch_incidents function. This function is responsible for retrieving MalOps and subsequently converting them into XSOAR incidents.
- Conversion Process: The conversion from MalOps to incidents is handled by the
malop_to_incidentfunction. This function processes MalOps one by one, ensuring each is correctly mapped to its corresponding incident structure.
Usage
- Configure Custom Fields: Ensure that all custom fields are properly set up in XSOAR before running the fetch function.
- Run Fetch Incidents: Execute the
fetch_incidentsfunction to initiate the retrieval and conversion process. - Monitor Incidents: Once the MalOps are converted, they will appear as incidents in XSOAR, allowing for effective incident management.
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
cybereason-query-processes
Searches for processes with various filters.
Base Command
cybereason-query-processes
Input
| Argument Name | Description | Required |
|---|---|---|
| machine | The hostname of the machine. | Optional |
| onlySuspicious | Show only suspicious processes. Possible values are: true, false. Default is false. | Optional |
| limit | Maximum number of results to retrieve. Default is 10000. | Optional |
| processName | Process name to filter by. | Optional |
| saveToContext | If true, save the result to the context. Possible values are: true, false. Default is false. | Optional |
| hasIncomingConnection | Filter only processes with incoming connections. Possible values are: true, false. Default is false. | Optional |
| hasOutgoingConnection | Filter only processes with outgoing connections. Possible values are: true, false. Default is false. | Optional |
| hasExternalConnection | If process has external connection. Possible values are: true, false. | Optional |
| unsignedUnknownReputation | If process is not known to reputation services and its image file is unsigned. Possible values are: true, false. | Optional |
| fromTemporaryFolder | If process is running from temporary folder. Possible values are: true, false. | Optional |
| privilegesEscalation | If process was identified elevating its privileges to local system user. Possible values are: true, false. | Optional |
| maliciousPsExec | If the process was executed by PsExec service and is suspicious as being executed maliciously. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Process.Name | Unknown | The process name |
| Cybereason.Process.Malicious | Unknown | Malicious status of the process |
| Cybereason.Process.CreationTime | Unknown | The process creation time |
| Cybereason.Process.EndTime | Unknown | The process end time |
| Cybereason.Process.CommandLine | Unknown | The command line of the process |
| Cybereason.Process.SignedAndVerified | Unknown | Is the process signed and verified |
| Cybereason.Process.ProductType | Unknown | The product type |
| Cybereason.Process.Children | Unknown | Children of the process |
| Cybereason.Process.Parent | Unknown | The parent process |
| Cybereason.Process.OwnerMachine | Unknown | The machine’s hostname |
| Cybereason.Process.User | Unknown | The user who ran the process |
| Cybereason.Process.ImageFile | Unknown | Image file of the process |
| Cybereason.Process.SHA1 | Unknown | SHA1 of the process file |
| Cybereason.Process.MD5 | Unknown | MD5 of the process file |
| Cybereason.Process.CompanyName | Unknown | The company’s name |
| Cybereason.Process.ProductName | Unknown | The product’s name |
Command example
!cybereason-query-processes machine=machine-name hasOutgoingConnection=true hasIncomingConnection=true
Context Example
{
"Process": [
{
"Children": null,
"CommandLine": "C:\\WINDOWS\\system32\\svchost.exe -k LocalService -s W32Time",
"CompanyName": "Microsoft Corporation",
"CreationTime": "2022-05-06T04:15:33.939000",
"EndTime": "",
"ImageFile": "svchost.exe",
"MD5": "<md5>",
"Malicious": "indifferent",
"Name": "svchost.exe",
"OwnerMachine": "<machine-name>",
"Parent": "services.exe",
"ProductName": "Microsoft\u00ae Windows\u00ae Operating System",
"ProductType": "SVCHOST",
"SHA1": "<sha1>",
"SignedandVerified": "true",
"User": "machine-name\\local service"
}
]
}
Human Readable Output
Cybereason Processes
Name Malicious Creation Time End Time Command Line Signed and Verified Product Type Children Parent Owner Machine User Image File SHA1 MD5 Company Name Product Name svchost.exe indifferent 2022-05-06T04:15:33.939000 C:\WINDOWS\system32\svchost.exe -k LocalService -s W32Time true SVCHOST services.exe machine-name machine-name\local service svchost.exe wxyz1234 abc123 Microsoft Corporation Microsoft® Windows® Operating System
cybereason-is-probe-connected
Checks if the machine is currently connected to the Cybereason server
Base Command
cybereason-is-probe-connected
Input
| Argument Name | Description | Required |
|---|---|---|
| machine | The hostname of the machine to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Machine.isConnected | boolean | true if machine is connected, else false |
| Cybereason.Machine.Name | string | Machine name |
Command example
!cybereason-is-probe-connected machine=machine-name
Context Example
{
"Cybereason": {
"Machine": {
"Name": "<machine-name>",
"isConnected": true
}
}
}
Human Readable Output
true
cybereason-query-connections
Searches for connections.
Base Command
cybereason-query-connections
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | Filter connections which contain this IP (in or out). | Optional |
| machine | Filter connections on the given machine. | Optional |
| saveToContext | If true, save the result to the context. Possible values are: true, false. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Connection.Name | Unknown | The connection’s name |
| Cybereason.Connection.Direction | Unknown | OUTGOING/INCOMING |
| Cybereason.Connection.ServerAddress | Unknown | Address of the Cybereason machine |
| Cybereason.Connection.ServerPort | Unknown | Port of the Cybereason machine |
| Cybereason.Connection.PortType | Unknown | Type of the connection |
| Cybereason.Connection.ReceivedBytes | Unknown | Received bytes count |
| Cybereason.Connection.TransmittedBytes | Unknown | Transmitted bytes count |
| Cybereason.Connection.RemoteCountry | Unknown | The connection’s remote country |
| Cybereason.Connection.OwnerMachine | Unknown | The machine’s hostname |
| Cybereason.Connection.OwnerProcess | Unknown | The process which performed the connection |
| Cybereason.Connection.CreationTime | Unknown | Creation time of the connection |
| Cybereason.Connection.EndTime | Unknown | End time of the connection |
Command example
!cybereason-query-connections ip=<host>
Context Example
{
"Connection": [
{
"CreationTime": "2021-04-20T00:00:00.00000",
"Direction": "OUTGOING",
"EndTime": "2021-04-20T00:00:00.000000",
"Name": "<connection_ip_addresses>",
"OwnerMachine": "simplify-cyber",
"OwnerProcess": "nbtscan.exe",
"PortType": "SERVICE_WINDOWS",
"ReceivedBytes": "0",
"RemoteCountry": null,
"ServerAddress": "<server_address>",
"ServerPort": "137",
"TransmittedBytes": "50"
}
]
}
Human Readable Output
Cybereason Connections for: 192.168.1.103
Creation Time Direction End Time Name Owner Machine Owner Process Port Type Received Bytes Remote Country Server Address Server Port Transmitted Bytes 2021-04-20T00:00:00.000000 OUTGOING 2021-04-20T00:00:00.000000 connection_ip_addresses simplify-cyber test.exe SERVICE_WINDOWS 0 192.168.1.103 137 50
cybereason-isolate-machine
Isolates a machine that has been infected from the rest of the network
Base Command
cybereason-isolate-machine
Input
| Argument Name | Description | Required |
|---|---|---|
| machine | Machine name to be isolated. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Machine | string | Machine name |
| Cybereason.IsIsolated | boolean | Is the machine isolated |
Command example
!cybereason-isolate-machine machine=machine-name
Context Example
{
"Cybereason": {
"IsIsolated": true,
"Machine": "<machine-name>"
}
}
Human Readable Output
Machine was isolated successfully.
cybereason-unisolate-machine
Stops isolation of a machine
Base Command
cybereason-unisolate-machine
Input
| Argument Name | Description | Required |
|---|---|---|
| machine | Machine name to be un-isolated. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Machine | string | Machine name |
| Cybereason.IsIsolated | boolean | Is the machine isolated |
Command example
!cybereason-unisolate-machine machine=machine-name
Context Example
{
"Cybereason": {
"IsIsolated": false,
"Machine": "<machine-name>"
}
}
Human Readable Output
Machine was un-isolated successfully.
cybereason-query-malops
Returns a list of all Malops and details on the Malops.
Base Command
cybereason-query-malops
Input
| Argument Name | Description | Required |
|---|---|---|
| filters | Filter to filter response by, given in Cybereason API syntax. | Optional |
| totalResultLimit | The total number of results to return for your Server. Ensure you make the limit a reasonable number to maximize Server performance and not to overload the system. | Optional |
| perGroupLimit | The number of items to return per Malop group. | Optional |
| templateContext | The level of detail to provide in the response. Possible values include: SPECIFIC: References value contain only the count in the ElementValues class. The Suspicions map is calculated for each results, with the suspicion name and the first time the suspicion appeared. The Evidence map is not calculated for the results. CUSTOM: Reference values contain the specific Elements, up to the limit defined in the perFeatureLimit parameter. The Suspicions map is not calculated for the results. The Evidence map is not calculated for the results. DETAILS: Reference values contain the specific Elements, up to the limit defined in the perFeatureLimit parameter. The Suspicions map is calculated for each result, containing the suspicion name and the first time the suspicion appeared. The Evidence map is not calculated for the results. Possible values are: MALOP, SPECIFIC, CUSTOM, DETAILS, OVERVIEW. Default is MALOP. | Optional |
| withinLastDays | Return all the malops within the last days. | Optional |
| malopGuid | Malop GUIDs to filter by (Comma separated values supported, e.g. 11.123456789,11.9874563210). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Malops.GUID | string | The unique globally unique identifier (guid) for the Malop. |
| Cybereason.Malops.CreationTime | string | The time reported as when the malicious behavior began on the system. This is not the time that the Malop was first detected by Cybereason. |
| Cybereason.Malops.DecisionFeature | string | The reason that Cybereason has raised the Malop. |
| Cybereason.Malops.Link | string | Link to the Malop on Cybereason. |
| Cybereason.Malops.Suspects | string | Malop suspect type and name |
| Cybereason.Malops.LastUpdatedTime | string | Last updated time of malop |
| Cybereason.Malops.AffectedMachine | string | List of machines affected by this Malop |
| Cybereason.Malops.InvolvedHash | string | List of file hashes involved in this Malop |
| Cybereason.Malops.Status | string | Malop managemant status |
Command example
#### Context Example
```json
{
"Cybereason": {
"Malops": [
{
"AffectedMachine": [
"win10-cybereaso",
"marketing"
],
"CreationTime": "2021-07-12T00:00:00.000000",
"DecisionFailure": "blackListedFileHash",
"GUID": "<malop_id>",
"InvolvedHash": [
1
],
"LastUpdateTime": "2021-08-28T00:00:00.000000",
"Link": "<malop_link>",
"Status": "OPEN",
"Suspects": "Process: test.exe"
}
]
}
}
Human Readable Output
Cybereason Malops
GUID Link CreationTime Status LastUpdateTime DecisionFailure Suspects AffectedMachine InvolvedHash https://test.server.net:0000/#/malop/11.1234567890 2021-07-12T00:00:00.000000 OPEN 2021-08-28T00:00:00.000000 blackListedFileHash Process: test.exe affected_machine_name 1
cybereason-malop-processes
Returns a list of malops
Base Command
cybereason-malop-processes
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuids | Array of malop GUIDs separated by comma. (Malop GUID can be retrieved with the command cybereason-query-malops command). | Required |
| machineName | Machine names which were affected by malop. Comma separated values supported (e.g., machine1,machine2). | Optional |
| dateTime | Starting Date and Time to filter the Processes based on their creation date. The format for the input is (“YYYY/MM/DD HH:MM:SS”). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Process.Name | string | The process name |
| Cybereason.Process.Malicious | Unknown | Malicious status of the process |
| Cybereason.Process.CreationTime | date | The process creation time |
| Cybereason.Process.EndTime | date | The process end time |
| Cybereason.Process.CommandLine | string | The command line of the process |
| Cybereason.Process.SignedAndVerified | Unknown | Is the process signed and verified |
| Cybereason.Process.ProductType | Unknown | The product type |
| Cybereason.Process.Children | Unknown | Children of the process |
| Cybereason.Process.Parent | Unknown | The parent process |
| Cybereason.Process.OwnerMachine | Unknown | The machine’s hostname |
| Cybereason.Process.User | string | The user who ran the process |
| Cybereason.Process.ImageFile | Unknown | Image file of the process |
| Cybereason.Process.SHA1 | string | SHA1 of the process file |
| Cybereason.Process.MD5 | string | MD5 of the process file |
| Cybereason.Process.CompanyName | string | The company’s name |
| Cybereason.Process.ProductName | string | The product’s name |
Command example
!cybereason-malop-processes malopGuids=<malop_id>
Context Example
{
"Process": [
{
"Children": null,
"CommandLine": "\"C:\\Users\\user\\winrar-x64-602.pdf.exe\"",
"CompanyName": "Hello World",
"CreationTime": "2022-03-14T00:00:00.000000",
"EndTime": "2022-03-14T00:00:00.000000",
"ImageFile": "<image_file_name>",
"MD5": "<md5>",
"Malicious": "indifferent",
"Name": "<file_name>",
"OwnerMachine": "<machine-name>",
"Parent": "explorer.exe",
"ProductName": "WinRAR",
"ProductType": null,
"SHA1": "<sha1>",
"SignedandVerified": null,
"User": "machine-name\\user"
}
]
}
Human Readable Output
Cybereason Malop Processes
Name Malicious Creation Time End Time Command Line Parent Owner Machine User Image File SHA1 MD5 Company Name Product Name winrar-x64-602.exe indifferent 2022-03-14T00:00:00.000000 2022-03-14T00:00:00.000000 “C:\Users\user\winrar-x64-602.exe” explorer.exe machine-name machine-name\user winrar-x64-602.exe 1234sajklfshljjvhlsdfhilh23 md5_hash Hello World WinRAR
cybereason-add-comment
Add new comment to malop
Base Command
cybereason-add-comment
Input
| Argument Name | Description | Required |
|---|---|---|
| comment | Comment to add to the malop. | Required |
| malopGuid | Malop GUID to add comment to. (Malop GUID can be retrieved with the command cybereason-query-malops command). | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-add-comment comment=NewComment malopGuid=<malop_id>
Human Readable Output
Comment added successfully
cybereason-update-malop-status
Updates malop status
Base Command
cybereason-update-malop-status
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | Malop GUID to update its status. | Required |
| status | Status to update. Possible values are: To Review, Unread, Remediated, Not Relevant, Open. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Malops.GUID | string | Malop GUID |
| Cybereason.Malops.Status | string | Malop status: To Review,Unread,Remediated,Not Relevant |
Command example
!cybereason-update-malop-status malopGuid=<malop_id> status="To Review"
Context Example
{
"Cybereason": {
"Malops": {
"GUID": "<malop_id>",
"Status": "To Review"
}
}
}
Human Readable Output
Successfully updated malop to status To Review
cybereason-prevent-file
Prevent malop process file
Base Command
cybereason-prevent-file
Input
| Argument Name | Description | Required |
|---|---|---|
| md5 | Malop process file MD5 to prevent. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Process.MD5 | string | Process file MD5 |
| Cybereason.Process.Prevent | boolean | True if process file is prevented, else false |
Command example
!cybereason-prevent-file md5=MD5
Context Example
{
"Process": {
"MD5": "<md5>",
"Prevent": true
}
}
Human Readable Output
File was prevented successfully
cybereason-unprevent-file
Unprevent malop process file
Base Command
cybereason-unprevent-file
Input
| Argument Name | Description | Required |
|---|---|---|
| md5 | Malop process file MD5 to unprevent. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Process.MD5 | string | Process file MD5 |
| Cybereason.Process.Prevent | boolean | True if process file is prevented, else false |
Command example
!cybereason-unprevent-file md5=MD5
Context Example
{
"Process": {
"MD5": "MD5",
"Prevent": false
}
}
Human Readable Output
File was unprevented successfully
cybereason-query-file
Query files as part of investigation
Base Command
cybereason-query-file
Input
| Argument Name | Description | Required |
|---|---|---|
| file_hash | File hash (SHA-1 and MD5 supported). | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.File.Path | string | File path |
| Cybereason.File.SHA1 | string | File SHA-1 hash |
| Cybereason.File.Machine | string | Machine name on which file is located |
| Cybereason.File.SuspicionsCount | number | File suspicions count |
| Cybereason.File.Name | string | File name |
| Cybereason.File.CreationTime | date | File creation time |
| Cybereason.File.Suspicion | string | File suspicions object of suspicion as key and detected date as value |
| Cybereason.File.OSVersion | string | Machine OS version on which file is located |
| Cybereason.File.ModifiedTime | date | File modified date |
| Cybereason.File.Malicious | boolean | Is file malicious |
| Cybereason.File.Company | string | Company name |
| Cybereason.File.MD5 | string | File MD5 hash |
| Cybereason.File.IsConnected | boolean | Is machine connected to Cybereason |
| Cybereason.File.Signed | boolean | Is file signed |
| Cybereason.File.Evidence | string | File evidences |
Command example
!cybereason-query-file file_hash=<file_hash>
Context Example
{
"Cybereason": {
"File": {
"Company": "Hello World",
"CreationTime": "2022-02-28T00:00:00.000Z",
"Evidence": [],
"IsConnected": false,
"MD5": "<md5>",
"Machine": "<machine-name>",
"Malicious": false,
"ModifiedTime": "2022-05-09T00:00:00.000Z",
"Name": "<file_name>",
"OSVersion": null,
"Path": "c:\\users\\user\\winrar-x64-602.exe",
"SHA1": "<sha1>",
"Signed": true,
"Suspicion": {},
"SuspicionsCount": null
}
}
}
Human Readable Output
Cybereason file query results for the file hash: 77ab1e20c685e716b82c7c90b373316fc84cde23
Company CreationTime IsConnected MD5 Machine Malicious ModifiedTime Name Path SHA1 Signed Hello World 2022-02-28T00:00:00.000Z false MD5 machine-name false 2022-05-09T00:00:00.000Z winrar-x64-602.pdf.exe c:\users\test\winrar-x64-602.pdf.exe 1245sedecthebdfkjkgjljldl2348 true
cybereason-query-domain
Query domains as part of investigation
Base Command
cybereason-query-domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Domain to query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Domain.Name | string | Domain name |
| Cybereason.Domain.Malicious | boolean | Is domain malicious |
| Cybereason.Domain.IsInternalDomain | boolean | Is domain internal |
| Cybereason.Domain.Reputation | string | Domain reputation |
| Cybereason.Domain.SuspicionsCount | number | Domain suspicions count |
| Cybereason.Domain.WasEverResolved | boolean | Was domain ever resolved |
| Cybereason.Domain.WasEverResolvedAsASecondLevelDomain | boolean | Was domain ever resolved as a second level domain |
Command example
!cybereason-query-domain domain=www2.bing.com
Context Example
{
"Cybereason": {
"Domain": {
"IsInternalDomain": false,
"Malicious": false,
"Name": "www2.bing.com",
"Reputation": null,
"SuspicionsCount": 0,
"WasEverResolved": false,
"WasEverResolvedAsASecondLevelDomain": true
}
}
}
Human Readable Output
Cybereason domain query results for the domain: www2.bing.com
Name Reputation IsInternalDomain WasEverResolved WasEverResolvedAsASecondLevelDomain Malicious SuspicionsCount www2.bing.com indifferent false false true false 0 www2.bing.com false false true false 0
cybereason-query-user
Query users as part of investigation
Base Command
cybereason-query-user
Input
| Argument Name | Description | Required |
|---|---|---|
| username | Username to query. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.User.Username | string | User name |
| Cybereason.User.Domain | string | User domain |
| Cybereason.User.LastMachineLoggedInTo | string | Last machine which user logged in to |
| Cybereason.User.LocalSystem | boolean | Is local system |
| Cybereason.User.Organization | string | User organization |
Command example
!cybereason-query-user username="user-name"
Context Example
{
"Cybereason": {
"User": {
"Domain": "<machine-name>",
"LastMachineLoggedInTo": "<machine-name>",
"LocalSystem": false,
"Organization": "INTEGRATION",
"Username": "user-name"
}
}
}
Human Readable Output
Cybereason user query results for the username: machine-name\prase
Username Domain LastMachineLoggedInTo Organization LocalSystem machine-name\prase machine-name machine-name INTEGRATION false
cybereason-archive-sensor
Archives a Sensor.
Base Command
cybereason-archive-sensor
Input
| Argument Name | Description | Required |
|---|---|---|
| sensorID | Sensor ID of Cybereason Sensor. | Required |
| archiveReason | Reason for Archiving Cybereason Sensor. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-archive-sensor sensorID=SENSOR_ID archiveReason="Archive this Sensor"
Human Readable Output
Sensor archive status: Failed Actions: 0. Succeeded Actions: 1
cybereason-unarchive-sensor
Unarchives a Sensor.
Base Command
cybereason-unarchive-sensor
Input
| Argument Name | Description | Required |
|---|---|---|
| sensorID | Sensor ID of Cybereason Sensor. | Required |
| unarchiveReason | Reason for Unarchiving Cybereason Sensor. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-unarchive-sensor sensorID=SENSOR_ID unarchiveReason="Unarchive this Sensor"
Human Readable Output
Sensor unarchive status: Failed Actions: 0. Succeeded Actions: 1
cybereason-delete-sensor
Deletes a Sensor.
Base Command
cybereason-delete-sensor
Input
| Argument Name | Description | Required |
|---|---|---|
| sensorID | Sensor ID of Cybereason Sensor. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-delete-sensor sensorID=SENSOR_ID
Human Readable Output
Sensor deleted successfully.
cybereason-start-fetchfile
Start fetching the file to download
Base Command
cybereason-start-fetchfile
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGUID | Malop GUID for fetching a file from a sensor to download. | Required |
| userName | The complete Cybereason user name string for the user performing the request. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-start-fetchfile malopGUID=<malop_id> userName=<user_name>
Human Readable Output
Successfully started fetching file for the given malop
cybereason-fetchfile-progress
Return a batch id for files waiting for download
Base Command
cybereason-fetchfile-progress
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | Malop GUID to know the progress for downloading a file. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Download.Progress.fileName | unknown | Filename for tha given malop |
| Cybereason.Download.Progress.status | unknown | Status for batch ID |
| Cybereason.Download.Progress.batchID | unknown | Unique batch id |
Command example
!cybereason-fetchfile-progress malopGuid=<malop_id>
Context Example
{
"Download": {
"progress": {
"MalopID": "<malop_id>",
"batchID": [
-1234
],
"fileName": [
"<file_name>"
],
"status": [
true
]
}
}
}
Human Readable Output
Filename: [‘winrar-x64-602.exe’] Status: [True] Batch ID: [-1234]
cybereason-download-file
Downloads the actual file to the machine
Base Command
cybereason-download-file
Input
| Argument Name | Description | Required |
|---|---|---|
| batchID | The batch id for the file download operation. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-download-file batchID=-1234
Context Example
{
"File": {
"EntryID": "<entry_id>",
"Extension": "zip",
"Info": "application/zip",
"MD5": "<md5>",
"Name": "download.zip",
"SHA1": "<sha1>",
"SHA256": "<SHA256>",
"SHA512": "<SHA512>",
"SSDeep": "<SSDeep_value>",
"Size": 3168792,
"Type": "Zip archive data, at least v2.0 to extract"
}
}
Human Readable Output
Integration log: Downloading the file with this Batch ID: -1234
cybereason-close-file-batch-id
Aborts a file download operation that is in progress
Base Command
cybereason-close-file-batch-id
Input
| Argument Name | Description | Required |
|---|---|---|
| batchID | The batch id to abort a file download operation. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-close-file-batch-id batchID=-1234
Human Readable Output
Successfully aborts a file download operation that is in progress.
cybereason-available-remediation-actions
Get all remediation action details whatever available for that malop
Base Command
cybereason-available-remediation-actions
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | The unique ID assigned by the Cybereason platform for the Malop. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-available-remediation-actions malopGuid=<malop_id>
Human Readable Output
{ "data": [ { "machineConnected": false, "machineId": "machine_id", "machineName": "<machine-name>", "machinesCount": 1, "malopId": "<malop_id>", "malopType": "MalopProcess", "remediationType": "BLOCK_FILE", "targetId": "<target_id>", "targetName": "<target_name>", "uniqueId": "<unique_id>" }, { "machineConnected": false, "machineId": "<machine_id>", "machineName": "<machine-name>", "machinesCount": 1, "malopId": "<malop_id>", "malopType": "MalopProcess", "remediationType": "UNQUARANTINE_FILE", "targetId": "<target_id>", "targetName": "<target_name>", "uniqueId": "<unique_id>" } ], "errorMessage": "", "status": "SUCCESS" }
cybereason-kill-process
Kill a processes for the malicious file. (User will get inputs by executing the ‘cybereason-available-remediation-actions’ command if this remediation action is available for that Malop)
Base Command
cybereason-kill-process
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | The unique ID assigned by the Cybereason platform for the Malop. | Required |
| machine | Machine name to kill the process. | Required |
| targetId | Target ID to kill the process. | Required |
| userName | The complete Cybereason user name string for the user performing the request. | Required |
| comment | Comment to add to the malop. | Optional |
Context Output
There is no context output for this command.
Command example
!cybereason-kill-process machine=machine-name malopGuid=<malop_id> targetId=<target_id> userName=<user_name> comment="Kill the Process"
Human Readable Output
Kill process remediation action status is: SUCCESS
Remediation ID: REMEDIATION_ID
cybereason-quarantine-file
Quarantine the detected malicious file in a secure location. (User will get inputs by executing the ‘cybereason-available-remediation-actions’ command if this remediation action is available for that Malop)
Base Command
cybereason-quarantine-file
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | The unique ID assigned by the Cybereason platform for the Malop. | Required |
| machine | Machine name to quarantine a file. | Required |
| targetId | Target ID to quarantine a file. | Required |
| userName | The complete Cybereason user name string for the user performing the request. | Required |
| comment | Comment to add to the malop. | Optional |
Context Output
There is no context output for this command.
Command example
!cybereason-quarantine-file machine=machine-name malopGuid=<malop_id> targetId=<target_id> userName=<user_name> comment="Quarantine the File"
Human Readable Output
Quarantine file remediation action status is: SUCCESS
Remediation ID: REMEDIATION_ID
cybereason-unquarantine-file
Unquarantine the detected malicious file in a secure location. (User will get inputs by executing the ‘cybereason-available-remediation-actions’ command if this remediation action is available for that Malop)
Base Command
cybereason-unquarantine-file
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | The unique ID assigned by the Cybereason platform for the Malop. | Required |
| machine | Machine name to unquarantine a file. | Required |
| targetId | Target ID to unquarantine a file. | Required |
| userName | The complete Cybereason user name string for the user performing the request. | Required |
| comment | Comment to add to the malop. | Optional |
Context Output
There is no context output for this command.
Command example
!cybereason-unquarantine-file machine=machine-name malopGuid=<malop_id> targetId=<target_id> userName=<user_name> comment="Unquarantine the File"
Human Readable Output
Unquarantine file remediation action status is: SUCCESS
Remediation ID: REMEDIATION_ID
cybereason-block-file
Block a file only in particular machine. (User will get inputs by executing the ‘cybereason-available-remediation-actions’ command if this remediation action is available for that Malop)
Base Command
cybereason-block-file
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | The unique ID assigned by the Cybereason platform for the Malop. | Required |
| machine | Machine name whose files needs to be blocked. | Required |
| targetId | Target ID of file to be blocked. | Required |
| userName | The complete Cybereason user name string for the user performing the request. | Required |
| comment | Comment to add to the malop. | Optional |
Context Output
There is no context output for this command.
Command example
!cybereason-block-file machine=machine-name malopGuid=<malop_id> targetId=<target_id> userName=<user_name> comment="Block a File"
Human Readable Output
Block file remediation action status is: SUCCESS
Remediation ID: REMEDIATION_ID
cybereason-delete-registry-key
Delete a registry entry associated with a malicious process. (User will get inputs by executing the ‘cybereason-available-remediation-actions’ command if this remediation action is available for that Malop)
Base Command
cybereason-delete-registry-key
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | The unique ID assigned by the Cybereason platform for the Malop. | Required |
| machine | Machine name to delete the registry key. | Required |
| targetId | Target ID to delete the registry key. | Required |
| userName | The complete Cybereason user name string for the user performing the request. | Required |
| comment | Comment to add to the malop. | Optional |
Context Output
There is no context output for this command.
Command example
!cybereason-delete-registry-key machine=machine-name malopGuid=<malop_id> targetId=<target_id> userName=<user_name> comment="Remove the registry key"
Human Readable Output
Delete registry key remediation action status is: SUCCESS
Remediation ID: REMEDIATION_ID
cybereason-kill-prevent-unsuspend
Prevent detected ransomware from running on the machine. (User will get inputs by executing the ‘cybereason-available-remediation-actions’ command if this remediation action is available for that Malop)
Base Command
cybereason-kill-prevent-unsuspend
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | The unique ID assigned by the Cybereason platform for the Malop. | Required |
| machine | Machine name to prevent detected ransomware from running on the machine. | Required |
| targetId | Target ID to prevent detected ransomware from running on the machine. | Required |
| userName | The complete Cybereason user name string for the user performing the request. | Required |
| comment | Comment to add to the malop. | Optional |
Context Output
There is no context output for this command.
Command example
!cybereason-kill-prevent-unsuspend machine=machine-name malopGuid=<malop_id> targetId=<target_id> userName=<user_name> comment="Kill Prevent"
Human Readable Output
Kill prevent unsuspend remediation action status is: SUCCESS
Remediation ID: REMEDIATION_ID
cybereason-unsuspend-process
Prevent a file associated with ransomware. (User will get inputs by executing the ‘cybereason-available-remediation-actions’ command if this remediation action is available for that Malop)
Base Command
cybereason-unsuspend-process
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | The unique ID assigned by the Cybereason platform for the Malop. | Required |
| machine | Machine name to prevent a file associated with ransomware. | Required |
| targetId | Target ID to prevent a file associated with ransomware. | Required |
| userName | The complete Cybereason user name string for the user performing the request. | Required |
| comment | Comment to add to the malop. | Optional |
Context Output
There is no context output for this command.
Command example
!cybereason-unsuspend-process machine=machine-name malopGuid=<malop_id> targetId=<target_id> userName=<user_name> comment="Unsuspend Process"
Human Readable Output
Unsuspend process remediation action status is: SUCCESS
Remediation ID: REMEDIATION_ID
cybereason-malware-query
Malware query with options and values to filter
Base Command
cybereason-malware-query
Input
| Argument Name | Description | Required |
|---|---|---|
| needsAttention | Filter for Fetching Malwares by Malware needsAttention. Possible values are: True, False. | Optional |
| type | Filter for Fetching Malwares by Malware Type. (Possible filter values for Type are “KnownMalware,UnknownMalware,FilelessMalware,ApplicationControlMalware,RansomwareMalware”). | Optional |
| status | Filter for Fetching Malwares by Malware Status. (Possible filter values for Status are “Done,Excluded,Detected,Prevented,Remediated,DeleteOnRestart,Quarantined”). | Optional |
| timestamp | Filter for Fetching Malwares by Timestamp. Enter the time (in epoch). | Optional |
| limit | Filter for Fetching Malwares by Malware Limit. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-malware-query limit=5 needsAttention=True status=Done type=KnownMalware timestamp=1582206286000
Human Readable Output
{ "data": { "hasMoreResults": false, "malwares": [], "totalResults": 0 }, "expectedResults": 0, "failedServersInfo": null, "failures": 0, "hidePartialSuccess": false, "message": "", "status": "SUCCESS" }
cybereason-start-host-scan
Start or stop a full or quick scan for a host.
Base Command
cybereason-start-host-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| sensorID | Sensor ID of a sensor. (Comma separated values supported.). | Required |
| scanType | Select a method/type to scan a host. Possible values are: FULL, QUICK, STOP. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-start-host-scan sensorID=SENSOR_ID scanType=FULL
Human Readable Output
Batch ID: -11156
cybereason-fetch-scan-status
Get the results for host scanning.
Base Command
cybereason-fetch-scan-status
Input
| Argument Name | Description | Required |
|---|---|---|
| batchID | The batch ID obtained after initiating the scan. | Required |
Context Output
There is no context output for this command.
Command example
!cybereason-fetch-scan-status batchID=-11156
Human Readable Output
{ "abortHttpStatusCode": null, "abortTime": 0, "abortTimeout": false, "aborterUser": null, "actionArguments": [ "ScheduleScanAction", "FULL" ], "actionType": "SchedulerScan", "batchId": -11156, "creatorUser": "<user_name>", "finalState": true, "globalStats": { "stats": { "AbortTimeout": 0, "Aborted": 0, "Aborting": 0, "AlreadyUpdated": 0, "BadArgument": 0, "ChunksRequired": 0, "Disconnected": 0, "EndedWithInvalidParam": 0, "EndedWithNoValidFolder": 0, "EndedWithSensorTimeout": 0, "EndedWithTooManyResults": 0, "EndedWithTooManySearches": 0, "EndedWithUnknownError": 0, "EndedWithUnsupportedFilter": 0, "EndedWithYaraCompileError": 0, "Failed": 0, "FailedSending": 0, "FailedSendingToServer": 0, "GettingChunks": 0, "InProgress": 0, "InvalidState": 0, "MsiFileCorrupted": 0, "MsiSendFail": 0, "NewerInstalled": 0, "None": 0, "NotSupported": 0, "Pending": 0, "Primed": 0, "ProbeRemoved": 0, "SendingMsi": 0, "SendingPlatform": 0, "Started": 0, "Succeeded": 1, "Timeout": 0, "TimeoutSending": 0, "UnauthorizedUser": 0, "UnknownProbe": 0, "partialResponse": 0 } }, "initiatorUser": "<user_name>", "startTime": 1652279731232, "totalNumberOfProbes": 1 }
cybereason-get-sensor-id
Get the Sensor ID of a machine.
Base Command
cybereason-get-sensor-id
Input
| Argument Name | Description | Required |
|---|---|---|
| machineName | The hostname of the machine. | Optional |
Context Output
There is no context output for this command.
Command example
!cybereason-get-sensor-id machineName=machine-name
Human Readable Output
Sensor ID for the machine ‘machine-id’ is: SENSOR_ID
cybereason-get-machine-details
Get the results related to machines.
Base Command
cybereason-get-machine-details
Input
| Argument Name | Description | Required |
|---|---|---|
| machineName | The hostname of the machine. | Required |
| page | The page number of machine records to retrieve (used for pagination) starting from 1. The page size is defined by the “pageSize” argument. | Optional |
| pageSize | The number of machine records per page to retrieve (used for pagination). The page number is defined by the “page” argument. | Optional |
| limit | The maximum number of records to retrieve. If “pageSize” is defined, this argument is ignored. Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Sensor.MachineID | string | Sensor ID of machine |
| Cybereason.Sensor.MachineName | string | Host name of machine |
| Cybereason.Sensor.MachineFQDN | string | FQDN of machine |
| Cybereason.Sensor.GroupID | string | Group ID of machine |
| Cybereason.Sensor.GroupName | string | Group Name of machine |
Command example
!cybereason-get-machine-details machineName=xyz-1
Context Example
{
"MachineID": "example-machine-id",
"MachineName": "example-machine-name",
"MachineFQDN": "example-machine-fqdn",
"GroupID": "example-group-id",
"GroupName": "example-group-name"
}
Base Command
cybereason-query-malop-management
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | malopGuid of the Cybereason Malop. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Malops.GUID | string | The unique globally unique identifier (guid) for the Malop. |
| Cybereason.Malops.CreationTime | string | The time reported as when the malicious behavior began on the system. This is not the time that the Malop was first detected by Cybereason. |
| Cybereason.Malops.Link | string | Link to the Malop on Cybereason. |
| Cybereason.Malops.LastUpdatedTime | string | Last updated time of malop |
| Cybereason.Malops.InvolvedHash | string | List of file hashes involved in this Malop |
| Cybereason.Malops.Status | string | Malop managemant status |
| Cybereason.Malops.MalopCloserName | string | List of Malop Closer Name involved in this Malop |
| Cybereason.Malops.Machines | string | List of Machines involved in this Malop |
| Cybereason.Malops.Severity | string | Severity of Malop |
| Cybereason.Malops.MitreTechniques | string | List of Mitre Techniques involved in this Malop |
| Cybereason.Malops.Users | string | List of Users involved in this Malop |
| Cybereason.Malops.DetectionTypes | string | List of Detection Types involved in this Malop |
| Cybereason.Malops.DecisionStatuses | string | List of Decision Statuses involved in this Malop |
| Cybereason.Malops.DetectionEngines | string | List of Detection Engines involved in this Malop |
Command example
!cybereason-query-malop-management malopGuid=<malop-guid>
Context Example
{
"GUID": "malop-guid",
"Link": "malop-url",
"CreationTime": 1686720403740,
"LastUpdateTime": 1686720403743,
"Status": "Pending",
"InvolvedHash": "involed-hash"
}
Base Command
cybereason_process_attack_tree_command
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | malopGuid of the Cybereason Malop | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Process.ProcessID | string | Cybereason Process ID |
| Cybereason.Process.URL | string | Attack tree url for a given Process |
Command example
!cybereason-process-attack-tree processGuid=<process-guid>
Context Example
{
"Process": [
{
"ProcessID": "<process-id>",
"URL": "<url>"
},
{
"ProcessID": "<process-id>",
"URL": "<url>"
}
]
}
cybereason-update-malop-investigation-status
Updates malop investigation status.
Base Command
cybereason-update-malop-investigation-status
Input
| Argument Name | Description | Required |
|---|---|---|
| malopGuid | Malop GUID to update its investigation status. | Required |
| investigationStatus | Investigation status to update. Possible values are: Pending, Reopened, Under Investigation, On Hold, Closed. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Cybereason.Malops.GUID | string | Malop GUID. |
| Cybereason.Malops.InvestigationStatus | string | Malop investigation status: Pending, Reopened, Under Investigation, On Hold, Closed. |
Command example
!cybereason-update-malop-investigation-status malopGuid=<malop_guid> investigationStatus="Under Investigation"
Context Example
{
"Cybereason": {
"Malops": {
"GUID": "<malop_guid>",
"InvestigationStatus": "Under Investigation"
}
}
}
Human Readable Output
Successfully updated malop to investigation status "Under Investigation"!
Configuration parameters
server— Server URL (e.g. https://192.168.0.1) (required)credentials— Credentialsunsecure— Trust any certificate (not secure)proxy— Use system proxy settingsisFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalfetch_time— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days, 3 months, 1 year)fetch_by— Fetch by "MALOP UPDATE TIME" (Fetching by Malop creation time is no longer supported)enable_epp_poll— Check this box to Enable Polling for Cybereason EPP Malops.
Commands (37)
-
cybereason-add-commentAdd new comment to malop.
-
cybereason-archive-sensorArchives a Sensor.
-
cybereason-available-remediation-actionsGet all remediation action details whatever available for that malop.
-
cybereason-block-fileBlock a file only in particular machine. (User will get inputs by executing the 'cybereason-available-remediation-actions' command if this remediation action is available for that Malop).
-
cybereason-close-file-batch-idAborts a file download operation that is in progress.
-
cybereason-delete-registry-keyDelete a registry entry associated with a malicious process. (User will get inputs by executing the 'cybereason-available-remediation-actions' command if this remediation action is available for that Malop).
-
cybereason-delete-sensorDeletes a Sensor.
-
cybereason-download-fileDownloads the actual file to the machine.
-
cybereason-fetch-scan-statusGet the results for host scanning.
-
cybereason-fetchfile-progressReturn a batch id for files waiting for download.
-
cybereason-get-machine-detailsGet the Machine FQDN and Machine Group Details.
-
cybereason-get-sensor-idGet the Sensor ID of a machine.
-
cybereason-is-probe-connectedChecks if the machine is currently connected to the Cybereason server.
-
cybereason-isolate-machineIsolates a machine that has been infected from the rest of the network.
-
cybereason-kill-prevent-unsuspendPrevent detected ransomware from running on the machine. (User will get inputs by executing the 'cybereason-available-remediation-actions' command if this remediation action is available for that Malop).
-
cybereason-kill-processKill a processes for the malicious file. (User will get inputs by executing the 'cybereason-available-remediation-actions' command if this remediation action is available for that Malop).
-
cybereason-malop-processesReturns a list of malops.
-
cybereason-malware-queryMalware query with options and values to filter.
-
cybereason-prevent-filePrevent malop process file.
-
cybereason-process-attack-treeGet Process Attack Tree URL.
-
cybereason-quarantine-fileQuarantine the detected malicious file in a secure location. (User will get inputs by executing the 'cybereason-available-remediation-actions' command if this remediation action is available for that Malop).
-
cybereason-query-connectionsSearches for connections.
-
cybereason-query-domainQuery domains as part of investigation.
-
cybereason-query-fileQuery files as part of investigation.
-
cybereason-query-malop-managementGet Management Malop details.
-
cybereason-query-malopsReturns a list of all Malops and details on the Malops.
-
cybereason-query-processesSearches for processes with various filters.
-
cybereason-query-userQuery users as part of investigation.
-
cybereason-start-fetchfileStart fetching the file to download.
-
cybereason-start-host-scanStart or stop a full or quick scan for a host.
-
cybereason-unarchive-sensorUnarchives a Sensor.
-
cybereason-unisolate-machineStops isolation of a machine.
-
cybereason-unprevent-fileUnprevent malop process file.
-
cybereason-unquarantine-fileUnquarantine the detected malicious file in a secure location. (User will get inputs by executing the 'cybereason-available-remediation-actions' command if this remediation action is available for that Malop).
-
cybereason-unsuspend-processPrevent a file associated with ransomware. (User will get inputs by executing the 'cybereason-available-remediation-actions' command if this remediation action is available for that Malop).
-
cybereason-update-malop-investigation-statusUpdates malop investigation status.
-
cybereason-update-malop-statusUpdates malop status.
import json import demistomock as demisto import pytest class MockResponse: def __init__(self, json_data, status_code): self.json_data = json_data self.status_code = status_code self.content = "test_content" def test_login_failed(requests_mock, mocker): """ Given: - Cybereason instance with invalid credentials When: - Running test module Then: - Ensure an indicative error is returned that authorization failed """ login_failed_html = b"""<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Cybereason | Login</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="favicon.ico"> <link rel="shortcut icon" href="favicon.ico"><link href="public/vendors_c29907a62751511cc002.css" rel="stylesheet"><link href="public/login_62faa8ec0f21f2d2949f.css" rel="stylesheet"></head> # noqa: E501 <body class="cbr-theme-dark"> <app-login></app-login> <script type="text/javascript" src="public/vendors_c29907a62751511cc002.js"></script><script type="text/javascript" src="public/login_62faa8ec0f21f2d2949f.js"></script></body> # noqa: E501 </html> """ # noqa: E501 mocker.patch.object( demisto, "params", return_value={ "server": "http://server", "credentials": {"identifier": "username", "password": "password"}, "proxy": True, }, ) mocker.patch.object(demisto, "command", return_value="test-module") return_error_mock = mocker.patch("Cybereason.return_error") requests_mock.post("http://server/login.html", content=login_failed_html) requests_mock.post("http://server/rest/visualsearch/query/simple", content=login_failed_html) requests_mock.get("http://server/logout") from Cybereason import main main() assert return_error_mock.call_count == 1 err_msg = return_error_mock.call_args[0][0] assert "Failed to process the API response. Authentication failed, verify the credentials are correct." in err_msg params = {"server": "http://server", "credentials": {"identifier": "username", "password": "password"}, "proxy": True} def load_mock_response(file_name: str) -> str: """ Load mock file that simulates an API response. Args: file_name (str): Name of the mock response JSON file to return. Returns: str: Mock file content. """ with open(f"test_data/{file_name}", encoding="utf-8") as mock_file: return mock_file.read() def test_cybereason_api_call(mocker): """ Given: - API call returns a redirect to the login page (session expired). When: - cybereason_api_call() is executed. Then: - Should trigger re-login, update token, and retry request successfully. """ from Cybereason import Client import time mock_response_login_redirect = mocker.Mock() mock_response_login_redirect.status_code = 200 mock_response_login_redirect.url = "https://server/login.html" mock_response_success = mocker.Mock() mock_response_success.status_code = 200 mock_response_success.url = "https://server/some_api" mock_response_success.json.return_value = {"result": "ok"} mock_http_request = mocker.Mock(side_effect=[mock_response_login_redirect, mock_response_success]) mock_login = mocker.patch("Cybereason.login", return_value=("new_token", int(time.time()))) mocker.patch("Cybereason.get_integration_context", return_value={}) mock_set_context = mocker.patch("Cybereason.set_integration_context") mock_headers = mocker.patch("Cybereason.HEADERS", {"Cookie": ""}) client = Client(base_url="https://server", verify=False, headers=mock_headers, proxy=False) client._http_request = mock_http_request result = client.cybereason_api_call("GET", "/some_api", json_body={}) # Assertions mock_login.assert_called_once() assert result == {"result": "ok"} assert mock_set_context.called assert "JSESSIONID=new_token" in mock_headers["Cookie"] assert mock_http_request.call_count == 2 def test_validate_jsession_two(mocker): """ Given: - A token validity scenario (valid or expired). When: - validate_jsession() is called. Then: - If token is valid → should NOT refresh. - If token expired → should refresh and update context. """ from Cybereason import validate_jsession import time token_valid = False expected_refresh = True mock_time = int(time.time()) valid_until = mock_time + 10000 if token_valid else mock_time - 10 mock_integration_context = { "jsession_id": "old_token", "valid_until": valid_until, } mocker.patch("Cybereason.get_integration_context", return_value=mock_integration_context) mock_set_context = mocker.patch("Cybereason.set_integration_context") mock_headers = mocker.patch("Cybereason.HEADERS", {}) mock_login = mocker.patch("Cybereason.login", return_value=("new_token", mock_time)) mock_client = mocker.Mock() validate_jsession(mock_client) if expected_refresh: # Expired case: login called, context updated mock_login.assert_called_once() mock_set_context.assert_called_once() assert mock_integration_context["jsession_id"] == "new_token" assert mock_integration_context["valid_until"] == mock_time + 28000 assert "JSESSIONID=new_token" in mock_headers["Cookie"] else: # Valid token case: no refresh mock_login.assert_not_called() mock_set_context.assert_not_called() assert "JSESSIONID=old_token" in mock_headers["Cookie"] def test_one_query_file(mocker): from Cybereason import Client, query_file_command HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"file_hash": "4778901e54f55d54435b2626923054a8"} machine_raw_response = json.loads(load_mock_response("machine_outputs.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=machine_raw_response) raw_response = json.loads(load_mock_response("file_outputs.json")) mocker.patch("Cybereason.query_file", return_value=raw_response) command_output = query_file_command(client, args) assert command_output.outputs_prefix == "Cybereason.File" def test_two_query_file(mocker): from Cybereason import Client, query_file_command HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"file_hash": "4778901e54f55d54435b2626923054a8"} machine_raw_response = json.loads(load_mock_response("machine_outputs.json")) mocker.patch("Cybereason.get_file_machine_details", return_value=machine_raw_response) raw_response = {"status": "SUCCESS", "data": None} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) with pytest.raises(Exception) as exc_info: query_file_command(client, args) assert exc_info.match(r"No results found.") args = {"file_hash": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value={}) with pytest.raises(Exception) as exc_info: query_file_command(client, args) assert exc_info.match(r"Hash type is not supported.") def test_validate_jsession(mocker): from Cybereason import Client, validate_jsession, HEADERS import time # Mock constants and objects client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) creation_time = int(time.time()) # Mocking integration context functions mock_integration_context = { "jsession_id": "valid_token", "valid_until": creation_time - 1000, # Expired token } mocker.patch("Cybereason.get_integration_context", return_value=mock_integration_context) mock_set_context = mocker.patch("Cybereason.set_integration_context") mocker.patch("Cybereason.login", return_value=("new_token", creation_time)) # Patch the global HEADERS mock_headers = mocker.patch("Cybereason.HEADERS", HEADERS) # Call function validate_jsession(client) # Assertions assert mock_headers["Cookie"] == "JSESSIONID=new_token", f"Expected Cookie to be set, but got: {mock_headers}" mock_set_context.assert_called_once_with({"jsession_id": "new_token", "valid_until": creation_time + 28000}) def test_get_remediation_action_status_success(mocker): from Cybereason import get_remediation_action_status, Client # Mock dependencies mocker.patch( "Cybereason.dict_safe_get", side_effect=lambda d, keys: "remediation123" if "remediationId" in keys else "SUCCESS" ) mocker.patch("Cybereason.get_remediation_action_progress", return_value={"Remediation status": "SUCCESS"}) mocker.patch("Cybereason.add_comment") HEADERS = {"Content-Type": "application/json", "Connection": "close"} # Prepare test inputs client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) user_name = "test_user" malop_guid = "malop123" response = {"remediationId": "remediation123"} comment = "Remediation successful." # Call the function result = get_remediation_action_status(client, user_name, malop_guid, response, comment) # Assertions assert result["Remediation status"] == "SUCCESS" assert result["Remediation ID"] == "remediation123" def test_malop_processes_command(mocker): from Cybereason import malop_processes_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"malopGuids": "11.-6236127207710541535", "machineName": "desktop", "dateTime": "None"} raw_response = json.loads(load_mock_response("malop_processes_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) mocker.patch.object(demisto, "results") command_output = malop_processes_command(client, args) assert command_output.outputs[0].get("Name", "") == "bdata.bin" assert command_output.outputs[0].get("SHA1", "") == "f56238da9fbfa3864d443a85bb80743bd2415682" args = {"malopGuids": None, "machineName": "desktop", "dateTime": "2022/08/01 00:00:00"} mocker.patch.object(demisto, "results") with pytest.raises(Exception) as exc_info: command_output = malop_processes_command(client, args) assert exc_info.match(r"malopGuids must be array of strings") def test_is_probe_connected_command(mocker): from Cybereason import is_probe_connected_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"machine": "desktop-j60ivd0", "is_remediation_commmand": True} raw_response = json.loads(load_mock_response("is_probe_connected_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = is_probe_connected_command(client, args) assert command_output.readable_output == "True" def test_query_processes_command(mocker): from Cybereason import query_processes_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = { "machine": ["desktop-vg9ke2u"], "hasOutgoingConnection": "true", "hasIncomingConnection": "true", "hasExternalConnection": "true", "unsignedUnknownReputation": "true", "fromTemporaryFolder": "true", "privilegesEscalation": "true", "maliciousPsExec": "true", "processName": "test_process", "onlySuspicious": "true", } raw_response = json.loads(load_mock_response("query_processes_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = query_processes_command(client, args) assert command_output.outputs[0].get("SHA1", "") == "1bc5066ddf693fc034d6514618854e26a84fd0d1" def test_query_connections_command(mocker): from Cybereason import query_connections_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"ip": "192.168.1.103"} raw_response = json.loads(load_mock_response("query_processes_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = query_connections_command(client, args) assert command_output.outputs[0]["Name"] == "svchost.exe" args = {"machine": "desktop"} command_output = query_connections_command(client, args) assert command_output.outputs[0]["Name"] == "svchost.exe" args = {"machine": "desktop", "ip": "192.168.1.103"} with pytest.raises(Exception) as exc_info: command_output = query_connections_command(client, args) assert exc_info.match(r"Too many arguments given.") args = {} with pytest.raises(Exception) as exc_info: command_output = query_connections_command(client, args) assert exc_info.match(r"Not enough arguments given.") def test_isolate_machine_command(mocker): from Cybereason import isolate_machine_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"machine": "desktop-vg9ke2u"} raw_response = json.loads(load_mock_response("isolate_machine_raw_response.json")) mocker.patch("Cybereason.get_pylum_id", return_value="PYLUMCLIENT_INTEGRATION_DESKTOP-VG9KE2U_0800273ADC2F") mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = isolate_machine_command(client, args) assert command_output[0].outputs_prefix == "Cybereason" def test_unisolate_machine_command(mocker): from Cybereason import unisolate_machine_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"machine": "desktop-vg9ke2u"} raw_response = json.loads(load_mock_response("isolate_machine_raw_response.json")) mocker.patch("Cybereason.get_pylum_id", return_value="PYLUMCLIENT_INTEGRATION_DESKTOP-VG9KE2U_0800273ADC2F") mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = unisolate_machine_command(client, args) assert command_output[0].outputs_prefix == "Cybereason" def test_get_non_edr_malop_data(mocker): from Cybereason import get_detection_details from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"malopGuid": "AAAA0yUlnvXGQODT"} raw_response = json.loads(load_mock_response("malop_detection_data.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = get_detection_details(client, args) assert command_output["malops"][0]["guid"] == "AAAA0yUlnvXGQODT" def test_query_malops_command(mocker): from Cybereason import query_malops_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"withinLastDays": 10} malop_process_raw_response = json.loads(load_mock_response("query_malop_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=malop_process_raw_response) command_output = query_malops_command(client, args) assert command_output.outputs[0]["AffectedMachine"] == ["desktop-j60ivd0"] def test_query_malop_management_command(mocker): from Cybereason import query_malop_management_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"guid": "AAAA0w7GERjl3oae"} query_malop_management_raw_response = json.loads(load_mock_response("query_malop_management_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=query_malop_management_raw_response) command_output = query_malop_management_command(client, args) assert command_output.outputs[0]["GUID"] == "AAAA0w7GERjl3oae" def test_cybereason_process_attack_tree_command(mocker): from Cybereason import cybereason_process_attack_tree_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"processGuid": "HobXaEWU0CZ6S6LC"} url = "https://test.server.com:8888/#/processTree?guid=HobXaEWU0CZ6S6LC&viewedGuids=HobXaEWU0CZ6S6LC&rootType=Process" expected_response = [ { "ProcessID": "HobXaEWU0CZ6S6LC", "URL": url, } ] mocker.patch("Cybereason.Client.cybereason_api_call", return_value=expected_response) mocker.patch("Cybereason.SERVER", new="https://test.server.com:8888") command_output = cybereason_process_attack_tree_command(client, args) assert command_output.outputs[0] == expected_response[0] def test_update_malop_status_command(mocker): from Cybereason import update_malop_status_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"malopGuid": "11.-7780537507363356527", "status": "To Review"} raw_response = {"status": "SUCCESS"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = update_malop_status_command(client, args) assert command_output.outputs["GUID"] == "11.-7780537507363356527" assert command_output.outputs["Status"] == "To Review" raw_response = {"status": "SUCESS"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) with pytest.raises(Exception) as exc_info: command_output = update_malop_status_command(client, args) assert exc_info.match(r"message") args = {"malopGuid": "11.-7780537507363356527", "status": "test"} with pytest.raises(Exception) as exc_info: command_output = update_malop_status_command(client, args) assert exc_info.match(r"Invalid status.") def test_update_malop_investigation_status_command(mocker): from Cybereason import update_malop_investigation_status_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"malopGuid": "11.-7780537507363356527", "investigationStatus": "Under Investigation"} raw_response = {"status": "SUCCESS"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = update_malop_investigation_status_command(client, args) assert command_output.outputs["GUID"] == "11.-7780537507363356527" assert command_output.outputs["InvestigationStatus"] == "Under Investigation" raw_response = {"status": "SUCESS"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) with pytest.raises(Exception) as exc_info: command_output = update_malop_investigation_status_command(client, args) assert exc_info.match(r"message") args = {"malopGuid": "11.-7780537507363356527", "investigationStatus": "test"} with pytest.raises(Exception) as exc_info: command_output = update_malop_investigation_status_command(client, args) assert exc_info.match(r"Invalid investigation status") def test_prevent_file_command(mocker): from Cybereason import prevent_file_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"md5": "fc61fdcad5a9d52a01bd2d596f2c92b9"} raw_response = json.loads(load_mock_response("prevent_file_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = prevent_file_command(client, args) assert command_output.outputs["MD5"] == "fc61fdcad5a9d52a01bd2d596f2c92b9" raw_response = {"outcome": "failure"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) with pytest.raises(Exception) as exc_info: command_output = prevent_file_command(client, args) assert exc_info.match(r"Failed to prevent file") def test_unprevent_file_command(mocker): from Cybereason import unprevent_file_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"md5": "fc61fdcad5a9d52a01bd2d596f2c92b9"} raw_response = json.loads(load_mock_response("prevent_file_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = unprevent_file_command(client, args) assert command_output.outputs["MD5"] == "fc61fdcad5a9d52a01bd2d596f2c92b9" raw_response = {"outcome": "failure"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) with pytest.raises(Exception) as exc_info: command_output = unprevent_file_command(client, args) assert exc_info.match(r"Failed to unprevent file") def test_query_domain_command(mocker): from Cybereason import query_domain_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"domain": "www2.bing.com"} raw_response = json.loads(load_mock_response("query_domain_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = query_domain_command(client, args) assert command_output.outputs_prefix == "Cybereason.Domain" mocker.patch("Cybereason.Client.cybereason_api_call", return_value={}) with pytest.raises(Exception) as exc_info: command_output = query_domain_command(client, args) assert exc_info.match(r"Error occurred while trying to query the file.") raw_response = {"status": "SUCCESS", "data": None} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) with pytest.raises(Exception) as exc_info: command_output = query_domain_command(client, args) assert exc_info.match(r"No results found.") def test_query_user_command(mocker): from Cybereason import query_user_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"username": "desktop-vg9ke2u"} raw_response = json.loads(load_mock_response("query_user_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = query_user_command(client, args) assert command_output.outputs[0]["Username"] == "desktop-vg9ke2u" mocker.patch("Cybereason.Client.cybereason_api_call", return_value={}) with pytest.raises(Exception) as exc_info: command_output = query_user_command(client, args) assert exc_info.match(r"Error occurred while trying to query the file.") raw_response = {"status": "SUCCESS", "data": None} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) with pytest.raises(Exception) as exc_info: command_output = query_user_command(client, args) assert exc_info.match(r"No results found.") def test_available_remediation_actions_command(mocker): from Cybereason import available_remediation_actions_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"malopGuid": "11.-7780537507363356527"} raw_response = json.loads(load_mock_response("available_remediation_actions_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = available_remediation_actions_command(client, args) assert command_output.outputs_prefix == "Cybereason.Remediation" def test_start_fetchfile_command(mocker): from Cybereason import start_fetchfile_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"malopGUID": "11.-7780537507363356527", "userName": "desktop-vg9ke2u"} raw_response = json.loads(load_mock_response("get_file_guids_raw_response.json")) mocker.patch("Cybereason.get_file_guids", return_value=raw_response) raw_response = json.loads(load_mock_response("start_fetch_file_raw_response.json")) mocker.patch("Cybereason.start_fetchfile", return_value=raw_response) command_output = start_fetchfile_command(client, args) assert command_output.readable_output[0] == "S" def test_fetchfile_progress_command(mocker): from Cybereason import fetchfile_progress_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"malopGuid": "11.-7780537507363356527"} raw_response = json.loads(load_mock_response("get_file_guids_raw_response.json")) mocker.patch("Cybereason.get_file_guids", return_value=raw_response) raw_response = json.loads(load_mock_response("get_batch_id_raw_response.json")) mocker.patch("Cybereason.get_batch_id", return_value=raw_response) command_output = fetchfile_progress_command(client, args) assert command_output.outputs["MalopID"] == "11.-7780537507363356527" def test_quarantine_file_command(mocker): from Cybereason import quarantine_file_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = { "machine": "desktop-vg9ke2u", "malopGuid": "11.-7780537507363356527", "targetId": "-1845090846.-1424333057657783286", "userName": "desktop-vg9ke2u", "comment": "Quarantine the File", "timeout": 60, } mocker.patch("Cybereason.is_probe_connected_command", return_value=True) raw_response = json.loads(load_mock_response("get_remediation_action.json")) mocker.patch("Cybereason.get_remediation_action", return_value=raw_response) raw_response = json.loads(load_mock_response("get_remediation_action_status.json")) mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response) with pytest.raises(Exception) as exc_info: quarantine_file_command(client, args) assert exc_info.match(r"Quarantine file remediation") def test_unquarantine_file_command(mocker): from Cybereason import unquarantine_file_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = { "machine": "desktop-vg9ke2u", "malopGuid": "11.-7780537507363356527", "targetId": "-1845090846.-1424333057657783286", "userName": "desktop-vg9ke2u", "comment": "Unquarantine the File", "timeout": 60, } mocker.patch("Cybereason.is_probe_connected_command", return_value=True) raw_response = json.loads(load_mock_response("get_remediation_action.json")) mocker.patch("Cybereason.get_remediation_action", return_value=raw_response) raw_response = json.loads(load_mock_response("get_remediation_action_status.json")) mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response) with pytest.raises(Exception) as exc_info: unquarantine_file_command(client, args) assert exc_info.match(r"Unquarantine file remediation") def test_block_file_command(mocker): from Cybereason import block_file_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = { "machine": "desktop-vg9ke2u", "malopGuid": "11.-7780537507363356527", "targetId": "-1845090846.-1424333057657783286", "userName": "desktop-vg9ke2u", "comment": "Block the File", "timeout": 60, } mocker.patch("Cybereason.is_probe_connected_command", return_value=True) raw_response = json.loads(load_mock_response("get_remediation_action.json")) mocker.patch("Cybereason.get_remediation_action", return_value=raw_response) raw_response = json.loads(load_mock_response("get_remediation_action_status.json")) mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response) with pytest.raises(Exception) as exc_info: block_file_command(client, args) assert exc_info.match(r"Block file remediation") def test_kill_process_command(mocker): from Cybereason import kill_process_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = { "machine": "desktop-vg9ke2u", "malopGuid": "11.-7780537507363356527", "targetId": "-1845090846.-1424333057657783286", "userName": "desktop-vg9ke2u", "comment": "Kill the Process", } mocker.patch("Cybereason.is_probe_connected_command", return_value=True) raw_response = json.loads(load_mock_response("get_remediation_action.json")) mocker.patch("Cybereason.get_remediation_action", return_value=raw_response) raw_response = json.loads(load_mock_response("get_remediation_action_status.json")) mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response) with pytest.raises(Exception) as exc_info: kill_process_command(client, args) assert exc_info.match(r"Kill process remediation") def test_get_sensor_id_command(mocker): from Cybereason import get_sensor_id_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"machineName": "desktop-vg9ke2u"} raw_response = json.loads(load_mock_response("get_sensor_id_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = get_sensor_id_command(client, args) assert command_output.readable_output == ( "Available Sensor IDs are {'desktop-vg9ke2u': " "'5e77883de4b0575ddcf824ef:PYLUMCLIENT_INTEGRATION_DESKTOP-VG9KE2U_0800273ADC2F'}" ) mocker.patch("Cybereason.Client.cybereason_api_call", return_value={"sensors": []}) with pytest.raises(Exception) as exc_info: command_output = get_sensor_id_command(client, args) assert exc_info.match(r"Could not find any Sensor ID for the machine") def test_number_one_fetch_scan_status_command(mocker): from Cybereason import fetch_scan_status_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"batchID": "-1112786456"} raw_response = json.loads(load_mock_response("fetch_scan_status_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = fetch_scan_status_command(client, args) assert command_output.raw_response == "The given batch ID does not match with any actions on sensors." def test_malware_query_command(mocker): from Cybereason import malware_query_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"limit": "5", "needsAttention": "True", "status": "Done", "type": "KnownMalware", "timestamp": "1582206286000"} raw_response = raw_response = json.loads(load_mock_response("malware_query_raw_data.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = malware_query_command(client, args) assert command_output.raw_response["status"] == "SUCCESS" args = {"limit": "0"} with pytest.raises(Exception) as exc_info: command_output = malware_query_command(client, args) assert exc_info.match(r"Limit cannot be zero or a negative number.") def test_unsuspend_process_command(mocker): from Cybereason import unsuspend_process_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = { "machine": "desktop-vg9ke2u", "malopGuid": "11.-7780537507363356527", "targetId": "-1845090846.-1424333057657783286", "userName": "desktop-vg9ke2u", "comment": "Unsuspend Process", } mocker.patch("Cybereason.is_probe_connected_command", return_value=True) raw_response = json.loads(load_mock_response("get_remediation_action.json")) mocker.patch("Cybereason.get_remediation_action", return_value=raw_response) raw_response = json.loads(load_mock_response("get_remediation_action_status.json")) mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response) with pytest.raises(Exception) as exc_info: unsuspend_process_command(client, args) assert exc_info.match(r"Unsuspend process remediation") def test_kill_prevent_unsuspend_command(mocker): from Cybereason import kill_prevent_unsuspend_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = { "machine": "desktop-vg9ke2u", "malopGuid": "11.-7780537507363356527", "targetId": "-1845090846.-1424333057657783286", "userName": "desktop-vg9ke2u", "comment": "Kill Prevent", "timeout": "30", } mocker.patch("Cybereason.is_probe_connected_command", return_value=True) raw_response = json.loads(load_mock_response("get_remediation_action.json")) mocker.patch("Cybereason.get_remediation_action", return_value=raw_response) raw_response = json.loads(load_mock_response("get_remediation_action_status.json")) mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response) with pytest.raises(Exception) as exc_info: kill_prevent_unsuspend_command(client, args) assert exc_info.match(r"Kill prevent unsuspend") def test_delete_registry_key_command(mocker): from Cybereason import delete_registry_key_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = { "machine": "desktop-vg9ke2u", "malopGuid": "11.-7780537507363356527", "targetId": "-1845090846.-1424333057657783286", "userName": "desktop-vg9ke2u", "comment": "Remove the registry key", "timeout": 30, } mocker.patch("Cybereason.is_probe_connected_command", return_value=True) raw_response = json.loads(load_mock_response("get_remediation_action.json")) mocker.patch("Cybereason.get_remediation_action", return_value=raw_response) raw_response = json.loads(load_mock_response("get_remediation_action_status.json")) mocker.patch("Cybereason.get_remediation_action_status", return_value=raw_response) with pytest.raises(Exception) as exc_info: delete_registry_key_command(client, args) assert exc_info.match(r"Delete registry key") def test_add_comment_command(mocker): from Cybereason import add_comment_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"comment": "New comment", "malopGuid": "11.-7780537507363356527"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value={}) command_output = add_comment_command(client, args) assert command_output.readable_output == "Comment added successfully" def test_fetch_incidents(mocker): from Cybereason import fetch_incidents from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) raw_response = json.loads(load_mock_response("query_malop_management_raw_response.json")) mocker.patch("Cybereason.get_malop_management_data", return_value=raw_response) malop_process_raw_response = json.loads(load_mock_response("query_malop_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=malop_process_raw_response) command_output = fetch_incidents(client) command_output = str(command_output) assert command_output == "None" def test_archive_sensor_command(mocker): from Cybereason import archive_sensor_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) test_reponse = MockResponse({"key1": "val1"}, 204) args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) command_output = archive_sensor_command(client, args) assert command_output.readable_output == ( "The selected Sensor with Sensor ID: 5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ is not available for archive." ) test_reponse = MockResponse({"key1": "val1"}, 404) args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) with pytest.raises(Exception) as exc_info: command_output = archive_sensor_command(client, args) assert exc_info.match(r"Your request failed") def test_unarchive_sensor_command(mocker): from Cybereason import unarchive_sensor_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) test_reponse = MockResponse({"key1": "val1"}, 204) args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) command_output = unarchive_sensor_command(client, args) assert command_output.readable_output == ( "The selected Sensor with Sensor ID: 5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ is not available for unarchive." ) test_reponse = MockResponse({"key1": "val1"}, 404) args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) with pytest.raises(Exception) as exc_info: command_output = unarchive_sensor_command(client, args) assert exc_info.match(r"Your request failed") def test_delete_sensor_command(mocker): from Cybereason import delete_sensor_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) test_reponse = MockResponse({"key1": "val1"}, 200) args = {"sensorID": "5e77883de4b0575ddcf824ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ-4CTUN1V_123CC99CA7E5"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) command_output = delete_sensor_command(client, args) assert command_output.readable_output == "Sensor deleted successfully." test_reponse = MockResponse({"key1": "val1"}, 204) args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) command_output = delete_sensor_command(client, args) assert command_output.readable_output == ( "The selected Sensor with Sensor ID: 5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ is not available for deleting." ) test_reponse = MockResponse({"key1": "val1"}, 404) args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ"} mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) with pytest.raises(Exception) as exc_info: command_output = delete_sensor_command(client, args) assert exc_info.match(r"Your request failed") def test_start_host_scan_command(mocker): from Cybereason import start_host_scan_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"sensorID": "5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ", "scanType": "FULL"} test_reponse = MockResponse({"key1": "val1"}, 204) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) command_output = start_host_scan_command(client, args) assert command_output.readable_output == ( "Given Sensor ID/ID's ['5e778834ef:PYLUMCLIENT_INTEGRATION_EC2AMAZ'] is/are not available for scanning." ) test_reponse = MockResponse({"key1": "val1"}, 404) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) with pytest.raises(Exception) as exc_info: command_output = start_host_scan_command(client, args) assert exc_info.match(r"Your request failed") def test_number_two_fetch_scan_status_command(mocker): from Cybereason import fetch_scan_status_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"batchID": "123456"} test_reponse = [{"batchId": 123456}] mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) command_output = fetch_scan_status_command(client, args) assert command_output.raw_response == test_reponse[0] test_reponse = [{"batchId": "123456"}] mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) command_output = fetch_scan_status_command(client, args) assert command_output.raw_response == "The given batch ID does not match with any actions on sensors." def test_download_fetchfile_command(mocker): from Cybereason import download_fetchfile_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"batchID": "-1044817479"} test_reponse = MockResponse({"key1": "val1"}, 404) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) with pytest.raises(Exception) as exc_info: command_output = download_fetchfile_command(client, args) assert exc_info.match(r"request failed with the following error:") test_reponse = MockResponse({"key1": "val1"}, 200) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) command_output = download_fetchfile_command(client, args) assert command_output["File"] == "download.zip" def test_close_fetchfile_command(mocker): from Cybereason import close_fetchfile_command, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"batchID": "-796720096"} test_reponse = MockResponse({"key1": "val1"}, 200) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) with pytest.raises(Exception) as exc_info: close_fetchfile_command(client, args) assert exc_info.match(r"The given Batch ID does not exist") def test_malop_to_incident_edr_malop(mocker): from Cybereason import malop_to_incident args = { "guidString": "12345A", "status": 1, "simpleValues": { "detectionType": {"values": ["EXTENSION_MANIPULATION"]}, "creationTime": {"values": ["1721798910159"]}, "malopLastUpdateTime": {"values": ["1728032260900"]}, }, "elementValues": { "primaryRootCauseElements": {"elementValues": [{"elementType": "File", "name": "avg_secure_browser_setup.pdf.exe"}]} }, "isEdr": True, } command_output = malop_to_incident(args) assert all( [ (command_output["name"] == "Cybereason Malop 12345A"), (command_output["status"] == 0), (command_output["CustomFields"]["malopcreationtime"] == "1721798910159"), (command_output["CustomFields"]["malopupdatetime"] == "1728032260900"), (command_output["CustomFields"]["malopdetectiontype"] == "EXTENSION_MANIPULATION"), (command_output["CustomFields"]["maloprootcauseelementname"] == "avg_secure_browser_setup.pdf.exe"), (command_output["CustomFields"]["maloprootcauseelementtype"] == "File"), (command_output["CustomFields"]["malopedr"]), (command_output["dbotmirrorid"] == "12345A"), ] ) with pytest.raises(Exception) as exc_info: command_output = malop_to_incident("args") assert exc_info.match(r"Cybereason raw response is not valid") def test_malop_to_incident_remediated_non_edr_malop(mocker): from Cybereason import malop_to_incident args = { "guidString": "12345C", "status": "Remediated", "malopDetectionType": "ABCD", "creationTime": "23456", "lastUpdateTime": "6789", "edr": False, } command_output = malop_to_incident(args) assert all( [ (command_output["name"] == "Cybereason Malop 12345C"), (command_output["status"] == 1), (command_output["CustomFields"]["malopcreationtime"] == "23456"), (command_output["CustomFields"]["malopupdatetime"] == "6789"), (command_output["CustomFields"]["malopdetectiontype"] == "ABCD"), (not command_output["CustomFields"]["malopedr"]), (command_output["dbotmirrorid"] == "12345C"), ] ) with pytest.raises(Exception) as exc_info: command_output = malop_to_incident("args") assert exc_info.match(r"Cybereason raw response is not valid") def test_malop_to_incident_resolved_non_edr_malop(mocker): from Cybereason import malop_to_incident args = { "guidString": "12345D", "status": "RESOLVED", "malopDetectionType": "ABCD", "creationTime": "23456", "lastUpdateTime": "6789", "edr": False, } command_output = malop_to_incident(args) assert all( [ (command_output["name"] == "Cybereason Malop 12345D"), (command_output["status"] == 2), (command_output["CustomFields"]["malopcreationtime"] == "23456"), (command_output["CustomFields"]["malopupdatetime"] == "6789"), (command_output["CustomFields"]["malopdetectiontype"] == "ABCD"), (not command_output["CustomFields"]["malopedr"]), (command_output["dbotmirrorid"] == "12345D"), ] ) with pytest.raises(Exception) as exc_info: command_output = malop_to_incident("args") assert exc_info.match(r"Cybereason raw response is not valid") def test_malop_to_incident_active_non_edr_malop(mocker): from Cybereason import malop_to_incident args = { "guidString": "12345D", "status": "Active", "malopDetectionType": "ABCD", "creationTime": "23456", "lastUpdateTime": "6789", "edr": False, } command_output = malop_to_incident(args) assert all( [ (command_output["name"] == "Cybereason Malop 12345D"), (command_output["status"] == 0), (command_output["CustomFields"]["malopcreationtime"] == "23456"), (command_output["CustomFields"]["malopupdatetime"] == "6789"), (command_output["CustomFields"]["malopdetectiontype"] == "ABCD"), (not command_output["CustomFields"]["malopedr"]), (command_output["dbotmirrorid"] == "12345D"), ] ) with pytest.raises(Exception) as exc_info: command_output = malop_to_incident("args") assert exc_info.match(r"Cybereason raw response is not valid") def test_get_pylum_id(mocker): from Cybereason import get_pylum_id, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) test_reponse = { "data": { "resultIdToElementDataMap": { "-1845090846.1198775089551518743": { "simpleValues": {"pylumId": {"totalValues": 1, "values": [None]}}, } } } } raw_response = json.loads(load_mock_response("get_pylum_id_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = get_pylum_id(client, "test_machine") assert command_output == "PYLUMCLIENT_INTEGRATION_DESKTOP-VG9KE2U_0800273ADC2F" mocker.patch("Cybereason.Client.cybereason_api_call", return_value=test_reponse) with pytest.raises(Exception) as exc_info: command_output = get_pylum_id(client, "test_machine") assert exc_info.match(r"Could not find machine") def test_get_machine_guid(mocker): from Cybereason import get_machine_guid, Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) raw_response = json.loads(load_mock_response("get_machine_guid_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = get_machine_guid(client, "test_machine") assert command_output == "-1826875736.1198775089551518743" def test_get_machine_details_command(mocker): from Cybereason import get_machine_details_command from Cybereason import Client HEADERS = {"Content-Type": "application/json", "Connection": "close"} client = Client(base_url="https://test.server.com:8888", verify=False, headers=HEADERS, proxy=True) args = {"machineName": "empow_2"} raw_response = json.loads(load_mock_response("fetch_machine_details_raw_response.json")) mocker.patch("Cybereason.Client.cybereason_api_call", return_value=raw_response) command_output = get_machine_details_command(client, args) assert command_output.outputs[0]["GroupName"] == "Test" assert command_output.outputs[0]["MachineName"] == "empow_2"