carbonblack-v2 Deprecated
Deprecated. Use VMware Carbon Black EDR v2 instead.
Endpoint · Carbon Black Enterprise Response
Details
| ID | carbonblack-v2 |
|---|---|
| Provider | Broadcom |
| Category | Endpoint |
| From Version | 5.0.0 |
| Docker Image | demisto/python:2.7.18.8715 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
Deprecated. Use VMware Carbon Black EDR v2 instead.
Query and response with Carbon Black endpoint detection and response.
This integration was integrated and tested with version 6.2.0 of Carbon Black Response
Configure carbonblack-v2 in Cortex
| Parameter | Required |
|---|---|
| Server URL | True |
| API Token | True |
| Trust any certificate (not secure) | False |
| Use system proxy settings | False |
| Fetch incidents | False |
| Incident type | False |
| Fetch Alert Severity Threshold Higher Than | False |
| Maximum Number Of Incidents To Fetch | False |
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.
cb-alert
Retrieve alerts from Carbon Black Response.
Base Command
cb-alert
Input
| Argument Name | Description | Required |
|---|---|---|
| status | Alert status to filter by. Possible values are: Unresolved, In Progress, Resolved, False Positive. | Optional |
| username | Alert username to filter by. | Optional |
| feedname | Alert feedname to filter by. | Optional |
| hostname | Alert hostname to filter by. | Optional |
| report | Alert report name (watchlist_id) to filter by. | Optional |
| query | Query string. Accepts the same data as the search box on the Binary Search page. See https://github.com/carbonblack/cbapi/blob/master/client_apis/docs/query_overview.pdf. | Optional |
| rows | Return this many rows, 10 by default. | Optional |
| start | Start at this row, 0 by default. | Optional |
| sort | Sort rows by this field and order. server_added_timestamp desc by default. | Optional |
| facet | Return facet results. ‘false’ by default, set to ‘true’ for facets. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CbResponse.Alerts.CbAlertID | unknown | Alert unique id |
| CbResponse.Alerts.ProcessPath | string | Alert Process Path |
| CbResponse.Alerts.Hostname | string | Alert Hostname |
| CbResponse.Alerts.InterfaceIP | string | Alert interface IP |
| CbResponse.Alerts.CommsIP | string | Communications IP |
| CbResponse.Alerts.MD5 | string | Alert process MD5 |
| CbResponse.Alerts.Description | unknown | Alert description |
| CbResponse.Alerts.FeedName | unknown | Alert feed name |
| CbResponse.Alerts.Severity | unknown | Alert severity |
| CbResponse.Alerts.Time | unknown | Alert created time |
| CbResponse.Alerts.Status | unknown | Alert status. One of: Unresolved, Resolved, False Positive |
Command Example
#### Human Readable Output
### cb-binary
***
Query for binaries based on given parameters
#### Base Command
`cb-binary`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| digital-signature | Whether digital signature is signed or not. Possible values are: Signed, Unsigned. | Optional |
| publisher | Filter binary by publisher. | Optional |
| company-name | Filter binary by company name. | Optional |
| product-name | Filter binary by product name. | Optional |
| filepath | Filter binary by file path. | Optional |
| group | Filter binary by group. | Optional |
| hostname | Filter binary by hostname. | Optional |
| query | Query string. Accepts the same data as the search box on the Binary Search page. See https://github.com/carbonblack/cbapi/blob/master/client_apis/docs/query_overview.pdf. | Optional |
| rows | Return this many rows, 10 by default. | Optional |
| start | Start at this row, 0 by default. | Optional |
| sort | Sort rows by this field and order. server_added_timestamp desc by default. | Optional |
| facet | Return facet results. 'false' by default, set to 'true' for facets. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| File.DigSig.Publisher | unknown | The publisher of the Digital Signature |
| File.InternalName | unknown | The Internal Name |
| File.ServerAddedTimestamp | unknown | The server added timestamp |
| File.Name | unknown | Binary Name |
| File.Extension | unknown | Binary Extension |
| File.Timestamp | unknown | Binary Timestamp |
| File.Hostname | unknown | Binary Hostname |
| File.Description | unknown | The description |
| File.DigSig.Result | unknown | Cb's decision after checking this binary's Digital Signature |
| File.LastSeen | unknown | Last time binary was seen |
| File.Path | unknown | Binary Path |
| File.ProductName | unknown | The Product Name |
| File.OS | unknown | The OS |
| File.MD5 | unknown | Binary MD5 |
| File.Company | string | Name of the company that released a binary |
| File.DigitalSignature.Publisher | string | Publisher of the digital signature for the file. |
| File.Name | string | Full Filename e.g. data.xls. |
| File.Signature.OriginalName | string | File's original name. |
| File.Signature.InternalName | string | File's internal name. |
| File.Signature.FileVersion | string | File version. |
| File.Signature.Description | string | Description of the signature. |
#### Command Example
Human Readable Output
cb-block-hash
Blocking hash
Base Command
cb-block-hash
Input
| Argument Name | Description | Required |
|---|---|---|
| md5hash | the blacklisted hash. | Required |
| text | text description of block list. | Required |
| lastBanTime | the last time the hash was blocked or prevented from being executed. | Optional |
| banCount | total number of blocks on this block list. | Optional |
| lastBanHost | last hostname to block this hash. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| File.LastAction | unknown | Last action taken on this file |
Command Example
#### Human Readable Output
### cb-get-hash-blacklist
***
Returns a list of hashes on block list, with each list entry describing one hash on block list.
#### Base Command
`cb-get-hash-blacklist`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| filter | OPTIONAL filters blacklist by fields. Example: filter="md5hash == put_your_hash_here". | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| CbResponse.BlockedHashes.MD5 | unknown | Blocked MD5 |
| CbResponse.BlockedHashes.Enabled | unknown | Is Enabled |
| CbResponse.BlockedHashes.Description | unknown | Blocked Description |
| CbResponse.BlockedHashes.Timestamp | unknown | Blocked Timestamp |
| CbResponse.BlockedHashes.BlockCount | unknown | Blocked Count |
| CbResponse.BlockedHashes.Username | unknown | Blocked hash username |
| CbResponse.BlockedHashes.LastBlock.Time | unknown | Last block time |
| CbResponse.BlockedHashes.LastBlock.Hostname | unknown | Last block hostname |
| CbResponse.BlockedHashes.LastBlock.CbSensorID | unknown | Last block sensor ID |
#### Command Example
Human Readable Output
cb-get-process
Gets basic process information for segment (segment_id) of process (process_id)
Base Command
cb-get-process
Input
| Argument Name | Description | Required |
|---|---|---|
| pid | the internal CB process id; this is the id field in search results. | Required |
| segid | the process segment id, the segment_id field in search results. | Required |
| get_related | If set to true, will get process siblings, parent and children. Possible values are: false, true. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Process.Siblings.MD5 | unknown | The sibling Process MD5 |
| Process.CbSegmentID | unknown | Cb ‘segment’ where this process instance is stored. Required to fetch further info on a process. |
| Process.Parent.MD5 | unknown | The parent Process MD5 |
| Process.Children.CommandLine | unknown | The children Process CommandLine |
| Process.Hostname | unknown | Process Hostname |
| Process.Parent.CbSegmentID | unknown | The parent Cb ‘segment’ where this process instance is stored. Required to fetch further info on a process. |
| Process.CbID | unknown | Cb unique ID for this process instance - required (together with CbSegmentID) to fetch further info on a process. |
| Process.Siblings.CbSegmentID | unknown | The sibling Cb ‘segment’ where this process instance is stored. Required to fetch further info on a process. |
| Process.Children.Name | unknown | The children Process Name |
| Process.Parent.Name | unknown | The parent Process Name |
| Process.Siblings.Hostname | unknown | The sibling Process Hostname |
| Process.Parent.Path | unknown | The parent Process Path |
| Process.Children.Hostname | unknown | The children Process Hostname |
| Process.PID | unknown | Process PID |
| Process.Children.CbSegmentID | unknown | The children Cb ‘segment’ where this process instance is stored. Required to fetch further info on a process. |
| Process.Children.CbID | unknown | The children Cb unique ID for this process instance - required (together with CbSegmentID) to fetch further info on a process. |
| Process.Path | unknown | Process Path |
| Process.Parent.PID | unknown | The parent Process PID |
| Process.Children.Path | unknown | The children Process Path |
| Process.Name | unknown | Process Name |
| Process.Children.PID | unknown | The children Process PID |
| Process.Parent.CbID | unknown | The parent Cb unique ID for this process instance - required (together with CbSegmentID) to fetch further info on a process. |
| Process.CommandLine | unknown | Process CommandLine |
| Process.Siblings.CommandLine | unknown | The sibling Process CommandLine |
| Process.Siblings.Name | unknown | The sibling Process Name |
| Process.Parent.CommandLine | unknown | The parent Process CommandLine |
| Process.Parent.Hostname | unknown | The parent Process Hostname |
| Process.MD5 | unknown | Process MD5 |
| Process.Children.MD5 | unknown | The children Process MD5 |
| Process.Siblings.CbID | unknown | The sibling Cb unique ID for this process instance - required (together with CbSegmentID) to fetch further info on a process. |
| Process.Siblings.Path | unknown | The sibling Process Path |
| Process.Siblings.PID | unknown | The sibling Process PID |
| Process.StartTime | date | Start time of the process. |
Command Example
#### Human Readable Output
### cb-get-processes
***
Query processes based on given parameters
#### Base Command
`cb-get-processes`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| name | Filter processes by name. | Optional |
| group | Filter processes by group. | Optional |
| hostname | Filter processes by hostname. | Optional |
| parent-process-name | Filter processes by parent process name. | Optional |
| process-path | Filter processes by process path (Example: "c:\windows\resources\spoolsv.exe"). | Optional |
| md5 | Filter processes by md5 hash. | Optional |
| query | Query string. Accepts the same data as the search box on the Binary Search page. See https://github.com/carbonblack/cbapi/blob/master/client_apis/docs/query_overview.pdf. | Optional |
| rows | Return this many rows, 10 by default. | Optional |
| start | Start at this row, 0 by default. | Optional |
| sort | Sort rows by this field and order. server_added_timestamp desc by default. | Optional |
| facet | Return facet results. 'false' by default, set to 'true' for facets. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| File.Name | unknown | File Name |
| File.MD5 | unknown | File MD5 |
| File.Path | unknown | File Path |
| Endpoint.Hostname | unknown | Endpoint Hostname |
| Process.CommandLine | unknown | Process Commandline |
| Process.PID | unknown | Process PID |
| Process.CbID | unknown | Cb unique ID for this process instance - required \(together with CbSegmentID\) to fetch further info on a process. |
| Process.CbSegmentId | unknown | Cb "segment" where this process instance is stored. Required to fetch further info on a process. |
| Process.Parent.PID | unknown | Process Parent PID |
| Process.Parent.Name | unknown | Process Parent Name |
| Process.StartTime | date | Start time of the process. |
#### Command Example
Human Readable Output
cb-list-sensors
List the CarbonBlack sensors
Base Command
cb-list-sensors
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | The maximum amount of sensors to be returned. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CbResponse.Sensors.Status | unknown | Sensor Status |
| CbResponse.Sensors.LastUpdate | unknown | Sensor Last Updated |
| CbResponse.Sensors.Uptime | unknown | The Sensor uptime |
| CbResponse.Sensors.SupportsCbLive | unknown | Sensor Support CB Live |
| CbResponse.Sensors.Notes | unknown | Sensor Notes |
| CbResponse.Sensors.Hostname | unknown | Hostname |
| CbResponse.Sensors.CbSensorID | unknown | Sensor ID |
| CbResponse.Sensors.Isolated | unknown | Sensor Isolated |
| CbResponse.Sensors.IPAddresses | unknown | Sensor IP Addresses |
| CbResponse.Sensors.OS | unknown | Sensor OS |
| Endpoint.Hostname | unknown | Sensor Hostname |
| Endpoint.OS | unknown | Sensor OS |
| Endpoint.IPAddresses | unknown | Sensor IP Addresses |
Command Example
#### Human Readable Output
### cb-process-events
***
Retrieve all process events for a given process segmented by segment ID
#### Base Command
`cb-process-events`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| pid | the internal CB process id; this is the id field in search results. | Required |
| segid | the process segment id; this is the segment_id field in search results. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Process.CrossProc.OtherProcessMD5 | unknown | Other process MD5 |
| Process.MD5 | unknown | Process MD5 |
| Process.Modules.MD5 | unknown | Module MD5 |
| Process.CommandLine | unknown | Process CommandLine |
| Process.Registry.RegistryPath | unknown | Registry path |
| Process.Path | unknown | Process Path |
| Process.CbID | unknown | Cb unique ID for this process instance - required \(together with CbSegmentID\) to fetch further info on a process. |
| Process.Parent.Name | unknown | The parent Process Name |
| Process.Hostname | unknown | Process Hostname |
| Process.Binaries.DigSig.Publisher | unknown | The publisher of the Digital Signature |
| Process.CrossProc.Action | unknown | Cross process action |
| Process.CrossProc.OtherProcessCbID | unknown | Other process CbID |
| Process.CbSegmentID | unknown | Cb 'segment' where this process instance is stored. Required to fetch further info on a process. |
| Process.Name | unknown | Process Name |
| Process.CrossProc.Time | unknown | Time of action |
| Process.PID | unknown | Process PID |
| Process.Modules.Filepath | unknown | Module path |
| Process.Binaries.DigSig.Result | unknown | Cb's decision after checking this binary's Digital Signature |
| Process.Parent.PID | unknown | The parent Process PID |
| Process.Binaries.MD5 | unknown | Binary MD5 |
| Process.CrossProc.OtherProcessBinary | unknown | Other process binary |
| Process.Registry.Time | unknown | Registry time |
| Process.Modules.Time | unknown | Module time |
#### Command Example
Human Readable Output
cb-quarantine-device
Isolate the endpoint from the network
Base Command
cb-quarantine-device
Input
| Argument Name | Description | Required |
|---|---|---|
| sensor | the sensor ID to quarantine. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Endpoint.LastAction | unknown | Endpoint Actions |
Command Example
#### Human Readable Output
### cb-sensor-info
***
Display information about the given sensor
#### Base Command
`cb-sensor-info`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| sensor | the sensor id. | Optional |
| ip | returns the sensor registration(s) with specified IP address. | Optional |
| hostname | returns the sensor registration(s) with matching hostname. | Optional |
| groupid | returns the sensor registration(s) in the specified sensor group id. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| CbResponse.Sensors.Status | unknown | Sensor Status |
| CbResponse.Sensors.LastUpdate | unknown | Sensor Last Updated |
| CbResponse.Sensors.Uptime | unknown | The Sensor uptime |
| CbResponse.Sensors.SupportsCbLive | unknown | Sensor Support CB Live |
| CbResponse.Sensors.Notes | unknown | Sensor Notes |
| CbResponse.Sensors.Hostname | unknown | Sensor Hostname |
| CbResponse.Sensors.CbSensorID | unknown | Sensor ID |
| CbResponse.Sensors.Isolated | unknown | Sensor Isolated |
| CbResponse.Sensors.IPAddresses | unknown | Sensor IP Addresses |
| CbResponse.Sensors.OS | unknown | Sensor OS |
#### Command Example
Human Readable Output
cb-unblock-hash
Unblocking hash
Base Command
cb-unblock-hash
Input
| Argument Name | Description | Required |
|---|---|---|
| md5hash | the hash on the block list. | Required |
| text | text description of block list. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| File.LastAction | unknown | Last action taken on this file |
Command Example
#### Human Readable Output
### cb-unquarantine-device
***
Unquarantine the endpoint
#### Base Command
`cb-unquarantine-device`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| sensor | the sensor ID to quarantine. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| Endpoint.LastAction | unknown | Endpoint Actions |
#### Command Example
Human Readable Output
cb-version
Display the CarbonBlack version
Base Command
cb-version
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
There is no context output for this command.
Command Example
#### Human Readable Output
### cb-watchlist-del
***
Delete a watchlist in Carbon black Response.
#### Base Command
`cb-watchlist-del`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| watchlist-id | Watchlist ID. | Required |
#### Context Output
There is no context output for this command.
#### Command Example
Human Readable Output
cb-watchlist-get
Retrieve info for a watchlist in Carbon black Response.
Base Command
cb-watchlist-get
Input
| Argument Name | Description | Required |
|---|---|---|
| watchlist-id | Watchlist ID. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CbResponse.Watchlists.LastHit | unknown | Watchlist last hit |
| CbResponse.Watchlists.TotalHits | unknown | Watchlist Total hits |
| CbResponse.Watchlists.SearchQuery | unknown | Cb search query used for the watchlist. |
| CbResponse.Watchlists.Name | unknown | Watchlist Name |
| CbResponse.Watchlists.Enabled | unknown | Watchlist is enabled |
| CbResponse.Watchlists.LastHitCount | unknown | Watchlist last hit count |
| CbResponse.Watchlists.DateAdded | unknown | Watchlist Date added |
| CbResponse.Watchlists.SearchTimestamp | unknown | Watchlist last hit count |
| CbResponse.Watchlists.CbWatchlistID | unknown | Watchlist ID |
Command Example
#### Human Readable Output
### cb-watchlist-new
***
Create a new watchlist in Carbon black Response.
#### Base Command
`cb-watchlist-new`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| search-query | the raw Carbon Black query that this watchlist matches. | Required |
| name | name of this watchlist. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| CbResponse.Watchlists.LastHit | unknown | Watchlist last hit |
| CbResponse.Watchlists.TotalHits | unknown | Watchlist Total hits |
| CbResponse.Watchlists.SearchQuery | unknown | Cb search query used for the watchlist. |
| CbResponse.Watchlists.Name | unknown | Watchlist Name |
| CbResponse.Watchlists.Enabled | unknown | Watchlist is enabled |
| CbResponse.Watchlists.LastHitCount | unknown | Watchlist last hit count |
| CbResponse.Watchlists.DateAdded | unknown | Watchlist Date added |
| CbResponse.Watchlists.SearchTimestamp | unknown | Watchlist last hit count |
| CbResponse.Watchlists.CbWatchlistID | unknown | Watchlist ID |
#### Command Example
Human Readable Output
cb-watchlist-set
Modify a watchlist in Carbon black Response.
Base Command
cb-watchlist-set
Input
| Argument Name | Description | Required |
|---|---|---|
| watchlist-id | Watchlist ID. | Required |
| search-query | the raw Carbon Black query that this watchlist matches. | Optional |
| name | name of this watchlist. | Optional |
| indexType | the type of watchlist. Valid values are ‘modules’ and ‘events’ for binary and process watchlists, respectively. | Optional |
Context Output
There is no context output for this command.
Command Example
#### Human Readable Output
### cb-alert-update
***
Alert update and resolution
#### Base Command
`cb-alert-update`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| uniqueId | Alert unique identifier. | Required |
| status | Updated alert's status: Resolved,Unresolved,In Progress or False Positive. Possible values are: Resolved, Unresolved, In Progress, False Positive. | Required |
| setIgnored | Whether to stop showing this type of alert. Possible values are: true, false. | Optional |
#### Context Output
There is no context output for this command.
#### Command Example
Human Readable Output
cb-watchlist
Retrieve watchlist in Carbon black Response.
Base Command
cb-watchlist
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| CbResponse.Watchlists.LastHit | unknown | Watchlist last hit |
| CbResponse.Watchlists.TotalHits | unknown | Watchlist Total hits |
| CbResponse.Watchlists.SearchQuery | unknown | Cb search query used for the watchlist. |
| CbResponse.Watchlists.Name | unknown | Watchlist Name |
| CbResponse.Watchlists.Enabled | unknown | Watchlist is enabled |
| CbResponse.Watchlists.LastHitCount | unknown | Watchlist last hit count |
| CbResponse.Watchlists.DateAdded | unknown | Watchlist Date added |
| CbResponse.Watchlists.SearchTimestamp | unknown | Watchlist last hit count |
| CbResponse.Watchlists.CbWatchlistID | unknown | Watchlist ID |
Command Example
#### Human Readable Output
### cb-binary-download
***
Retrieve a binary from CarbonBlack based on hash. Returns a .zip file containing the requested file and it's metadata.
#### Base Command
`cb-binary-download`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| md5 | MD5 hash of the file. | Required |
| summary | Whether to include the summary. Possible values are: yes, no. | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| File.DigSig.Publisher | unknown | The publisher of the digital signature. |
| File.InternalName | unknown | The internal name. |
| File.ServerAddedTimestamp | unknown | The timestamp when the server was added. |
| File.Name | unknown | The binary name. |
| File.Extension | unknown | The binary extension. |
| File.Timestamp | unknown | The binary timestamp. |
| File.Hostname | unknown | The binary hostname. |
| File.Description | unknown | The binary description. |
| File.DigSig.Result | unknown | The Carbon Black decision after checking this binary's digital signature. |
| File.LastSeen | unknown | LThe lst time the binary was seen. |
| File.Path | unknown | The binary path. |
| File.ProductName | unknown | The product name. |
| File.OS | unknown | The OS. |
| File.MD5 | unknown | The MD5 hash of the binary. |
| File.Company | unknown | Name of the company that released a binary. |
| File.DigitalSignature.Publisher | unknown | Publisher of the digital signature for the file. |
| File.Name | unknown | Full filename, for example data.xls. |
| File.Signature.OriginalName | unknown | The file's original name. |
| File.Signature.InternalName | unknown | The file's internal name. |
| File.Signature.FileVersion | unknown | The file version. |
| File.Signature.Description | unknown | The description of the signature. |
#### Command Example
Human Readable Output
Configuration parameters
serverurl— Server URL (required)apitoken— API Token (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsisFetch— Fetch incidentsincidentType— Incident typefetchAlertsSeverityThreshold— Fetch Alert Severity Threshold Higher Thanrows— Maximum Number Of Incidents To Fetch
Commands (21)
-
cb-alertRetrieve alerts from Carbon Black Response.
-
cb-alert-updateAlert update and resolution
-
cb-binaryQuery for binaries based on given parameters
-
cb-binary-downloadRetrieve a binary from CarbonBlack based on hash. Returns a .zip file containing the requested file and it's metadata.
-
cb-binary-getDeprecatedDeprecated. Use the cb-binary-download command instead.
-
cb-block-hashBlocking hash
-
cb-get-hash-blacklistReturns a list of hashes on block list, with each list entry describing one hash on block list.
-
cb-get-processGets basic process information for segment (segment_id) of process (process_id)
-
cb-get-processesQuery processes based on given parameters
-
cb-list-sensorsList the CarbonBlack sensors
-
cb-process-eventsRetrieve all process events for a given process segmented by segment ID
-
cb-quarantine-deviceIsolate the endpoint from the network
-
cb-sensor-infoDisplay information about the given sensor
-
cb-unblock-hashUnblocking hash
-
cb-unquarantine-deviceUnquarantine the endpoint
-
cb-versionDisplay the CarbonBlack version
-
cb-watchlistRetrieve watchlist in Carbon black Response.
-
cb-watchlist-delDelete a watchlist in Carbon black Response.
-
cb-watchlist-getRetrieve info for a watchlist in Carbon black Response.
-
cb-watchlist-newCreate a new watchlist in Carbon black Response.
-
cb-watchlist-setModify a watchlist in Carbon black Response.
"use strict"; /// Base Functions function sendRequest(path, method, requestParams, headers, ignoredStatusCodes) { let baseUrl = params.serverurl + '/api'; if (!headers) { headers = {}; } if (!headers['X-Auth-Token']) { headers['X-Auth-Token'] = [params.apitoken]; } if (!headers['Accept']) { headers['Accept'] = ['application/json']; } if (!headers['Content-Type']) { headers['Content-Type'] = ['application/json']; } let request = { Method: method, Headers: headers }; let querystring = ''; if (requestParams) { if (typeof requestParams === 'string') { querystring = requestParams; } else { request.Body = JSON.stringify(requestParams); } } //logInfo("Request:\n" + JSON.stringify({path: path + querystring, req: request})); let result = http(baseUrl + path + querystring, request, params.insecure, params.proxy); if (!ignoredStatusCodes || ignoredStatusCodes.indexOf(result.StatusCode) === -1) { if (result.StatusCode < 200 || result.StatusCode >= 300) { if (result.StatusCode === 404) { throw 'Cannot find the requested resource (Status Code: 404)'; } throw `Request Failed.\nStatus code: ${result.StatusCode}.\nMessage: ${JSON.stringify(result.Body)}`; } } //logInfo("Body:\n" + result.Body); return result; } /// Commands function testModule() { let res = sendRequest('/v1/license', 'GET'); if (res.StatusCode === 200) { return 'ok'; } return `Test failed. Status Code: ${res.StatusCode}` } function getSensorByIdRequest(sensorId) { let response = sendRequest(`/v1/sensor/${sensorId}`, 'GET'); try { return JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function quarantineSensorRequest(sensorId, sensorDetails) { return sendRequest(`/v1/sensor/${sensorId}`, 'PUT', sensorDetails); } function quarantineDevice(doQuarantine) { let result = getSensorByIdRequest(args.sensor); result.network_isolation_enabled = doQuarantine; var filtered_sensor_object = { 'network_isolation_enabled': result.network_isolation_enabled, 'restart_queued': result.restart_queued, 'uninstall': result.uninstall, 'liveresponse_init': result.liveresponse_init, 'group_id': result.group_id, 'notes': result.notes, 'event_log_flush_time': result.event_log_flush_time } result = quarantineSensorRequest(args.sensor, filtered_sensor_object); if (result.StatusCode === 204) { let quarantinedStr = (doQuarantine) ? 'quarantined' : 'unquarantined'; return { Type: entryTypes.note, Contents: {success: true}, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: "Success: " + quarantinedStr + " sensor " + args.sensor, EntryContext: { "Endpoint(val.CbSensorID == obj.CbSensorID)": { "CbSensorID": args.sensor, "LastAction": (doQuarantine) ? "Blocked" : "Unblocked" } } } } else { throw result.Body; } } function getAlertsRequest(query, rows, start, sort, facets) { let queryParams = {}; if (query) { queryParams.q = query; } if (rows) { queryParams.rows = rows; } if (start) { queryParams.start = start; } if (sort) { queryParams.sort = sort; } if (facets) { queryParams.facets = facets; } let response = sendRequest('/v2/alert', 'GET', encodeToURLQuery(queryParams)); try { return JSON.parse(response.Body).results; } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function fetchIncidents() { let lastRun = getLastRun(); let fetchAlertsSeverityThreshold = (args['fetchAlertsSeverityThreshold']) ? args['fetchAlertsSeverityThreshold'] : 0; let defaultRunTime = (new Date().getTime()) - (24 * 60 * 60 * 1000); // Decrease one day if it's the first run, to get some alerts. let defaultRunTimeStr = unixToString(defaultRunTime); let lastRunStr = (lastRun.time) ? unixToString(lastRun.time + 1000) : defaultRunTimeStr; let result = getAlertsRequest(`alert_severity:[${fetchAlertsSeverityThreshold} TO *] and created_time:[${lastRunStr} TO *]`, params.rows); let latestTime = 0; let incidents = result.map(curAlert => { let createdTime = stringToUnix(curAlert['created_time']); latestTime = Math.max(latestTime, createdTime); // Save latest time from current fetch to query return { name: curAlert['description'] + ' : ' + curAlert['created_time'], occurred: curAlert['created_time'], rawJSON: JSON.stringify(curAlert), }; }); if (incidents.length > 0) { logInfo('Ingested ' + incidents.length + ' alerts into incidents'); setLastRun({'time': latestTime}); // Update last run } return JSON.stringify(incidents); } function version() { let response = sendRequest('/v1/builds', 'GET'); let result; try { result = JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } return { Type: entryTypes.note, Contents: result, ContentsType: formats.json }; } function showAlerts() { let query = ''; if (args.query) { query = '(' + args.query + ')'; } if (args.status) { query += ' AND status:' + args.status; } if (args.username) { query += ' AND username:' + args.username; } if (args.hostname) { query += ' AND hostname:' + args.hostname; } if (args.feedname) { query += ' AND feed_name:' + args.feedname; } if (args.report) { query += ' AND watchlist_id:' + args.report; } let alerts = getAlertsRequest(query, args.rows, args.start, args.sort, args.facets); let title = 'CB Response - Show Alerts'; let changeNames = [ {from: 'unique_id', to: 'CbAlertID'}, {from: 'process_path', to: 'ProcessPath'}, {from: 'hostname', to: 'Hostname'}, {from: 'interface_ip', to: 'InterfaceIP'}, {from: 'comms_ip', to: 'CommsIP'}, {from: 'md5', to: 'MD5'}, {from: 'description', to: 'Description'}, {from: 'feed_name', to: 'FeedName'}, {from: 'alert_severity', to: 'Severity'}, {from: 'created_time', to: 'Time'}, {from: 'status', to: 'Status'} ]; let headers = changeNames.map(cn => cn.to); let translatedData = mapObjFunction(changeNames)(alerts); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'CbResponse.Alerts(val.CbAlertID==obj.CbAlertID)': createContext(translatedData) }; return { Type: entryTypes.note, Contents: alerts, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context }; } function updateAlertRequest(alertUniqueId, status, setIgnored) { let queryParams = {}; if (alertUniqueId) { queryParams.alert_ids = [alertUniqueId]; } if (status) { queryParams.requested_status = status; } if (setIgnored) { queryParams.set_ignored = setIgnored; } let response = sendRequest('/v1/alerts', 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function updateAlert() { let response = updateAlertRequest(args.uniqueId, args.status, args.setIgnored); if (response.result && response.result === 'success') { return { Type: entryTypes.note, Contents: response, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: 'Alert updated successfully' } } else { throw `Command failed.\nOutput: ${JSON.stringify(response)}`; } } const processData = [ {from: 'process_name', to: 'Name'}, {from: 'hostname', to: 'Endpoint'}, {from: 'last_update', to: 'Update'}, {from: 'start', to: 'Start Time'}, {from: 'process_pid', to: 'PID'}, {from: 'username', to: 'Username'}, {from: 'process_md5', to: 'MD5'}, {from: 'cmdline', to: 'CommandLine'}, {from: 'path', to: 'Path'}, {from: 'id', to: 'CbID'}, {from: 'segment_id', to: 'CbSegmentID'}, {from: 'group', to: 'Group'}, {from: 'start', to: 'StartTime'} ]; const processDataForFileContext = [ {from: 'process_name', to: 'Name'}, {from: 'process_md5', to: 'MD5'}, {from: 'path', to: 'Path'} ]; const processDataForEndpointContext = [ {from: 'hostname', to: 'Hostname'} ]; function getProcessesRequest(query, rows, start, sort, facets) { let queryParams = {}; if (query) { queryParams.q = query; } if (rows) { queryParams.rows = rows; } if (start) { queryParams.start = start; } if (sort) { queryParams.sort = sort; } if (facets) { queryParams.facets = facets; } let response = sendRequest('/v1/process', 'GET', encodeToURLQuery(queryParams)); try { return JSON.parse(response.Body).results; } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function getProcesses() { let query = ''; if (args.query) { query = '(' + args.query + ')'; } if (args.name) { query += ' AND process_name:' + args.name } if (args.group) { query += ' AND group:' + args.group; } if (args.hostname) { query += ' AND hostname:' + args.hostname; } if (args['parent-process-name']) { query += ' AND parent_name:' + args['parent-process-name']; } if (args['process-path']) { query += ' AND path:' + args['process-path']; } if (args.md5) { query += ' AND md5:' + args.md5; } let processes = getProcessesRequest(query, args.rows, args.start, args.sort, args.facets); let title = 'CB Response - Get Processes'; let processDataMap = processData; let fileDataMap = processDataForFileContext; let endpointDataMap = processDataForEndpointContext; let headers = processDataMap.map(cn => cn.to); let processTranslatedData = mapObjFunction(processDataMap)(processes); let fileTranslatedData = mapObjFunction(fileDataMap)(processes); let endpointTranslatedData = mapObjFunction(endpointDataMap)(processes); let humanReadable = tableToMarkdown(title, processTranslatedData, headers, undefined, dotToSpace); let context = { 'Process(val.CbID==obj.CbID)': createContext(processTranslatedData), 'File(val.MD5==obj.MD5)': createContext(fileTranslatedData), 'Endpoint(val.Hostname==obj.Hostname)': createContext(endpointTranslatedData) }; return { Type: entryTypes.note, Contents: processes, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }; } function getProcessRequest(processId, segmentId) { let response = sendRequest(`/v2/process/${processId}/${segmentId}`, 'GET'); try { return JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function getFullProcessRequest(processId, segmentId) { let response = sendRequest(`/v1/process/${processId}/${segmentId}`, 'GET'); try { return JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function getProcess() { let entries = []; let title = 'CB Response - Process'; let dataMap = processData; let headers = dataMap.map(cn => cn.to); let result; let processTranslatedData; let context; if (args.get_related === 'true') { result = getFullProcessRequest(args.pid, args.segid) processTranslatedData = mapObjFunction(dataMap)(result.process); let parentProcessTranslatedData = mapObjFunction(dataMap)(result.parent); let siblingsProcessTranslatedData = []; for (var i = 0; i < result.siblings.length; i++) { siblingsProcessTranslatedData.push(mapObjFunction(dataMap)(result.siblings[i])); } let childrenProcessTranslatedData = [] for (var i = 0; i < result.children.length; i++) { childrenProcessTranslatedData.push(mapObjFunction(dataMap)(result.children[i])); } context = processTranslatedData; context.Siblings = siblingsProcessTranslatedData context.Parent = parentProcessTranslatedData context.Children = childrenProcessTranslatedData } else { result = getProcessRequest(args.pid, args.segid); processTranslatedData = mapObjFunction(dataMap)(result); context = processTranslatedData; } let humanReadable = tableToMarkdown(title, processTranslatedData, headers, undefined, dotToSpace); entries.push({ Type: entryTypes.note, Contents: result.process, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable }); entries[0].EntryContext = { 'Process(val.CbID==obj.CbID)': createContext(context) }; return entries; } function getProcessEventsRequest(processId, segmentId) { let response = sendRequest(`/v1/process/${processId}/${segmentId}/event`, 'GET'); try { return JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function getProcessEvents() { let result = getProcessEventsRequest(args.pid, args.segid); let entries = []; let title = 'CB Response - Process Event'; let dataMap = processData; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result.process); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let contextData = translatedData; entries.push({ Type: entryTypes.note, Contents: result.process, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable }); title = 'Cross Process'; let crossProcDataMap = [ {to: 'Action', from: ".=(val.split('|')[0])"}, {to: 'Time', from: ".=(val.split('|')[1])"}, {to: 'OtherProcessCbID', from: ".=(val.split('|')[2])"}, {to: 'OtherProcessMD5', from: ".=(val.split('|')[3])"}, {to: 'OtherProcessBinary', from: ".=(val.split('|')[4])"} ]; headers = crossProcDataMap.map(cn => cn.to); translatedData = []; if ('process' in result) { if (result.process.crossproc_complete) { translatedData = mapObjFunction(crossProcDataMap)(result.process.crossproc_complete); } } humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); contextData['CrossProc'] = translatedData; entries.push({ Type: entryTypes.note, Contents: result.process.crossproc_complete, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable }); title = 'Modules'; let modulesDataMap = [ {to: 'Time', from: ".=(val.split('|')[0])"}, {to: 'MD5', from: ".=(val.split('|')[1])"}, {to: 'Filepath', from: ".=(val.split('|')[2])"} ]; headers = modulesDataMap.map(cn => cn.to); let modulesResult = dq(result, 'process.modload_complete(val.MD5==obj.MD5)'); translatedData = mapObjFunction(modulesDataMap)(modulesResult); humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); contextData['Modules'] = translatedData; entries.push({ Type: entryTypes.note, Contents: modulesResult, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable }); title = 'Registry'; let registryDataMap = [ {to: 'Time', from: ".=(val.split('|')[1])"}, {to: 'RegistryPath', from: ".=(val.split('|')[2])"} ]; headers = registryDataMap.map(cn => cn.to); translatedData = []; if ('process' in result) { if (result.process.regmod_complete) { translatedData = mapObjFunction(registryDataMap)(result.process.regmod_complete); } } humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); contextData['Registry'] = translatedData; entries.push({ Type: entryTypes.note, Contents: result.process.regmod_complete, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable }); title = 'Binaries'; headers = ['MD5', 'Publisher', 'Result']; translatedData = []; if ('process' in result) { if (result.process.binaries) { let keys = Object.keys(result.process.binaries); translatedData = keys.map(md5 => ({ 'MD5': md5, 'Publisher': result.process.binaries[md5]['digsig_publisher'], 'Result': result.process.binaries[md5]['digsig_result'] })); } } humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); contextData['Binaries'] = translatedData.map(binary => ({ 'MD5': binary.MD5, 'DigSig.Publisher': binary['Publisher'], 'DigSig.Result': binary['Result'] })); entries.push({ Type: entryTypes.note, Contents: result.process.binaries, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable }); entries[0].EntryContext = { 'Process(val.CbID==obj.CbID)': createContext(contextData) }; return entries; } const binaryData = [ {to: 'Name', from: 'original_filename'}, {to: 'MD5', from: 'md5'}, {to: 'Timestamp', from: 'timestamp'}, { to: 'Extension', from: '.=(val.original_filename.indexOf(".")>=0 ? val.original_filename.split(".")[1] : "")' }, {to: 'Hostname', from: "endpoint"}, {to: 'Path', from: 'observed_filename'}, {to: 'LastSeen', from: 'last_seen'}, {to: 'ServerAddedTimestamp', from: 'server_added_timestamp'}, {to: 'Description', from: 'file_desc'}, {to: 'InternalName', from: 'internal_name'}, {to: 'ProductName', from: 'product_name'}, {to: 'OS', from: 'os_type'}, {to: 'DigSig.Result', from: 'digsig_result'}, {to: 'DigSig.Publisher', from: 'digsig_publisher'}, {to: 'Company', from: 'company_name'}, {to: 'DigitalSignature.Publisher', from: 'digsig_publisher'}, {to: 'Name', from: 'original_filename'}, {to: 'Signature.OriginalName', from: 'original_filename'}, {to: 'Signature.InternalName', from: 'internal_name'}, {to: 'Signature.FileVersion', from: 'file_version'}, {to: 'Signature.Description', from: 'file_desc'} ]; function getBinariesRequest(query, rows, start, sort, facets) { let queryParams = {}; if (query) { queryParams.q = query; } if (rows) { queryParams.rows = rows; } if (start) { queryParams.start = start; } if (sort) { queryParams.sort = sort; } if (facets) { queryParams.facets = facets; } let response = sendRequest('/v1/binary', 'GET', encodeToURLQuery(queryParams)); try { return JSON.parse(response.Body).results; } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function getBinaries() { let query = ''; if (args.query) { query = '(' + args.query + ')'; } if (args['digital-signature']) { query += ' AND digsig_result:' + args['digital-signature']; } if (args['publisher']) { query += ' AND digsig_publisher:' + args['publisher']; } if (args['company-name']) { query += ' AND company_name:' + args['company-name']; } if (args['product-name']) { query += ` AND product_name: "${args['product-name']}"`; } if (args['filepath']) { query += ` AND observed_filename:"${args['filepath']}"`; } if (args['group']) { query += ` AND group:"${args['group']}"` } if (args['hostname']) { query += ` AND hostname:"${args['hostname']}"` } let result = getBinariesRequest(query, args.rows, args.start, args.sort, args.facets); let title = 'CB Response - Get Binaries'; let dataMap = binaryData; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result); // format results - "|" char disturbing markdown representation for (let i = 0; i < translatedData.length; i++) { let data = translatedData[i]; if (data['Hostname']) { translatedData[i]['Hostname'] = data['Hostname'].join().replace(/\|/gi," "); } } let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'File(val.MD5==obj.MD5)': createContext(translatedData) }; return { Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }; } function getBinarySummaryRequest(md5) { let response = sendRequest('/v1/binary/' + md5 + '/summary', 'GET'); try { return JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function getBinaryRequest(md5) { return sendRequest('/v1/binary/' + md5, 'GET'); } function getBinary() { let entries = []; if (args.summary && args.summary === 'yes') { let result = getBinarySummaryRequest(args.md5); let title = 'CB Response - Binary Summary'; let dataMap = binaryData; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'File(val.MD5==obj.MD5)': createContext(translatedData) }; entries.push({ Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }); } let res = getBinaryRequest(args.md5); let fileEntryId = saveFile(res.Bytes); if (args.decompress && args.decompress === 'no') { return { Type: entryTypes.file, FileID: fileEntryId, File: 'results.zip', Contents: "" }; } else { let fileEntries = decompressFile(fileEntryId); fileEntries.forEach(fileEntry => { entries.push({ Type: fileEntry.Type, FileID: fileEntry.FileID, File: fileEntry.File, Contents: '' }); }); } return entries; } function getBinaryZip() { let entries = []; if (args.summary && args.summary === 'yes') { let result = getBinarySummaryRequest(args.md5); let title = 'CB Response - Binary Summary'; let dataMap = binaryData; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'File(val.MD5==obj.MD5)': createContext(translatedData) }; entries.push({ Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }); } let res = getBinaryRequest(args.md5); let fileEntryId = saveFile(res.Bytes); return { Type: entryTypes.file, FileID: fileEntryId, File: 'results.zip', Contents: "" }; } function getSensorsRequest(sensorId, hostname, ip, groupId) { let queryParams = {}; if (hostname) { queryParams.hostname = hostname; } if (ip) { queryParams.ip = ip; } if (groupId) { queryParams.groupid = groupId; } let path = '/v1/sensor'; if (sensorId) { path += '/' + sensorId; } let response = sendRequest(path, 'GET', encodeToURLQuery(queryParams)).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function getSensors() { let ipAddressDQ = '.=(val.network_adapters.split("|").slice(0, val.network_adapters.split("|").length-1))'; let result = getSensorsRequest(args.sensor, args.hostname, args.ip, args.groupid); if (args.limit) { args.limit = parseInt(args.limit); result.splice(args.limit, result.length - args.limit); } let entries = []; let title = 'CB Response - Get Sensors'; let dataMap = [ {to: 'CbSensorID', from: 'id'}, {to: 'Hostname', from: 'computer_name'}, {to: 'Status', from: 'status'}, {to: 'IPAddresses', from: ipAddressDQ}, {to: 'IPAddress', from: 'network_adapters'}, {to: 'Notes', from: 'notes'}, {to: 'Isolated', from: 'is_isolating'}, {to: 'OS', from: 'os_environment_display_string'}, {to: 'Uptime', from: 'sensor_uptime'}, {to: 'LastUpdate', from: 'last_update'}, {to: 'SupportsCbLive', from: 'supports_cblr'} ]; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'CbResponse.Sensors(val.CbSensorID==obj.CbSensorID)': createContext(translatedData) }; entries.push({ Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }); title = 'Endpoints'; dataMap = [ {to: 'Hostname', from: 'computer_name'}, {to: 'OS', from: 'os_environment_display_string'}, {to: 'IPAddresses', from: ipAddressDQ}, {to: 'CbSensorID', from: 'id'}, ]; headers = dataMap.map(cn => cn.to); translatedData = mapObjFunction(dataMap)(result); humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); context = { 'Endpoint': createContext(translatedData) }; entries.push({ Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }); return entries; } function getHashBlacklistRequest(filter) { let queryParams = {}; if (filter) { queryParams.filter = filter; } let response = sendRequest('/v1/banning/blacklist', 'GET', encodeToURLQuery(queryParams)).Body; try { if (response === '') { return []; } else { return JSON.parse(response); } } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function getHashBlacklist() { let result = getHashBlacklistRequest(args.filter); let title = 'CB Response - Hash Blacklist'; let dataMap = [ {to: 'MD5', from: 'md5hash'}, {to: 'Enabled', from: 'enabled'}, {to: 'Description', from: 'text'}, {to: 'Timestamp', from: 'timestamp'}, {to: 'BlockCount', from: 'block_count'}, {to: 'Username', from: 'username'}, {to: 'LastBlock.Time', from: 'last_block_time'}, {to: 'LastBlock.Hostname', from: 'last_block_hostname'}, {to: 'LastBlock.CbSensorID', from: 'last_block_sensor_id'} ]; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'CbResponse.BlockedHashes(val.MD5==obj.MD5)': createContext(translatedData) }; return { Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }; } function blockHashRequest(md5, text, enabled, lastBanTime, banCount, lastBanHost) { let queryParams = {}; if (md5) { queryParams.md5hash = md5; } if (text) { queryParams.text = text; } if (enabled) { queryParams.enabled = enabled; } if (lastBanTime) { queryParams.last_ban_time = lastBanTime; } if (banCount) { queryParams.ban_count = banCount; } if (lastBanHost) { queryParams.last_ban_host = lastBanHost; } let response = sendRequest('/v1/banning/blacklist', 'POST', queryParams); try { return JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function unblockHashRequest(md5, text) { let queryParams = {}; if (text) { queryParams.text = text; } let response = sendRequest(`/v1/banning/blacklist/${md5}`, 'DELETE', queryParams); try { return JSON.parse(response.Body); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response.Body}`; } } function blockHash(doBlock) { let result; if (doBlock) { // Get banning list result = getHashBlacklistRequest(`md5hash==${args.md5hash} && enabled==true`); if (result.length === 0 || isEmpty(result)) { // New hash so create a block result = blockHashRequest(args.md5hash, args.text, true, args.lastBanTime, args.banCount, args.lastBanHost); } else { // Existing hash so just update result = blockHashRequest(result[0].md5hash, result[0].text, true, result[0].lastBanTime, result[0].banCount, result[0].lastBanHost); } } else { result = unblockHashRequest(args.md5hash, args.text); } let blockedStr = (doBlock) ? 'blocked' : 'unblocked'; let entry = { Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: "Failed to " + blockedStr + " " + args.sensor, EntryContext: { "Endpoint(val.CbSensorID == obj.CbSensorID)": { "CbSensorID": args.sensor, "LastAction": (doBlock) ? "Blocked" : "Unblocked" } } }; if (result.result === 'success') { entry.HumanReadable = "Success: " + blockedStr + " " + args['md5hash']; entry.EntryContext = { "File(val.MD5 && val.MD5==obj.MD5)": { "MD5": args['md5hash'], "LastAction": (doBlock) ? "Blocked" : "Unblocked" } }; } return entry; } const watchlistData = [ {to: 'CbWatchlistID', from: 'id'}, {to: 'Name', from: 'name'}, {to: 'SearchQuery', from: 'search_query'}, {to: 'Enabled', from: 'enabled'}, {to: 'LastHit', from: 'last_hit'}, {to: 'LastHitCount', from: 'last_hit_count'}, {to: 'SearchTimestamp', from: 'search_timestamp'}, {to: 'TotalHits', from: 'total_hits'}, {to: 'DateAdded', from: 'date_added'} ]; function getWatchlistRequest(watchlistId) { let path = '/v1/watchlist'; if (watchlistId) { path += '/' + watchlistId; } let response = sendRequest(path, 'GET').Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function getWatchlist() { let result = getWatchlistRequest(args['watchlist-id']); let title = 'CB Response - List Watchlists'; let dataMap = watchlistData; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'CbResponse.Watchlists(val.CbWatchlistID==obj.CbWatchlistID)': createContext(translatedData) }; return { Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }; } function createWatchlistRequest(name, searchQuery, indexType) { let queryParams = {}; if (name) { queryParams.name = name; } if (searchQuery) { queryParams.search_query = searchQuery; } if (indexType) { queryParams.index_type = indexType; } let response = sendRequest(`/v1/watchlist`, 'POST', queryParams).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function createWatchlist() { let result = createWatchlistRequest(args.name, args['search-query'], args.indexType); let title = `CB Response - New Watchlist`; let dataMap = [{to: 'CbWatchlistID', from: 'id'}]; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(result); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'CbResponse.Watchlists(val.CbWatchlistID==obj.CbWatchlistID)': createContext(translatedData) }; return { Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }; } function updateWatchlistRequest(watchlistId, watchlistObject) { let response = sendRequest(`/v1/watchlist/${watchlistId}`, 'PUT', watchlistObject).Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function setWatchlist() { let watchlistObject = getWatchlistRequest(args['watchlist-id']); if (args['search-query']) { watchlistObject.search_query = args['search-query']; } if (args.name) { watchlistObject.name = args.name; } if (args.indexType) { watchlistObject.index_type = args.indexType; } let result = updateWatchlistRequest(args['watchlist-id'], watchlistObject); if (!result.result || result.result !== 'success') { throw `Failed updating watchlist.\nResponse: ${response}`; } let title = `CB Response - Set Watchlist`; let dataMap = watchlistData; let headers = dataMap.map(cn => cn.to); let translatedData = mapObjFunction(dataMap)(watchlistObject); let humanReadable = tableToMarkdown(title, translatedData, headers, undefined, dotToSpace); let context = { 'CbResponse.Watchlists(val.CbWatchlistID==obj.CbWatchlistID)': createContext(translatedData) }; return { Type: entryTypes.note, Contents: watchlistObject, ContentsType: formats.json, ReadableContentsFormat: formats.markdown, HumanReadable: humanReadable, EntryContext: context, }; } function deleteWatchlistRequest(watchlistId) { let response = sendRequest(`/v1/watchlist/${watchlistId}`, 'DELETE').Body; try { return JSON.parse(response); } catch (err) { throw `Could not parse response.\nError: ${err}.\nResponse: ${response}`; } } function deleteWatch() { let result = deleteWatchlistRequest(args['watchlist-id']); return { Type: entryTypes.note, Contents: result, ContentsType: formats.json, ReadableContentsFormat: formats.text, HumanReadable: "Success - deleted watchlist " + args["watchlist-id"] }; } try { switch (command) { case 'test-module': return testModule(); case 'cb-version': return version(); case 'fetch-incidents': return fetchIncidents(); case 'cb-alert': return showAlerts(); // Tested case 'cb-alert-update': return updateAlert(); // Tested case 'cb-quarantine-device': return quarantineDevice(true); // Tested case 'cb-unquarantine-device': return quarantineDevice(false); // Tested case 'cb-get-processes': return getProcesses(); // Tested case 'cb-get-process': return getProcess(); // Tested case 'cb-process-events': return getProcessEvents(); // Tested case 'cb-binary': return getBinaries(); // Tested case 'cb-binary-get': return getBinary(); // Tested case 'cb-list-sensors': case 'cb-sensor-info': return getSensors(); // Tested case 'cb-block-hash': return blockHash(true); // Tested case 'cb-unblock-hash': return blockHash(false); // Tested case 'cb-get-hash-blacklist': return getHashBlacklist(); // Tested case 'cb-watchlist': case 'cb-watchlist-get': return getWatchlist(); // Tested case 'cb-watchlist-new': return createWatchlist(); // Tested case 'cb-watchlist-set': return setWatchlist(); // Tested case 'cb-watchlist-del': return deleteWatch(); // Tested case 'cb-binary-download': return getBinaryZip(); default: throw `Unknown Command: ${command}`; } } catch (err) { return { Type: entryTypes.error, Contents: err, ContentsType: formats.json, ReadableContentsFormat: formats.text, HumanReadable: err } } /// Global Utils /** * Returns whether a given object 'obj' is empty (has no properties) */ function isEmpty(obj) { return Object.keys(obj).length === 0 && obj.constructor === Object } /** * Converts UNIX timestamp to format: YYYY-MM-DD HH:MM:SS */ function unixToString(unixTime) { let timeStr = convertTimestampToString(unixTime); return timeStr.substring(0, timeStr.length - 5); } /** * Converts a string timestamp (ISO String tested) to UNIX. */ function stringToUnix(dateString) { return new Date(dateString).getTime(); }