Details
| ID | FireEye HX |
|---|---|
| Provider | Trellix |
| Category | Endpoint |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.8.3296088 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
FireEye Endpoint Security is an integrated solution that detects what others miss and protects endpoint against known and unknown threats. The HX Demisto integration provides access to information about endpoints, acquisitions, alerts, indicators, and containment. Customers can extract critical data and effectively operate security operations automated playbook.
Configure FireEye HX in Cortex
| Parameter | Required |
|---|---|
| Server URL (e.g. https://192.168.0.1:3000) | True |
| Credentials | True |
| Password | True |
| Version | True |
| Trust any certificate (not secure) | False |
| Use system proxy settings | False |
| Fetch incidents | False |
| Incident type | False |
| Fetch limit | False |
| Incidents Fetch Interval | 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.
fireeye-hx-host-containment
Apply containment for a specific host, so that it no longer has access to other systems.
Base Command
fireeye-hx-host-containment
Input
| Argument Name | Description | Required |
|---|---|---|
| hostName | The host name to be contained. If the hostName is not specified, the agentId must be specified. | Optional |
| agentId | The agent id running on the host to be contained. If the agentId is not specified, the hostName must be specified. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Hosts._id | Unknown | FireEye HX Agent ID. |
| FireEyeHX.Hosts.agent_version | Unknown | The agent version. |
| FireEyeHX.Hosts.excluded_from_containment | Unknown | Determines whether the host is excluded from containment. |
| FireEyeHX.Hosts.containment_missing_software | Unknown | Boolean value to indicate for containment missing software. |
| FireEyeHX.Hosts.containment_queued | Unknown | Determines whether the host is queued for containment. |
| FireEyeHX.Hosts.containment_state | Unknown | The containment state of the host. Possible values normal, contain, contain_fail, containing, contained, uncontain, uncontaining, wtfc, wtfu. |
| FireEyeHX.Hosts.stats.alerting_conditions | Unknown | The number of conditions that have alerted for the host. |
| FireEyeHX.Hosts.stats.alerts | Unknown | Total number of alerts, including exploit-detection alerts. |
| FireEyeHX.Hosts.stats.exploit_blocks | Unknown | The number of blocked exploits on the host. |
| FireEyeHX.Hosts.stats.malware_alerts | Unknown | The number of malware alerts associated with the host. |
| FireEyeHX.Hosts.hostname | Unknown | The host name. |
| FireEyeHX.Hosts.domain | Unknown | Domain name. |
| FireEyeHX.Hosts.timezone | Unknown | Host time zone. |
| FireEyeHX.Hosts.primary_ip_address | Unknown | The host IP address. |
| FireEyeHX.Hosts.last_poll_timestamp | Unknown | The timestamp of the last system poll preformed on the host. |
| FireEyeHX.Hosts.initial_agent_checkin | Unknown | Timestamp of the initial agent check-in. |
| FireEyeHX.Hosts.last_alert_timestamp | Unknown | The time stamp of the last alert for the host. |
| FireEyeHX.Hosts.last_exploit_block_timestamp | Unknown | Time when the last exploit was blocked on the host. The value is null if no exploits have been blocked. |
| FireEyeHX.Hosts.os.product_name | Unknown | Specific operating system |
| FireEyeHX.Hosts.os.bitness | Unknown | OS Bitness. |
| FireEyeHX.Hosts.os.platform | Unknown | Family of operating systems. Valid values are win, osx, and linux. |
| FireEyeHX.Hosts.primary_mac | Unknown | The host MAC address. |
Command Example
!fireeye-hx-host-containment agentId=”uGvn34ZkM3bfSf1nOT”
!fireeye-hx-host-containment hostname=“DESKTOP-HK8OI62”
Context Example
{
"FireEyeHX":{
"Hosts":{
"last_alert":{
"url":"/hx/api/v3/alerts/5",
"_id":5
},
"domain":"DEMISTO",
"last_exploit_block_timestamp":null,
"containment_state":"contain",
"timezone":"Eastern Daylight Time",
"gmt_offset_seconds":-14400,
"initial_agent_checkin":"2018-03-26T14:21:31.273Z",
"stats":{
"alerting_conditions":1,
"exploit_alerts":0,
"acqs":11,
"malware_false_positive_alerts":0,
"alerts":1,
"exploit_blocks":0,
"malware_cleaned_count":0,
"malware_alerts":0,
"malware_quarantined_count":0
},
"primary_mac":"XX-XX-XX-XX-XX-XX",
"hostname":"DESKTOP-XXX",
"primary_ip_address":"^^^XX.XX.XX.XX^^^",
"last_audit_timestamp":"2018-05-03T13:59:23.000Z",
"last_alert_timestamp":"2018-04-16T08:59:51.693+00:00",
"containment_queued":false,
"sysinfo":{
"url":"/hx/api/v3/hosts/uGvnGVpZkDSFySf2ZOiT/sysinfo"
},
"last_exploit_block":null,
"reported_clone":false,
"url":"/hx/api/v3/hosts/uGvnGVpZkeySf2ZOiT",
"excluded_from_containment":false,
"last_poll_timestamp":"2018-05-03T14:01:22.000Z",
"last_poll_ip":"^^^XX.XX.XX.XX^^^",
"containment_missing_software":false,
"_id":" uGvnGVpZkDSFySf2ZOiT ",
"os":{
"kernel_version":null,
"platform":"win",
"patch_level":null,
"bitness":"64-bit",
"product_name":"Windows 10 Enterprise Evaluation"
},
"agent_version":"26.21.10"
}
}
}
fireeye-hx-cancel-containment
Release a specific host from containment.
Base Command
fireeye-hx-cancel-containment
Input
| Argument Name | Description | Required |
|---|---|---|
| hostName | The host name to be contained. If the hostName is not specified, the agentId must be specified. | Optional |
| agentId | The agent id running on the host to be contained. If the agentId is not specified, the hostName must be specified. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Hosts._id | Unknown | FireEye HX Agent ID. |
| FireEyeHX.Hosts.agent_version | Unknown | The agent version. |
| FireEyeHX.Hosts.excluded_from_containment | Unknown | Determines whether the host is excluded from containment. |
| FireEyeHX.Hosts.containment_missing_software | Unknown | Boolean value to indicate for containment missing software. |
| FireEyeHX.Hosts.containment_queued | Unknown | Determines whether the host is queued for containment. |
| FireEyeHX.Hosts.containment_state | Unknown | The containment state of the host. Possible values normal, contain, contain_fail, containing, contained, uncontain, uncontaining, wtfc, wtfu. |
| FireEyeHX.Hosts.stats.alerting_conditions | Unknown | The number of conditions that have alerted for the host. |
| FireEyeHX.Hosts.stats.alerts | Unknown | Total number of alerts, including exploit-detection alerts. |
| FireEyeHX.Hosts.stats.exploit_blocks | Unknown | The number of blocked exploits on the host. |
| FireEyeHX.Hosts.stats.malware_alerts | Unknown | The number of malware alerts associated with the host. |
| FireEyeHX.Hosts.hostname | Unknown | The host name. |
| FireEyeHX.Hosts.domain | Unknown | Domain name. |
| FireEyeHX.Hosts.timezone | Unknown | Host time zone. |
| FireEyeHX.Hosts.primary_ip_address | Unknown | The host IP address. |
| FireEyeHX.Hosts.last_poll_timestamp | Unknown | The timestamp of the last system poll preformed on the host. |
| FireEyeHX.Hosts.initial_agent_checkin | Unknown | Timestamp of the initial agent check-in. |
| FireEyeHX.Hosts.last_alert_timestamp | Unknown | The time stamp of the last alert for the host. |
| FireEyeHX.Hosts.last_exploit_block_timestamp | Unknown | Time when the last exploit was blocked on the host. The value is null if no exploits have been blocked. |
| FireEyeHX.Hosts.os.product_name | Unknown | Specific operating system |
| FireEyeHX.Hosts.os.bitness | Unknown | OS Bitness. |
| FireEyeHX.Hosts.os.platform | Unknown | Family of operating systems. Valid values are win, osx, and linux. |
| FireEyeHX.Hosts.primary_mac | Unknown | The host MAC address. |
Command Examples
!fireeye-hx-cancel-containment hostname=“DESKTOP-HK8OI62”
!fireeye-hx-cancel-containment agentId=”uGvn34ZkM3bfSf1nOT”
Context Example
{
"FireEyeHX": {
"Hosts": {
"last_alert": {
"url": "/hx/api/v3/alerts/5",
"_id": 5
},
"domain": "DEMISTO",
"last_exploit_block_timestamp": null,
"containment_state": "normal",
"timezone": "Eastern Daylight Time",
"gmt_offset_seconds": -14400,
"initial_agent_checkin": "2018-03-26T14:21:31.273Z",
"stats": {
"alerting_conditions": 1,
"exploit_alerts": 0,
"acqs": 11,
"malware_false_positive_alerts": 0,
"alerts": 1,
"exploit_blocks": 0,
"malware_cleaned_count": 0,
"malware_alerts": 0,
"malware_quarantined_count": 0
},
"primary_mac": "XX-XX-XX-XX-XX-XX",
"hostname": "DESKTOP-XXX",
"primary_ip_address": "^^^XX.XX.XX.XX^^^",
"last_audit_timestamp": "2018-05-03T13:59:23.000Z",
"last_alert_timestamp": "2018-04-16T08:59:51.693+00:00",
"containment_queued": false,
"sysinfo": {
"url": "/hx/api/v3/hosts/uGvnGVpZkDSFySf2ZOiT/sysinfo"
},
"last_exploit_block": null,
"reported_clone": false,
"url": "/hx/api/v3/hosts/uGvnGVpZkeySf2ZOiT",
"excluded_from_containment": false,
"last_poll_timestamp": "2018-05-03T14:01:22.000Z",
"last_poll_ip": "^^^XX.XX.XX.XX^^^",
"containment_missing_software": false,
"_id": " uGvnGVpZkDSFySf2ZOiT ",
"os": {
"kernel_version": null,
"platform": "win",
"patch_level": null,
"bitness": "64-bit",
"product_name": "Windows 10 Enterprise Evaluation"
},
"agent_version": "26.21.10"
}
}
}
fireeye-hx-get-alerts
Get a list of alerts, use the different arguments to filter the results returned.
Base Command
fireeye-hx-get-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| hasShareMode | Identifies which alerts result from indicators with the specified share mode. Possible values are: any, restricted, unrestricted. | Optional |
| resolution | Sorts the results by the specified field. Possible values are: active_threat, alert, block, partial_block. | Optional |
| agentId | Filter by the agent ID. | Optional |
| conditionId | Filter by condition ID. | Optional |
| eventAt | Filter event occurred time. ISO-8601 timestamp.. | Optional |
| alertId | Filter by alert ID. | Optional |
| matchedAt | Filter by match detection time. ISO-8601 timestamp. | Optional |
| minId | Filter that returns only records with an AlertId field value great than the minId value. | Optional |
| reportedAt | Filter by reported time. ISO-8601 timestamp. | Optional |
| IOCsource | Source of alert- indicator of compromise. Possible values are: yes. | Optional |
| EXDsource | Source of alert - exploit detection. Possible values are: yes. | Optional |
| MALsource | Source of alert - malware alert. Possible values are: yes. | Optional |
| limit | Limit the results returned. | Optional |
| sort | Sorts the results by the specified field in ascending order. Possible values are: agentId, conditionId, eventAt, alertId, matchedAt, id, reportedAt. | Optional |
| sortOrder | The sort order for the results. Possible values are: ascending, descending. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Alerts._id | Unknown | FireEye alert ID. |
| FireEyeHX.Alerts.agent._id | Unknown | FireEye agent ID. |
| FireEyeHX.Alerts.agent.containment_state | Unknown | Host containment state. |
| FireEyeHX.Alerts.condition._id | Unknown | The condition unique ID. |
| FireEyeHX.Alerts.event_at | Unknown | Time when the event occoured. |
| FireEyeHX.Alerts.matched_at | Unknown | Time when the event was matched. |
| FireEyeHX.Alerts.reported_at | Unknown | Time when the event was reported. |
| FireEyeHX.Alerts.source | Unknown | Source of alert. |
| FireEyeHX.Alerts.matched_source_alerts._id | Unknown | Source alert ID. |
| FireEyeHX.Alerts.matched_source_alerts.appliance_id | Unknown | Appliance ID |
| FireEyeHX.Alerts.matched_source_alerts.meta | Unknown | Source alert meta. |
| FireEyeHX.Alerts.matched_source_alerts.indicator_id | Unknown | Indicator ID. |
| FireEyeHX.Alerts.resolution | Unknown | Alert resulotion. |
| FireEyeHX.Alerts.event_type | Unknown | Event type. |
Command Example
!fireeye-hx-get-alerts limit="10" sort="id" sortOrder="descending"
Context Example
{
"FireEyeHX": {
"Alerts": {
"_id": 5,
"agent": {
"_id": "uGvnGVp…4bKeySf2ZOiT",
"containment_state": "normal",
"url": "/hx/api/v3/hosts/ uGvnGVp…4bKeySf2ZOiT "
},
"condition": {
"_id": "CSaoSZFw…JNPW0mw==",
"url": "/hx/api/v3/conditions/ CSaoSZFw…JNPW0mw =="
},
"event_at": "2018-04-16T08:59:02.061Z",
"event_id": 7885715,
"event_type": "fileWriteEvent",
"event_values": {
"fileWriteEvent/closed": 1,
"fileWriteEvent/dataAtLowestOffset": "dGVzdGVzdA==",
"fileWriteEvent/devicePath": "\\Device\\HarddiskVolume2",
"fileWriteEvent/drive": "C",
"fileWriteEvent/fileExtension": "txt",
"fileWriteEvent/fileName": "testest - Copy.txt",
"fileWriteEvent/filePath": "Users\\demistodev\\Documents",
"fileWriteEvent/fullPath": "C:\\Users\\User\\Documents\\testest - Copy.txt",
"fileWriteEvent/lowestFileOffsetSeen": 0,
"fileWriteEvent/md5": " c3add7b947…817c79f7b7bd ",
"fileWriteEvent/numBytesSeenWritten": 7,
"fileWriteEvent/pid": 3308,
"fileWriteEvent/process": "explorer.exe",
"fileWriteEvent/processPath": "C:\\Windows",
"fileWriteEvent/size": 7,
"fileWriteEvent/textAtLowestOffset": "testest",
"fileWriteEvent/timestamp": "2018-04-16T08:59:02.061Z",
"fileWriteEvent/username": "DEMISTO\\User",
"fileWriteEvent/writes": 1
},
"is_false_positive": null,
"matched_at": "2018-04-16T08:59:10.000Z",
"matched_source_alerts": [],
"reported_at": "2018-04-16T08:59:51.693Z",
"resolution": "ALERT",
"source": "IOC",
"url": "/hx/api/v3/alerts/5"
}
},
"File": [
{
"Extension": "txt",
"MD5": "c3add7b947…817c79f7b7bd",
"Name": "testest - Copy.txt",
"Path": "C:\\Users\\User\\Documents\\testest - Copy.txt"
}
],
"IP": [],
"RrgistryKey": []
}
fireeye-hx-suppress-alert
Suppress alert by ID
Base Command
fireeye-hx-suppress-alert
Input
| Argument Name | Description | Required |
|---|---|---|
| alertId | The alert id. The alert id is listed in the output of ‘get-alerts’ command. | Optional |
Context Output
There is no context output for this command.
Command Example
!fireeye-hx-suppress-alert alertId=2
fireeye-hx-get-indicators
Get a list of indicators
Base Command
fireeye-hx-get-indicators
Input
| Argument Name | Description | Required |
|---|---|---|
| category | The indicator category. | Optional |
| searchTerm | The searchTerm can be any name, category, signature, source, or condition value. | Optional |
| shareMode | Determines who can see the indicator. You must belong to the correct authorization group . Possible values are: any, restricted, unrestricted, visible. | Optional |
| sort | Sorts the results by the specified field in ascending order. Possible values are: category, activeSince, createdBy, alerted. | Optional |
| createdBy | Person who created the indicator. | Optional |
| alerted | Whether the indicator resulted in alerts. Possible values are: yes, no. | Optional |
| limit | Limit the number of results. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Indicators._id | Unknown | FireEye unique indicator ID. |
| FireEyeHX.Indicators.name | Unknown | The indicator name as displayed in the UI. |
| FireEyeHX.Indicators.description | Unknown | Indicator description. |
| FireEyeHX.Indicators.category.name | Unknown | Catagory name. |
| FireEyeHX.Indicators.created_by | Unknown | The “Created By” field as displayed in UI |
| FireEyeHX.Indicators.active_since | Unknown | Date indicator became active. |
| FireEyeHX.Indicators.stats.source_alerts | Unknown | Total number of source alerts associated with this indicator. |
| FireEyeHX.Indicators.stats.alerted_agents | Unknown | Total number of agents with HX alerts associated with this indicator. |
| FireEyeHX.Indicators.platforms | Unknown | List of families of operating systems. |
| FireEyeHX.Indicators.uri_name | String | URI formatted name of the indicator. |
| FireEyeHX.Indicators.category.uri_name | String | URI name of the category. |
Command Example
!fireeye-hx-get-indicators limit=2
Context Example
{
"FireEyeHX": {
"Indicators": [
{
"_id": "34757fe7-bdd7-4c85-b0e1-9adfb5e48300",
"_revision": "20211017115618818832920449",
"active_since": "2021-10-17T11:56:18.818Z",
"category": {
"_id": 2,
"name": "Custom",
"share_mode": "unrestricted",
"uri_name": "Custom",
"url": "/hx/api/v3/indicator_categories/custom"
},
"create_actor": {
"_id": 1001,
"username": "api-admin"
},
"create_text": null,
"created_by": "api-admin",
"description": null,
"display_name": null,
"meta": null,
"name": "34757fe7-bdd7-4c85-b0e1-9adfb5e48300",
"platforms": [
"win",
"osx",
"linux"
],
"signature": null,
"stats": {
"active_conditions": 0,
"alerted_agents": 0,
"source_alerts": 0
},
"update_actor": {
"_id": 1001,
"username": "api-admin"
},
"uri_name": "34757fe7-bdd7-4c85-b0e1-9adfb5e48300",
"url": "/hx/api/v3/indicators/custom/34757fe7_bdd7_4c85_b0e1_9adfb5e48300"
},
{
"_id": "c6286e1b-10bd-4046-8aff-0dbcc5b1e974",
"_revision": "20201214155227728995101265",
"active_since": "2021-09-28T14:44:04.245Z",
"category": {
"_id": 7,
"name": "Mandiant Unrestricted Intel",
"share_mode": "unrestricted",
"uri_name": "mandiant_unrestricted",
"url": "/hx/api/v3/indicator_categories/mandiant_unrestricted"
},
"create_actor": {
"_id": 3,
"username": "mandiant"
},
"create_text": "General_Windows_unrestricted_2021.09.270849",
"created_by": "General_Windows_unrestricted_2021.09.270849",
"description": "This IOC alerts on suspicious filewrites by the legitimate solarwinds process solarwinds.businesslayerhost.exe. solarwinds.businesslayerhost.exe is part of the the Network Performance Monitor (NPM) module of Solarwinds; responsible for detecting and diagnosing network performance issues. This may be an evidence of SUNBURST which is a backdoor that has the ability to spawn and kill processes, write and delete files, set and create registry keys, gather system information, and disable a set of forensic analysis tools and services.This is associated with MITRE ATT&CK (r) Tactic(s): Initial Access and Technique(s): T1195.002.",
"display_name": "SUNBURST SUSPICIOUS FILEWRITES (METHODOLOGY)",
"meta": null,
"name": "SUNBURST SUSPICIOUS FILEWRITES (METHODOLOGY)",
"platforms": [
"win",
"osx",
"linux"
],
"signature": null,
"stats": {
"active_conditions": 6,
"alerted_agents": 0,
"source_alerts": 0
},
"update_actor": {
"_id": 3,
"username": "mandiant"
},
"uri_name": "c6286e1b-10bd-4046-8aff-0dbcc5b1e974",
"url": "/hx/api/v3/indicators/mandiant_unrestricted/c6286e1b_10bd_4046_8aff_0dbcc5b1e974"
}
]
}
}
Human Readable Output
FireEye HX Get Indicator- None
OS Name Created By Active Since Category Signature Active Condition Hosts With Alerts Source Alerts win, osx, linux 34757fe7-bdd7-4c85-b0e1-9adfb5e48300 api-admin 2021-10-17T11:56:18.818Z Custom 0 0 0 win, osx, linux SUNBURST SUSPICIOUS FILEWRITES (METHODOLOGY) General_Windows_unrestricted_2021.09.270849 2021-09-28T14:44:04.245Z Mandiant Unrestricted Intel 6 0 0
fireeye-hx-get-indicator
Get a specific indicator details
Base Command
fireeye-hx-get-indicator
Input
| Argument Name | Description | Required |
|---|---|---|
| category | Indicator category. Please use the uri_category value. |
Required |
| name | Indicator name. Please use the uri_name value. |
Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Indicators._id | Unknown | FireEye unique indicator ID. |
| FireEyeHX.Indicators.name | Unknown | The indicator name as displayed in the UI. |
| FireEyeHX.Indicators.description | Unknown | Indicator description. |
| FireEyeHX.Indicators.category.name | Unknown | Catagory name. |
| FireEyeHX.Indicators.created_by | Unknown | The “Created By” field as displayed in UI |
| FireEyeHX.Indicators.active_since | Unknown | Date indicator became active. |
| FireEyeHX.Indicators.stats.source_alerts | Unknown | Total number of source alerts associated with this indicator. |
| FireEyeHX.Indicators.stats.alerted_agents | Unknown | Total number of agents with HX alerts associated with this indicator. |
| FireEyeHX.Indicators.platforms | Unknown | List of families of operating systems. |
| FireEyeHX.Conditions._id | Unknown | FireEye unique condition ID. |
| FireEyeHX.Conditions.event_type | Unknown | Event type. |
| FireEyeHX.Conditions.enabled | Unknown | Indicates whether the condition is enabled. |
Command Example
!fireeye-hx-get-indicator category=Custom name="5def0b16-87bc-42a2-877a-bca45ebcbc9a"
Context Example
{
"FireEyeHX": {
"Conditions": [
{
"_id": "YhXur1M8FNRDi8GAr9CMbQ==",
"enabled": true,
"event_type": "dnsLookupEvent",
"is_private": false,
"tests": [
{
"operator": "equal",
"token": "dnsLookupEvent/hostname",
"type": "text",
"value": "example.lol"
}
],
"url": "/hx/api/v3/conditions/YhXur1M8FNRDi8GAr9CMbQ",
"uuid": "6215eeaf-533c-44d4-838b-c180afd08c6d"
},
{
"_id": "gB7gGHN9RmLNdf8mwuvQ8Q==",
"enabled": true,
"event_type": "dnsLookupEvent",
"is_private": false,
"tests": [
{
"operator": "equal",
"token": "dnsLookupEvent/hostname",
"type": "text",
"value": "example.abc"
}
],
"url": "/hx/api/v3/conditions/gB7gGHN9RmLNdf8mwuvQ8Q",
"uuid": "801ee018-737d-4662-8d75-ff26c2ebd0f1"
}
],
"Indicators": {
"_id": "5def0b16-87bc-42a2-877a-bca45ebcbc9a",
"_revision": "20210920184007966360614215",
"active_since": "2021-09-20T18:40:07.966Z",
"category": {
"_id": 2,
"name": "Custom",
"share_mode": "unrestricted",
"uri_name": "Custom",
"url": "/hx/api/v3/indicator_categories/custom"
},
"create_actor": {
"_id": 1001,
"username": "api-admin"
},
"create_text": null,
"created_by": "api-admin",
"description": null,
"display_name": null,
"meta": null,
"name": "5def0b16-87bc-42a2-877a-bca45ebcbc9a",
"platforms": [
"win",
"osx",
"linux"
],
"signature": null,
"stats": {
"active_conditions": 2,
"alerted_agents": 0,
"source_alerts": 0
},
"update_actor": {
"_id": 1001,
"username": "api-admin"
},
"uri_name": "5def0b16-87bc-42a2-877a-bca45ebcbc9a",
"url": "/hx/api/v3/indicators/custom/5def0b16_87bc_42a2_877a_bca45ebcbc9a"
}
}
}
Human Readable Output
Indicator “5def0b16-87bc-42a2-877a-bca45ebcbc9a” Alerts on
Event Type Operator Value dnsLookupEvent equal example.lol dnsLookupEvent equal example.abc
fireeye-hx-get-host-information
Get information on a host associated with an agent.
Base Command
fireeye-hx-get-host-information
Input
| Argument Name | Description | Required |
|---|---|---|
| agentId | The agent ID. If the agent ID is not specified, the host Name must be specified. | Optional |
| hostName | The host name. If the host name is not specified, the agent ID must be specified. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Hosts._id | Unknown | FireEye HX Agent ID. |
| FireEyeHX.Hosts.agent_version | Unknown | The agent version. |
| FireEyeHX.Hosts.excluded_from_containment | Unknown | Determines whether the host is excluded from containment. |
| FireEyeHX.Hosts.containment_missing_software | Unknown | Boolean value to indicate for containment missing software. |
| FireEyeHX.Hosts.containment_queued | Unknown | Determines whether the host is queued for containment. |
| FireEyeHX.Hosts.containment_state | Unknown | The containment state of the host. Possible values normal, contain, contain_fail, containing, contained, uncontain, uncontaining, wtfc, wtfu. |
| FireEyeHX.Hosts.stats.alerting_conditions | Unknown | The number of conditions that have alerted for the host. |
| FireEyeHX.Hosts.stats.alerts | Unknown | Total number of alerts, including exploit-detection alerts. |
| FireEyeHX.Hosts.stats.exploit_blocks | Unknown | The number of blocked exploits on the host. |
| FireEyeHX.Hosts.stats.malware_alerts | Unknown | The number of malware alerts associated with the host. |
| FireEyeHX.Hosts.hostname | Unknown | The host name. |
| FireEyeHX.Hosts.domain | Unknown | Domain name. |
| FireEyeHX.Hosts.timezone | Unknown | Host time zone. |
| FireEyeHX.Hosts.primary_ip_address | Unknown | The host IP address. |
| FireEyeHX.Hosts.last_poll_timestamp | Unknown | The timestamp of the last system poll preformed on the host. |
| FireEyeHX.Hosts.initial_agent_checkin | Unknown | Timestamp of the initial agent check-in. |
| FireEyeHX.Hosts.last_alert_timestamp | Unknown | The time stamp of the last alert for the host. |
| FireEyeHX.Hosts.last_exploit_block_timestamp | Unknown | Time when the last exploit was blocked on the host. The value is null if no exploits have been blocked. |
| FireEyeHX.Hosts.os.product_name | Unknown | Specific operating system |
| FireEyeHX.Hosts.os.bitness | Unknown | OS Bitness. |
| FireEyeHX.Hosts.os.platform | Unknown | Family of operating systems. Valid values are win, osx, and linux. |
| FireEyeHX.Hosts.primary_mac | Unknown | The host MAC address. |
Command Example
!fireeye-hx-get-host-information hostName=”DESKTOP-XXX”
Context Output
{
"FireEyeHX": {
"Hosts": {
"last_alert": {
"url": "/hx/api/v3/alerts/5",
"_id": 5
},
"domain": "DEMISTO",
"last_exploit_block_timestamp": null,
"containment_state": "normal",
"timezone": "Eastern Daylight Time",
"gmt_offset_seconds": -14400,
"initial_agent_checkin": "2018-03-26T14:21:31.273Z",
"stats": {
"alerting_conditions": 1,
"exploit_alerts": 0,
"acqs": 11,
"malware_false_positive_alerts": 0,
"alerts": 1,
"exploit_blocks": 0,
"malware_cleaned_count": 0,
"malware_alerts": 0,
"malware_quarantined_count": 0
},
"primary_mac": "XX-XX-XX-XX-XX-XX",
"hostname": "DESKTOP-XXX",
"primary_ip_address": "^^^XX.XX.XX.XX^^^",
"last_audit_timestamp": "2018-05-03T13:59:23.000Z",
"last_alert_timestamp": "2018-04-16T08:59:51.693+00:00",
"containment_queued": false,
"sysinfo": {
"url": "/hx/api/v3/hosts/uGvnGVpZkDSFySf2ZOiT/sysinfo"
},
"last_exploit_block": null,
"reported_clone": false,
"url": "/hx/api/v3/hosts/uGvnGVpZkeySf2ZOiT",
"excluded_from_containment": false,
"last_poll_timestamp": "2018-05-03T14:01:22.000Z",
"last_poll_ip": "^^^XX.XX.XX.XX^^^",
"containment_missing_software": false,
"_id": " uGvnGVpZkDSFySf2ZOiT ",
"os": {
"kernel_version": null,
"platform": "win",
"patch_level": null,
"bitness": "64-bit",
"product_name": "Windows 10 Enterprise Evaluation"
},
"agent_version": "26.21.10"
}
},
"Endpoint": {
"MACAddress": "XX-XX-XX-XX-XX-XX",
"Domain": "DEMISTO",
"IPAddress": "^^^XX.XX.XX.XX^^^",
"Hostname": "DESKTOP-XXX",
"OSVersion": "Windows 10 Enterprise Evaluation",
"OS": "win",
"ID": " uGvnGVpZkDSFySf2ZOiT "
},
}
fireeye-hx-get-alert
Get details of a specific alert
Base Command
fireeye-hx-get-alert
Input
| Argument Name | Description | Required |
|---|---|---|
| alertId | The alert ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Alerts._id | Unknown | FireEye alert ID. |
| FireEyeHX.Alerts.agent._id | Unknown | FireEye agent ID. |
| FireEyeHX.Alerts.agent.containment_state | Unknown | Host containment state. |
| FireEyeHX.Alerts.condition._id | Unknown | The condition unique ID. |
| FireEyeHX.Alerts.event_at | Unknown | Time when the event occoured. |
| FireEyeHX.Alerts.matched_at | Unknown | Time when the event was matched. |
| FireEyeHX.Alerts.reported_at | Unknown | Time when the event was reported. |
| FireEyeHX.Alerts.source | Unknown | Source of alert. |
| FireEyeHX.Alerts.matched_source_alerts._id | Unknown | Source alert ID. |
| FireEyeHX.Alerts.matched_source_alerts.appliance_id | Unknown | Appliance ID |
| FireEyeHX.Alerts.matched_source_alerts.meta | Unknown | Source alert meta. |
| FireEyeHX.Alerts.matched_source_alerts.indicator_id | Unknown | Indicator ID. |
| FireEyeHX.Alerts.resolution | Unknown | Alert resulotion. |
| FireEyeHX.Alerts.event_type | Unknown | Event type. |
fireeye-hx-file-acquisition
Aquire a specific file as a password protected zip file. The password for unlocking the zip file is ‘unzip-me’.
Base Command
fireeye-hx-file-acquisition
Input
| Argument Name | Description | Required |
|---|---|---|
| fileName | The file name. | Required |
| filePath | The file path. | Required |
| acquireUsing | Whether to aqcuire the file using the API or RAW. By default, raw file will be acquired. Use API option when file is encrypted. Possible values are: API, RAW. | Optional |
| agentId | The agent ID associated with the host that holds the file. If the hostName is not specified, the agentId must be specified. | Optional |
| hostName | The host that holds the file. If the agentId is not specified, hostName must be specified. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Acquisitions.Files._id | Unknown | The acquisition unique ID. |
| FireEyeHX.Acquisitions.Files.state | Unknown | The acquisition state. |
| FireEyeHX.Acquisitions.Files.md5 | Unknown | File md5. |
| FireEyeHX.Acquisitions.Files.req_filename | Unknown | The file name. |
| FireEyeHX.Acquisitions.Files.req_path | Unknown | The file path. |
| FireEyeHX.Acquisitions.Files.host._id | Unknown | FireEye HX agent ID. |
Command Example
!fireeye-hx-file-acquisition fileName="test.txt"filePath="C:\\Users\\user\\Documents" hostName="DESKTOP-DES01"
Context Output
"FireEyeHX": {
"Acquisitions": {
"Files": {
"_id": 13,
"_revision": "206073441021688",
"alert": null,
"comment": null,
"condition": null,
"error_message": "The acquisition completed with issues.",
"external_id": null,
"finish_time": "2018-04-26T07:34:14.100Z",
"host": {
"_id": "uGvnGVpZkKeySf2ZT",
"url": "/hx/api/v3/hosts/ uGvnGVpZkKeySf2ZT "
},
"indicator": null,
"md5": "ee26908bf9…64b37da4754a",
"req_filename": "ex.txt",
"req_path": "C:\\Users\\user\\Documents",
"req_use_api": null,
"request_actor": {
"_id": 1001,
"username": "api"
},
"request_time": "2018-04-26T07:33:03.000Z",
"state": "COMPLETE",
"url": "/hx/api/v3/acqs/files/13",
"zip_passphrase": "unzip-me"
}
}
}
fireeye-hx-delete-file-acquisition
Delete the file acquisition, by ID.
Base Command
fireeye-hx-delete-file-acquisition
Input
| Argument Name | Description | Required |
|---|---|---|
| acquisitionId | The acquisition ID. | Required |
Context Output
There is no context output for this command.
Command Example
!fireeye-hx-delete-file-acquisition acquisitionId=10
fireeye-hx-data-acquisition
Start a data acquisition process to gather artifacts from the system disk and memory. The data is fetched as mans file.
Base Command
fireeye-hx-data-acquisition
Input
| Argument Name | Description | Required |
|---|---|---|
| script | Acquisition script in JSON format. | Optional |
| scriptName | The script name. If the Acquisition script is specified, the script name must be specified as well. | Optional |
| defaultSystemScript | Use default script. Select the host system. Possible values are: osx, win, linux. | Optional |
| agentId | The agent ID. If the host name is not specified, the agent ID must be specified. | Optional |
| hostName | The host name. If the agent ID is not specified, the host name must be specified. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Acquisitions.Data._id | Unknown | The acquisition unique ID. |
| FireEyeHX.Acquisitions.Data.state | Unknown | The acquisition state. |
| FireEyeHX.Acquisitions.Data.md5 | Unknown | File md5. |
| FireEyeHX.Acquisitions.Data.finish_time | Unknown | Time when the acquisition was finished. |
| FireEyeHX.Acquisitions.Data.host._id | unknown | Agent ID |
Command Example
! fireeye-hx-data-acquisition hostName="DESKTOP-DES01" defaultSystemScript=win
Contex Example
{
"FireEyeHX": {
"Acquisitions": {
"Data": {
"comment": null,
"zip_passphrase": null,
"request_actor": {
"username": "api",
"_id": 1001
},
"name": "test",
"script": {
"download": "/hx/api/v3/scripts/131ab1da5086fe09f5a210437de366007867fa26.json",
"url": "/hx/api/v3/scripts/^^^131ab1da5086fe09f5a210437de366007867fa26^^^",
"_id": "^^^131ab1da5086fe09f5a210437de366007867fa26^^^"
},
"finish_time": "2018-05-15T11:58:18.541Z",
"_revision": "20180515115818542250101787",
"error_message": "The triage completed with issues.",
"state": "COMPLETE",
"request_time": "2018-05-15T11:57:22.000Z",
"url": "/hx/api/v3/acqs/live/28",
"host": {
"url": "/hx/api/v3/hosts/uGvnGVpZkM4bKeySf2ZOiT",
"_id": "uGvnGVpZkXXXX2ZOiT"
},
"download": "/hx/api/v3/acqs/live/28.mans",
"_id": 28,
"external_id": null,
"md5": null
}
}
},
"File": {
"Info": "mans",
"SHA1": "^^^4374d09a27ef85XXXXX66785c040d7febff7d8^^^",
"Name": "agent_uGvnGVpZkMXXXX2ZOiT_data.mans",
"Extension": "mans",
"Size": 5154,
"EntryID": "383@1",
"SSDeep": "96:JraN9hyFIVls4Dst99i462teLuf0XXXXyU2y46Gd/pV:xapyFIVibPi462teLuf0TXdLNJLU23dt",
"SHA256": "7944d5e86ce2bXXXXe154d4c2923ddf47016a07b84b460f08b0f2f",
"Type": "Zip archive data, at least v2.0 to extract\n",
"MD5": "^^^c24a2c4aeXXXXf89e1e012dae^^^"
}
}
fireeye-hx-delete-data-acquisition
Delete data acquisition.
Base Command
fireeye-hx-delete-data-acquisition
Input
| Argument Name | Description | Required |
|---|---|---|
| acquisitionId | The acquisition ID. | Required |
Context Output
There is no context output for this command.
Command Example
!fireeye-hx-delete-data-acquisition acquisitionId=10
fireeye-hx-search
Search endpoints to check all hosts or a subset of hosts for a specific file or indicator.
Base Command
fireeye-hx-search
Input
| Argument Name | Description | Required |
|---|---|---|
| agentsIds | IDs of agents to be searched. | Optional |
| hostsNames | Names of hosts to be searched. | Optional |
| hostSet | Id of host set to be searched. | Optional |
| limit | Limit results count (once limit is reached, the search is stopped). | Optional |
| exhaustive | Should search be exhaustive or quick. Possible values are: yes, no. Default is True. | Optional |
| ipAddress | A valid IPv4 address to search for. | Optional |
| ipAddressOperator | Which operator to apply to the given IP address. Possible values are: equals, not equals. | Optional |
| fileMD5Hash | A 32-character MD5 hash value to search for. | Optional |
| fileMD5HashOperator | Which operator to apply to the given MD5 hash. Possible values are: equals, not equals. | Optional |
| fileFullPath | Full path of file to search. | Optional |
| fileFullPathOperator | Which operator to apply to the given file path. Possible values are: equals, not equals, contains, not contains. | Optional |
| dnsHostname | DNS value to search for. | Optional |
| dnsHostnameOperator | Which operator to apply to the given DNS. Possible values are: equals, not equals, contains, not contains. | Optional |
| stopSearch | Method in which search should be stopped after finding <limit> number of results. Possible values are: stopAndDelete, stop. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Search.Results.Timestamp - Modified | string | Time when the entry was last modified |
| FireEyeHX.Search.Results.File Text Written | string | The file text content |
| FireEyeHX.Search.Results.File Name | string | Name of the file |
| FireEyeHX.Search.Results.File Full Path | string | The full path of the file |
| FireEyeHX.Search.Results.File Bytes Written | string | Number of bytes written to the file |
| FireEyeHX.Search.Results.Size in bytes | string | Size of the file in bytes |
| FireEyeHX.Search.Results.Browser Version | string | Version of the browser |
| FireEyeHX.Search.Results.Browser Name | string | Name of the browser |
| FireEyeHX.Search.Results.Cookie Name | string | Name of the cookie |
| FireEyeHX.Search.Results.DNS Hostname | string | Name of the DNS host |
| FireEyeHX.Search.Results.URL | string | The event URL |
| FireEyeHX.Search.Results.Username | string | The event username |
| FireEyeHX.Search.Results.File MD5 Hash | string | MD5 hash of the file |
| FireEyeHX.Search.HostID | string | ID of the host |
| FireEyeHX.Search.HostName | string | Name of host |
| FireEyeHX.Search.HostUrl | string | Inner FireEye host url |
| FireEyeHX.Search.SearchID | string | ID of performed search |
| FireEyeHX.Search.Results.Timestamp - Accessed | string | Last accessed time |
| FireEyeHX.Search.Results.Port | number | Port |
| FireEyeHX.Search.Results.Process ID | string | ID of the process |
| FireEyeHX.Search.Results.Local IP Address | string | Local IP Address |
| FireEyeHX.Search.Results.Local IP Address | string | Local IP Address |
| FireEyeHX.Search.Results.Local Port | number | Local Port |
| FireEyeHX.Search.Results.Username | string | Username |
| FireEyeHX.Search.Results.Remote Port | number | Remote Port |
| FireEyeHX.Search.Results.IP Address | string | IP Address |
| FireEyeHX.Search.Results.Process Name | string | Process Name |
| FireEyeHX.Search.Results.Timestamp - Event | string | Timestamp - Event |
| FireEyeHX.Search.Results.type | string | The type of the event |
| FireEyeHX.Search.Results.id | string | ID of the result |
fireeye-hx-get-host-set-information
Get a list of all host sets known to your HX Series appliance
Base Command
fireeye-hx-get-host-set-information
Input
| Argument Name | Description | Required |
|---|---|---|
| hostSetID | ID of a specific host set to get. | Optional |
| offset | Specifies which record to start with in the response. The offset value must be an unsigned 32-bit integer. The default is 0. | Optional |
| limit | Specifies how many records are returned. The limit value must be an unsigned 32-bit integer. The default is 50. | Optional |
| search | Searches the names of all host sets connected to the specified HX appliance. | Optional |
| sort | Sorts the results by the specified field in ascending or descending order. The default is sorting by name in ascending order. Sortable fields are _id (host set ID) and name (host set name). | Optional |
| name | Specifies the name of host set to look for. | Optional |
| type | Specifies the type of host sets to search for. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.HostSets._id | number | host set id |
| FireEyeHX.HostSets._revision | string | Revision number |
| FireEyeHX.HostSets.name | string | Host set name |
| FireEyeHX.HostSets.type | string | Host set type (static/dynamic/hidden) |
| FireEyeHX.HostSets.url | string | Host set FireEye url |
Command Example
#### Context Example
```json
{
"FireEyeHX": {
"HostSets": {
"_id": 1001,
"_revision": "20210308150955358783164361",
"name": "Demisto",
"type": "venn",
"url": "/hx/api/v3/host_sets/1001"
}
}
}
Human Readable Output
FireEye HX Get Host Sets Information
Name ID Type Demisto 1001 venn
fireeye-hx-create-indicator
Create new indicator
Base Command
fireeye-hx-create-indicator
Input
| Argument Name | Description | Required |
|---|---|---|
| category | The indicator category. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Indicators.active_since | date | Date indicator became active. |
| FireEyeHX.Indicators.meta | string | Meta data for new indicator |
| FireEyeHX.Indicators.display_name | string | The indicator display name |
| FireEyeHX.Indicators.name | string | The indicator name as displayed in the UI. |
| FireEyeHX.Indicators.created_by | string | The “Created By” field as displayed in UI |
| FireEyeHX.Indicators.url | string | The data URL |
| FireEyeHX.Indicators.create_text | Unknown | The indicator create text |
| FireEyeHX.Indicators.platforms | string | List of families of operating systems. |
| FireEyeHX.Indicators.create_actor._id | number | The ID of the actor |
| FireEyeHX.Indicators.create_actor.username | string | Actor user name |
| FireEyeHX.Indicators.signature | string | Signature of indicator |
| FireEyeHX.Indicators._revision | string | Indicator revision |
| FireEyeHX.Indicators._id | string | FireEye unique indicator ID. |
| FireEyeHX.Indicator.description | string | Indicator description |
| FireEyeHX.Indicators.category._id | number | Category ID |
| FireEyeHX.Indicators.category.name | string | Category name |
| FireEyeHX.Indicators.category.share_mode | string | Category share mode |
| FireEyeHX.Indicators.category.uri_name | string | Category uri name |
| FireEyeHX.Indicators.category.url | string | Category URL |
| FireEyeHX.Indicators.uri_name | string | The indicator uri name |
| FireEyeHX.Indicators.stats.active_conditions | number | Indicator active conditions |
| FireEyeHX.Indicators.stats.alerted_agents | number | Total number of agents with HX alerts associated with this indicator. |
| FireEyeHX.Indicators.stats.source_alerts | number | Total number of source alerts associated with this indicator. |
| FireEyeHX.Indicators.update_actor._id | number | Update actor ID |
| FireEyeHX.Indicators.update_actor.username | string | Update actor name |
fireeye-hx-append-conditions
Add conditions to an indicator. Conditions can be MD5, hash values, domain names and IP addresses.
Base Command
fireeye-hx-append-conditions
Input
| Argument Name | Description | Required |
|---|---|---|
| category | The indicator category. Please use the uri_category value. |
Required |
| name | The name of the indicator. Please use the uri_name value. |
Required |
| condition | A list of conditions to add. The list can include a list of IPv4 addresses, MD5 files, and domain names. For example: example.netexample.orgexample.lol. | Required |
Context Output
There is no context output for this command.
fireeye-hx-get-all-hosts-information
Get information on all hosts
Base Command
fireeye-hx-get-all-hosts-information
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Hosts._id | Unknown | FireEye HX Agent ID. |
| FireEyeHX.Hosts.agent_version | Unknown | The agent version. |
| FireEyeHX.Hosts.excluded_from_containment | Unknown | Determines whether the host is excluded from containment. |
| FireEyeHX.Hosts.containment_missing_software | Unknown | Boolean value to indicate for containment missing software. |
| FireEyeHX.Hosts.containment_queued | Unknown | Determines whether the host is queued for containment. |
| FireEyeHX.Hosts.containment_state | Unknown | The containment state of the host. Possible values normal, contain, contain_fail, containing, contained, uncontain, uncontaining, wtfc, wtfu. |
| FireEyeHX.Hosts.stats.alerting_conditions | Unknown | The number of conditions that have alerted for the host. |
| FireEyeHX.Hosts.stats.alerts | Unknown | Total number of alerts, including exploit-detection alerts. |
| FireEyeHX.Hosts.stats.exploit_blocks | Unknown | The number of blocked exploits on the host. |
| FireEyeHX.Hosts.stats.malware_alerts | Unknown | The number of malware alerts associated with the host. |
| FireEyeHX.Hosts.hostname | Unknown | The host name. |
| FireEyeHX.Hosts.domain | Unknown | Domain name. |
| FireEyeHX.Hosts.timezone | Unknown | Host time zone. |
| FireEyeHX.Hosts.primary_ip_address | Unknown | The host IP address. |
| FireEyeHX.Hosts.last_poll_timestamp | Unknown | The timestamp of the last system poll preformed on the host. |
| FireEyeHX.Hosts.initial_agent_checkin | Unknown | Timestamp of the initial agent check-in. |
| FireEyeHX.Hosts.last_alert_timestamp | Unknown | The time stamp of the last alert for the host. |
| FireEyeHX.Hosts.last_exploit_block_timestamp | Unknown | Time when the last exploit was blocked on the host. The value is null if no exploits have been blocked. |
| FireEyeHX.Hosts.os.product_name | Unknown | Specific operating system |
| FireEyeHX.Hosts.os.bitness | Unknown | OS Bitness. |
| FireEyeHX.Hosts.os.platform | Unknown | Family of operating systems. Valid values are win, osx, and linux. |
| FireEyeHX.Hosts.primary_mac | Unknown | The host MAC address. |
Command Example
#### Context Example
```json
{
"Endpoint": [
{
"Domain": "WORKGROUP",
"Hostname": "WIN10X64",
"ID": "Hqb2ns3oui1fpzg0BxI1Ch",
"IPAddress": "1.1.1.1",
"MACAddress": "00-50-56-89-1c-5b",
"OS": "win",
"OSVersion": "Windows 10 Pro"
},
{
"Domain": "localdomain",
"Hostname": "localhost",
"ID": "GfLI00Q4zpidezw9I11rV6",
"IPAddress": "1.1.1.1",
"MACAddress": "00-50-56-89-e7-22",
"OS": "linux",
"OSVersion": "CentOS Linux 7 (Core)"
}
],
"FireEyeHX": {
"Hosts": {
"Agent ID": "GfLI00Q4zpidezw9I11rV6",
"Agent Version": "31.28.17",
"Containment State": "normal",
"Domain": "localdomain",
"Host IP": "1.1.1.1",
"Host Name": "localhost",
"Last Alert": null,
"Last Poll": "2021-10-18T14:02:32.000Z",
"OS": "linux"
}
}
}
Human Readable Output
FireEye HX Get Hosts Information
Host Name Host IP Agent ID Agent Version OS Last Poll Containment State Domain Last Alert WIN10X64 1.1.1.1 Hqb2ns3oui1fpzg0BxI1Ch 31.28.17 win 2021-10-18T13:59:44.000Z normal WORKGROUP _id: 2
url: /hx/api/v3/alerts/2localhost 1.1.1.1 GfLI00Q4zpidezw9I11rV6 31.28.17 linux 2021-10-18T14:02:32.000Z normal localdomain
fireeye-hx-initiate-data-acquisition
Initiate a data acquisition process to gather artifacts from the system disk and memory
Base Command
fireeye-hx-initiate-data-acquisition
Input
| Argument Name | Description | Required |
|---|---|---|
| script | Acquisition script in JSON format. | Optional |
| scriptName | The script name. If the Acquisition script is specified, the script name must be specified as well. | Optional |
| defaultSystemScript | Use default script. Select the host system. Possible values are: osx, win, linux. | Optional |
| agentId | The agent ID. If the host name is not specified, the agent ID must be specified. | Optional |
| hostName | The host name. If the agent ID is not specified, the host name must be specified. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeHX.Acquisitions.Data._id | unknown | The acquisition unique ID. |
| FireEyeHX.Acquisitions.Data.state | unknown | The acquisition state |
| FireEyeHX.Acquisitions.Data.md5 | unknown | File md5 |
| FireEyeHX.Acquisitions.Data.host._id | unknown | Agent ID |
| FireEyeHX.Acquisitions.Data.host.hostname | unknown | Hostname |
| FireEyeHX.Acquisitions.Data.instance | unknown | FIreEye HX instance |
| FireEyeHX.Acquisitions.Data.finish_time | unknown | Time when the acquisition finished |
Command Example
#### Human Readable Output
### fireeye-hx-get-data-acquisition
***
Gather artifacts from the system disk and memory for the given acquisition id. The data is fetched as mans file
#### Base Command
`fireeye-hx-get-data-acquisition`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| acquisitionId | The acquisition unique ID. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| FireEyeHX.Acquisitions.Data._id | unknown | The acquisition unique ID. |
| FireEyeHX.Acquisitions.Data.state | unknown | The acquisition state. |
| FireEyeHX.Acquisitions.Data.md5 | unknown | File md5. |
| FireEyeHX.Acquisitions.Data.host._id | unknown | Agent ID |
| FireEyeHX.Acquisitions.Data.finish_time | unknown | Time when the acquisition finished |
| FireEyeHX.Acquisitions.Data.host.hostname | unknown | Hostname |
| FireEyeHX.Acquisitions.Data.instance | unknown | FIreEye HX instance |
#### Command Example
Human Readable Output
Error Responses - Timeout Error
Timeout error indicates that time limitation for the command has exceeded before results are returned.
To resolve this issue, configure new time limitation for the command.
- Navigate to Settings > About > Troubleshooting > Server Configuration.
- click Add Server Configuration.
- Set the key field using this format: FireEye HX.<command-name>.timeout.
- Set the value field to the desired time limit for the command to run (in minutes).

Known Limitations
Acquisitions limitations
- Acquisitions are stored for 14 days or until the aggregate size of all acquisitions exceeds the acquisition space limit, which is from 30 GB to 9 TB, depending on the HX Series appliance.
- When the acquisition space is completely full and automatic triages fill 10 percent of the acquisition space, the HX Series appliance reclaims disk space by removing automatic triage collections.
- When the acquisition space is 90 percent full, no new acquisitions can be created, and bulk acquisitions that are running might be canceled.
Containment Limitations
- Some hosts cannot be contained.
- The time it takes to contain a host varies, based on factors such as agent connectivity, network traffic, and other jobs running in your environment.
- You can only contain a host if the agent package for that host is available on the HX Series appliance.
Command Timeout
The following commands have high potential to exceed the default time limit for a running command. To avoid command timeout, change the command timeout settings.
- fireeye-hx-search
- fireeye-hx-data-acquisition
- fireeye-hx-file-acquisition
Configure Command Timeout
- Navigate to Settings > About > Troubleshooting.
- In the Server Configuration section, click Add Server Configuration.
- Set the Key field using this format: FireEye HX.timeout
- Set the Value field to the timeout you need (in minutes).
Configuration parameters
server— Server URL (e.g. https://192.168.0.1:3000) (required)credentials— Credentials (required)version— Version (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsisFetch— Fetch incidentsincidentType— Incident typefetch_limit— Fetch limitincidentFetchInterval— Incidents Fetch Interval
Commands (19)
-
fireeye-hx-append-conditionsDeprecatedAdd conditions to an indicator. Conditions can be MD5, hash values, domain names and IP addresses.
-
fireeye-hx-cancel-containmentDeprecatedRelease a specific host from containment.
-
fireeye-hx-create-indicatorDeprecatedCreate new indicator.
-
fireeye-hx-data-acquisitionDeprecatedStart a data acquisition process to gather artifacts from the system disk and memory. The data is fetched as mans file.
-
fireeye-hx-delete-data-acquisitionDeprecatedDelete data acquisition.
-
fireeye-hx-delete-file-acquisitionDeprecatedDelete the file acquisition, by ID.
-
fireeye-hx-file-acquisitionDeprecatedAquire a specific file as a password protected zip file. The password for unlocking the zip file is 'unzip-me'.
-
fireeye-hx-get-alertDeprecatedGet details of a specific alert.
-
fireeye-hx-get-alertsDeprecatedGet a list of alerts, use the different arguments to filter the results returned.
-
fireeye-hx-get-all-hosts-informationDeprecatedGet information on all hosts.
-
fireeye-hx-get-data-acquisitionDeprecatedGather artifacts from the system disk and memory for the given acquisition id. The data is fetched as mans file.
-
fireeye-hx-get-host-informationDeprecatedGet information on a host associated with an agent.
-
fireeye-hx-get-host-set-informationDeprecatedGet a list of all host sets known to your HX Series appliance.
-
fireeye-hx-get-indicatorDeprecatedGet a specific indicator details.
-
fireeye-hx-get-indicatorsDeprecatedGet a list of indicators.
-
fireeye-hx-host-containmentDeprecatedApply containment for a specific host, so that it no longer has access to other systems.
-
fireeye-hx-initiate-data-acquisitionDeprecatedInitiate a data acquisition process to gather artifacts from the system disk and memory.
-
fireeye-hx-searchDeprecatedSearch endpoints to check all hosts or a subset of hosts for a specific file or indicator.
-
fireeye-hx-suppress-alertDeprecatedSuppress alert by ID.
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 """ IMPORTS """ import base64 import json import os import re import time import requests # disable insecure warnings requests.packages.urllib3.disable_warnings() """ HANDLE PROXY """ def set_proxies(): if not demisto.params().get('proxy', False): del os.environ['HTTP_PROXY'] del os.environ['HTTPS_PROXY'] del os.environ['http_proxy'] del os.environ['https_proxy'] """ GLOBAL VARS """ TOKEN = '' SERVER_URL = demisto.params()['server'] USERNAME = demisto.params()['credentials']['identifier'] PASSWORD = demisto.params()['credentials']['password'] PASSWORD = PASSWORD.encode('utf-8') USE_SSL = not demisto.params()['insecure'] VERSION = demisto.params()['version'] GET_HEADERS = { 'Accept': 'application/json' } POST_HEADERS = { 'Accept': 'application/json', 'Content-type': 'application/json' } PATCH_HEADERS = { 'Content-Type': 'text/plain' } BASE_PATH = '{}/hx/api/{}'.format(SERVER_URL, VERSION) INDICATOR_MAIN_ATTRIBUTES = [ 'OS', 'Name', 'Created By', 'Active Since', 'Category', 'Signature', 'Active Condition', 'Hosts With Alerts', 'Source Alerts' ] ALERT_MAIN_ATTRIBUTES = [ 'Alert ID', 'Reported', 'Event Type', 'Agent ID' ] HOST_MAIN_ATTRIBUTES = [ 'Host Name', 'Host IP', 'Agent ID', 'Agent Version', 'OS', 'Last Poll', 'Containment State', 'Domain', 'Last Alert' ] HOST_SET_MAIN_ATTRIBUTES = [ 'Name', 'ID', 'Type' ] # scripts for data acquisitions STANDART_INVESTIGATIVE_DETAILS_OSX = { "commands": [ { "name": "sysinfo" }, { "name": "disks" }, { "name": "volumes" }, { "name": "useraccounts" }, { "name": "groups" }, { "name": "files-api", "parameters": [ { "name": "Path", "value": "/" }, { "name": "Regex", "value": "^(?:Applications|Library|System|User|bin|cores|opt|private|sbin|usr)+" }, { "name": "Include Remote Locations", "value": False }, { "name": "Depth", "value": -1 }, { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "Verify Digital Signatures", "value": False }, { "name": "AND Operator", "value": False }, { "name": "Include Files", "value": True }, { "name": "Include Directories", "value": True }, { "name": "Preserve Times", "value": False } ] }, { "name": "persistence", "parameters": [ { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "Preserve Times", "value": False }, { "name": "Verify Digital Signatures", "value": False } ] }, { "name": "tasks", "parameters": [ { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "Verify Digital Signatures", "value": True }, { "name": "Preserve Times", "value": False } ] }, { "name": "processes-api" }, { "name": "urlhistory", "parameters": [ { "name": "TargetBrowser", "value": "Chrome" }, { "name": "TargetBrowser", "value": "Firefox" }, { "name": "TargetBrowser", "value": "Safari" } ] }, { "name": "quarantine-events" }, { "name": "ports" }, { "name": "services", "parameters": [ { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "Verify Digital Signatures", "value": True }, { "name": "Preserve Times", "value": False } ] }, { "name": "stateagentinspector", "parameters": [ { "name": "eventTypes", "value": [] } ] }, { "name": "syslog" } ] } STANDART_INVESTIGATIVE_DETAILS_LINUX = { "commands": [ { "name": "sysinfo" }, { "name": "files-api", "parameters": [ { "name": "Path", "value": "/" }, { "name": "Regex", "value": "^(?:usr|lib|lib64|opt|home|sbin|bin|etc|root)+" }, { "name": "Include Remote Locations", "value": False }, { "name": "Depth", "value": -1 }, { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "AND Operator", "value": False }, { "name": "Include Files", "value": True }, { "name": "Include Directories", "value": True }, { "name": "Preserve Times", "value": False } ] }, { "name": "processes-api" }, { "name": "ports" }, { "name": "shell-history", "parameters": [ { "name": "ShellList", "value": [ "bash", "zsh", "ksh93" ] } ] } ] } STANDART_INVESTIGATIVE_DETAILS_WIN = { "commands": [ { "name": "sysinfo" }, { "name": "disks", "parameters": [ { "name": "Prevent Hibernation", "value": True } ] }, { "name": "volumes", "parameters": [ { "name": "Prevent Hibernation", "value": True } ] }, { "name": "useraccounts", "parameters": [ { "name": "Prevent Hibernation", "value": True } ] }, { "name": "prefetch", "parameters": [ { "name": "Prevent Hibernation", "value": True } ] }, { "name": "files-raw", "parameters": [ { "name": "Prevent Hibernation", "value": True }, { "name": "Active Files", "value": True }, { "name": "Deleted Files", "value": True }, { "name": "Parse NTFS INDX Buffers", "value": True }, { "name": "Path", "value": "%systemdrive%" }, { "name": "Depth", "value": -1 }, { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "Analyze Entropy", "value": False }, { "name": "Enumerate Imports", "value": False }, { "name": "Enumerate Exports", "value": False }, { "name": "Analyze File Anomalies", "value": False }, { "name": "Verify Digital Signatures", "value": False }, { "name": "Strings", "value": False }, { "name": "AND Operator", "value": False }, { "name": "Include Files", "value": True }, { "name": "Include Directories", "value": True }, { "name": "Get Resources", "value": False }, { "name": "Get Resource Data", "value": False }, { "name": "Get Version Info", "value": False } ] }, { "name": "persistence", "parameters": [ { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "Preserve Times", "value": False }, { "name": "Enumerate Imports", "value": False }, { "name": "Enumerate Exports", "value": False }, { "name": "Verify Digital Signatures", "value": True }, { "name": "Analyze Entropy", "value": False }, { "name": "Analyze File Anomalies", "value": False }, { "name": "Get Resources", "value": False }, { "name": "Get Version Info", "value": False }, { "name": "Prevent Hibernation", "value": True } ] }, { "name": "registry-raw", "parameters": [ { "name": "Prevent Hibernation", "value": True }, { "name": "Type", "value": "All" } ] }, { "name": "tasks", "parameters": [ { "name": "Prevent Hibernation", "value": True }, { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "Verify Digital Signatures", "value": True }, { "name": "Preserve Times", "value": False }, { "name": "raw mode", "value": False } ] }, { "name": "eventlogs", "parameters": [ { "name": "Prevent Hibernation", "value": True } ] }, { "name": "processes-memory", "parameters": [ { "name": "Preserve Times", "value": False }, { "name": "Prevent Hibernation", "value": True }, { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "MemD5", "value": False }, { "name": "enumerate imports", "value": True }, { "name": "enumerate exports", "value": True }, { "name": "Verify Digital Signatures", "value": True }, { "name": "sections", "value": True }, { "name": "ports", "value": True }, { "name": "handles", "value": True }, { "name": "detect injected dlls", "value": True }, { "name": "raw mode", "value": False }, { "name": "strings", "value": False } ] }, { "name": "urlhistory", "parameters": [ { "name": "Prevent Hibernation", "value": True }, { "name": "GetThumbnails", "value": False }, { "name": "GetIndexedPageContent", "value": False } ] }, { "name": "ports", "parameters": [ { "name": "Prevent Hibernation", "value": True } ] }, { "name": "services", "parameters": [ { "name": "Prevent Hibernation", "value": True }, { "name": "MD5", "value": True }, { "name": "SHA1", "value": False }, { "name": "SHA256", "value": False }, { "name": "Verify Digital Signatures", "value": True }, { "name": "Preserve Times", "value": False }, { "name": "raw mode", "value": False } ] }, { "name": "stateagentinspector", "parameters": [ { "name": "eventTypes", "value": [] } ] } ] } SYS_SCRIPT_MAP = { 'osx': STANDART_INVESTIGATIVE_DETAILS_OSX, 'win': STANDART_INVESTIGATIVE_DETAILS_WIN, 'linux': STANDART_INVESTIGATIVE_DETAILS_LINUX } """ COMMAND HANDLERS """ def get_token_request(): """ returns a token on successful request """ url = '{}/token'.format(BASE_PATH) # basic authentication try: response = requests.request( 'GET', url, headers=GET_HEADERS, verify=USE_SSL, auth=(USERNAME, PASSWORD) ) except requests.exceptions.SSLError as e: LOG(e) raise ValueError('An SSL error occurred when trying to connect to the server.\ Consider configuring unsecure connection in the integration settings') # handle request failure if response.status_code not in range(200, 205): message = parse_error_response(response) raise ValueError('Token request failed with status code {}\n{}'.format(response.status_code, message)) # successful request response_headers = response.headers token = response_headers.get('X-FeApi-Token') return token def get_token(): token = get_token_request() if token: return token raise Exception('Failed to get a token, unexpected response structure from the server') """ HOST INFORMATION """ def get_host_by_agent_request(agent_id): """ returns the response body raises an exception on: - http request failure - response status code different from 200 """ url = '{}/hosts/{}'.format(BASE_PATH, agent_id) response = http_request( 'GET', url, headers=GET_HEADERS ) # successful request try: return response.json()['data'] except Exception as e: LOG(e) raise ValueError('Failed to get host information - unexpected response structure from the server.') def get_host_information(): """ return the host information to the war room, given an agentId or hostName from input. """ args = demisto.args() if not args.get('agentId') and not args.get('hostName'): raise ValueError('Please provide either agentId or hostName') host = {} # type: Dict[str, str] if args.get('agentId'): host = get_host_by_agent_request(args.get('agentId')) else: host = get_host_by_name_request(args.get('hostName')) md_table = tableToMarkdown( 'FireEye HX Get Host Information', host_entry(host), headers=HOST_MAIN_ATTRIBUTES ) entry = { 'Type': entryTypes['note'], 'Contents': host, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': md_table, 'EntryContext': { "FireEyeHX.Hosts(obj._id==val._id)": host, "Endpoint(obj.ID==val.ID)": collect_endpoint_contxt(host) } } demisto.results(entry) def get_hosts_information(): """ return the host information to the war room, given an agentId or hostName from input. """ offset = 0 hosts = [] # type: List[Dict[str, str]] # get all hosts while True: hosts_partial_results = get_hosts_request(offset=offset, limit=1000) if not hosts_partial_results: break hosts.extend(hosts_partial_results) offset = len(hosts) hosts_entry = [host_entry(host) for host in hosts] md_table = tableToMarkdown( 'FireEye HX Get Hosts Information', hosts_entry, headers=HOST_MAIN_ATTRIBUTES ) entry = { 'Type': entryTypes['note'], 'Contents': hosts, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': md_table, 'EntryContext': { "FireEyeHX.Hosts(obj._id==val._id)": hosts_entry, "Endpoint(obj.ID==val.ID)": [collect_endpoint_contxt(host)for host in hosts] } } demisto.results(entry) def get_host_set_information(): """ return host set information to the war room according to given id or filters """ args = demisto.args() url = '{}/host_sets/{}'.format(BASE_PATH, args.get('hostSetID', '')) url_params = { 'limit': args.get('limit'), 'offset': args.get('offset'), 'search': args.get('search'), 'sort': args.get('sort'), 'name': args.get('name'), 'type': args.get('type') } response = http_request( 'GET', url, headers=GET_HEADERS, url_params=url_params ) host_set = [] # type: List[Dict[str, str]] try: if args.get('hostSetID'): data = response.json()['data'] host_set = [data] else: data = response.json()['data'] host_set = data.get('entries', []) except Exception as e: LOG(e) raise ValueError('Failed to get host set information - unexpected response from the server.\n' + response.text) md_table = "No host sets found" if len(host_set) > 0: md_table = tableToMarkdown( 'FireEye HX Get Host Sets Information', host_set_entry(host_set), headers=HOST_SET_MAIN_ATTRIBUTES ) entry = { 'Type': entryTypes['note'], 'Contents': host_set, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': md_table, 'EntryContext': { "FireEyeHX.HostSets(obj._id==val._id)": host_set } } demisto.results(entry) def get_hosts_request(limit=None, offset=None, has_active_threats=None, has_alerts=None, agent_version=None, containment_queued=None, containment_state=None, host_name=None, os_platform=None, reported_clone=None, time_zone=None): """ returns the response body raises an exception on: - http request failure - response status code different from 200 """ url = '{}/hosts'.format(BASE_PATH) url_params = { 'limit': limit, 'offset': offset, 'has_active_threats': has_active_threats, 'has_alerts': has_alerts, 'agent_version': agent_version, 'containment_queued': containment_queued, 'containment_state': containment_state, 'hostname': host_name, 'os.platform': os_platform, 'reported_clone': reported_clone, 'time_zone': time_zone } # remove None values url_params = {k: v for k, v in url_params.items() if v is not None} response = http_request( 'GET', url, url_params=url_params, headers=GET_HEADERS ) # successful request try: return response.json()['data']['entries'] except Exception as e: LOG(e) raise ValueError('Failed to parse response body - unexpected response structure from the server.') def get_host_by_name_request(host_name): try: return get_hosts_request(host_name=host_name, limit=1)[0] except Exception as e: LOG(e) raise ValueError('Host {} not found.'.format(host_name)) def get_all_agents_ids(): """ returns a list of all agents ids """ offset = 0 hosts = [] # type: List[Dict[str, str]] # get all hosts while True: hosts_partial_results = get_hosts_request(offset=offset, limit=1000) if not hosts_partial_results: break hosts.extend(hosts_partial_results) offset = len(hosts) return [host.get('_id') for host in hosts] def get_agent_id(host_name): """ returns the agent id given the host name raises an exception on: - unexpected response structure - empty results """ host = get_host_by_name_request(host_name) try: return host['_id'] except Exception as e: LOG(e) raise ValueError('Failed to get agent id for host {}'.format(host_name)) def collect_endpoint_contxt(host): return { 'Hostname': host.get('hostname'), 'ID': host.get('_id'), 'IPAddress': host.get('primary_ip_address'), 'Domain': host.get('domain'), 'MACAddress': host.get('primary_mac'), 'OS': host.get('os', {}).get('platform'), 'OSVersion': host.get('os', {}).get('product_name') } """ HOST CONTAINMENT """ def containment_request(agent_id): """ no return value on successful request """ url = '{}/hosts/{}/containment'.format(BASE_PATH, agent_id) body = { 'state': 'contain' } try: api_version = int(VERSION[-1]) except Exception as exc: raise ValueError('Invalid version was set: {} - {}'.format(VERSION, str(exc))) if api_version >= 3: http_request( 'POST', url, headers=POST_HEADERS ) else: http_request( 'POST', url, body=body, headers=POST_HEADERS ) # no exception raised - successful request def containment(): """ returns a success message to the war room """ args = demisto.args() # validate one of the arguments was passed if not args: raise ValueError('Please provide either agentId or hostName') # in case a hostName was given, set the agentId accordingly if args.get('hostName'): args['agentId'] = get_agent_id(args['hostName']) containment_request(args['agentId']) # no exceptions raised->successful request host = get_host_by_agent_request(args['agentId']) entry = { 'Type': entryTypes['note'], 'Contents': 'Containment rquest for the host was sent and approved successfully', 'ContentsFormat': formats['text'], 'EntryContext': { "FireEyeHX.Hosts(obj._id==val._id)": host, "Endpoint(obj.ID==val.ID)": collect_endpoint_contxt(host) } } demisto.results(entry) def containment_cancellation_request(agent_id): """ no return value on successful request """ url = '{}/hosts/{}/containment'.format(BASE_PATH, agent_id) http_request( 'DELETE', url, headers=GET_HEADERS ) # no exceptions are raised - successful request def containment_cancellation(): """ returns a success message to the war room """ args = demisto.args() # validate one of the arguments was passed if not args: raise ValueError('Please provide either agentId or hostName') # in case a hostName was given, set the agentId accordingly if args.get('hostName'): args['agentId'] = get_agent_id(args['hostName']) containment_cancellation_request(args['agentId']) # no exceptions raised->successful request host = get_host_by_agent_request(args['agentId']) entry = { 'Type': entryTypes['note'], 'Contents': 'The host is released from containment.', 'ContentsFormat': formats['text'], 'EntryContext': { "FireEyeHX.Hosts(obj._id==val._id)": host, "Endpoint(obj.ID==val.ID)": collect_endpoint_contxt(host) } } demisto.results(entry) """ ALERTS """ def get_alert_request(alert_id): url = '{}/alerts/{}'.format(BASE_PATH, alert_id) response = http_request( 'GET', url, headers=GET_HEADERS ) return response.json().get('data') def get_alert(): alert_id = demisto.args().get('alertId') alert = get_alert_request(alert_id) alert_table = tableToMarkdown( 'FireEye HX Get Alert # {}'.format(alert_id), alert_entry(alert), headers=ALERT_MAIN_ATTRIBUTES ) event_type = alert.get('event_type') event_type = 'NewEvent' if not event_type else event_type event_type = re.sub("([a-z])([A-Z])", "\g<1> \g<2>", event_type).title() event_table = tableToMarkdown( event_type, alert.get('event_values') ) entry = { 'Type': entryTypes['note'], 'Contents': alert, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': u'{}\n{}'.format(alert_table, event_table), 'EntryContext': { "FireEyeHX.Alerts(obj._id==val._id)": alert } } demisto.results(entry) def get_alerts_request(has_share_mode=None, resolution=None, agent_id=None, host_name=None, condition_id=None, limit=None, offset=None, sort=None, min_id=None, event_at=None, alert_id=None, matched_at=None, reported_at=None, source=None): """ returns the response body on successful request """ url = '{}/alerts'.format(BASE_PATH) body = { 'has_share_mode': has_share_mode, 'resolution': resolution, 'agent._id': agent_id, 'condition._id': condition_id, 'event_at': event_at, 'min_id': min_id, '_id': alert_id, 'matched_at': matched_at, 'reported_at': reported_at, 'source': source, 'limit': limit, 'offset': offset, 'sort': sort } # remove None values body = {k: v for k, v in body.items() if v is not None} response = http_request( 'GET', url, url_params=body, headers=GET_HEADERS ) try: return response.json()['data']['entries'] except Exception as e: LOG(e) raise ValueError('Failed to parse response body') def get_all_alerts(has_share_mode=None, resolution=None, agent_id=None, condition_id=None, limit=None, sort=None, min_id=None, event_at=None, alert_id=None, matched_at=None, reported_at=None, source=None): """ returns a list of alerts, all results up to limit """ offset = 0 alerts = [] # type: List[Dict[str, str]] max_records = limit or float('inf') while len(alerts) < max_records: alerts_partial_results = get_alerts_request( has_share_mode=has_share_mode, resolution=resolution, agent_id=agent_id, condition_id=condition_id, event_at=event_at, alert_id=alert_id, matched_at=matched_at, reported_at=reported_at, source=source, min_id=min_id, offset=offset, limit=limit or 100, sort=sort ) # empty list if not alerts_partial_results: break alerts.extend(alerts_partial_results) offset = len(alerts) # remove access results if len(alerts) > max_records: alerts[int(max_records) - 1: -1] = [] return alerts def general_context_from_event(alert): def file_context(values): return { 'Name': values.get('fileWriteEvent/fileName'), 'MD5': values.get('fileWriteEvent/md5'), 'Extension': values.get('fileWriteEvent/fileExtension'), 'Path': values.get('fileWriteEvent/fullPath') } def ip_context(values): return { 'Address': values.get('ipv4NetworkEvent/remoteIP') } def registry_key_context(values): return { 'Path': values.get('regKeyEvent/path'), 'Name': values.get('regKeyEvent/valueName'), 'Value': values.get('regKeyEvent/value') } context_map = { 'fileWriteEvent': file_context, 'ipv4NetworkEvent': ip_context, 'regKeyEvent': registry_key_context } if context_map.get(alert['event_type']) is not None: f = context_map[alert['event_type']] return f(alert['event_values']) return None def collect_context(alerts): # collect_context files = [] ips = [] registry_keys = [] for alert in alerts: event_type = alert.get('event_type') context = general_context_from_event(alert) if event_type == 'fileWriteEvent': files.append(context) elif event_type == 'ipv4NetworkEvent': ips.append(context) elif event_type == 'regKeyEvent': registry_keys.append(context) return (files, ips, registry_keys) def get_alerts(): """ returns a list of alerts to the war room """ args = demisto.args() source = [] # add source type if args.get('MALsource'): source.append('mal') if args.get('EXDsource'): source.append('exd') if args.get('IOCsource'): source.append('ioc') sort_map = { 'agentId': 'agent._id', 'conditionId': 'condition._id', 'eventAt': 'event_at', 'alertId': '_id', 'matchedAt': 'matched_at', 'id': '_id', 'reportedAt': 'reported_at' } if args.get('sort'): args['sort'] = '{}+{}'.format(sort_map.get(args['sort']), args.get('sortOrder', 'ascending')) if args.get('hostName'): args['agentId'] = get_agent_id(args.get('hostName')) if args.get('limit'): args['limit'] = int(args['limit']) alerts = get_all_alerts( has_share_mode=args.get("hasShareMode"), resolution=args.get('resolution'), agent_id=args.get('agentId'), condition_id=args.get('conditionId'), event_at=args.get('eventAt'), alert_id=args.get('alertId'), matched_at=args.get('matchedAt'), reported_at=args.get('reportedAt'), source=source, min_id=args.get('min_id'), limit=args.get('limit'), sort=args.get('sort') ) # parse each alert to a record displayed in the human readable table alerts_entries = [alert_entry(alert) for alert in alerts] files, ips, registry_keys = collect_context(alerts) md_table = tableToMarkdown( 'FireEye HX Get Alerts', alerts_entries, headers=ALERT_MAIN_ATTRIBUTES ) entry = { 'Type': entryTypes['note'], 'Contents': alerts, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': md_table, 'EntryContext': { "FireEyeHX.Alerts(obj._id==val._id)": alerts, 'File': files, 'RegistryKey': registry_keys, 'IP': ips } } demisto.results(entry) def suppress_alert_request(alert_id): """ no return value on successful request """ url = '{}/alerts/{}'.format(BASE_PATH, alert_id) http_request( 'DELETE', url ) def suppress_alert(): """ returns a success message to the war room """ alert_id = demisto.args().get('alertId') suppress_alert_request(alert_id) # no exceptions raised->successful request entry = { 'Type': entryTypes['note'], 'Contents': 'Alert {} suppressed successfully.'.format(alert_id), 'ContentsFormat': formats['text'] } demisto.results(entry) """ INDICATORS """ def new_indicator_request(category): """ Create a new indicator """ url = '{}/indicators/{}'.format(BASE_PATH, category) response = http_request( 'POST', url, headers=GET_HEADERS ) try: return response.json().get('data') except Exception as e: LOG(e) raise ValueError('Failed to parse response body, unexpected response structure from the server.') def create_indicator(): """ Get new indicator details returns a success message to the war room """ category = demisto.args().get('category') response = new_indicator_request(category) md_table = { 'ID': response.get('_id'), } entry = { 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('FireEye HX New Indicator created successfully', md_table), 'EntryContext': { "FireEyeHX.Indicators(obj._id===val._id)": response } } demisto.results(entry) def append_conditions_request(name, category, body): """ Append conditions to indicator request """ url = '{}/indicators/{}/{}/conditions'.format(BASE_PATH, category, name) response = http_request( 'PATCH', url, conditions_params=body, headers=PATCH_HEADERS ) return response.json() def append_conditions(): """ Append conditions to indicator no return value on successfull request """ name = demisto.args().get('name') category = demisto.args().get('category') body = demisto.args().get('condition') body = body.replace(',', '\n') response = append_conditions_request(name, category, body) md_table = { 'Name': name, 'Category': category, 'Conditions': body } entry = { 'Type': entryTypes['note'], 'Contents': response, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': tableToMarkdown('The conditions were added successfully', md_table) } demisto.results(entry) def get_indicator_request(category, name): """ returns a json object representing an indicator """ url = '{}/indicators/{}/{}'.format(BASE_PATH, category, name) response = http_request( 'GET', url, headers=GET_HEADERS, ) return response.json().get('data') def get_indicator_conditions_request(category, name, limit=None, offset=None, enabled=None, has_alerts=None): """ returns a list of json objects, each representing an indicator condition if no results are found- returns None """ url = '{}/indicators/{}/{}/conditions'.format(BASE_PATH, category, name) url_params = { 'limit': limit, 'offset': offset, 'enabled': enabled, 'has_alerts': has_alerts } # remove None values url_params = {k: v for k, v in url_params.items() if v is not None} response = http_request( 'GET', url, headers=GET_HEADERS, url_params=url_params ) try: return response.json()['data']['entries'] except Exception as e: LOG(e) raise ValueError('Failed to parse response body') def get_all_enabled_conditions(indicator_category, indicator_name): offset = 0 conditions = [] # type: List[Dict[str, str]] # get all results while True: conditions_partial_results = get_indicator_conditions_request( indicator_category, indicator_name, enabled=True, offset=offset ) if not conditions_partial_results: break conditions.extend(conditions_partial_results) offset = len(conditions) return conditions def get_indicator_conditions(): """ returns a list of enabled conditions assosiated with a specific indicator to the war room """ args = demisto.args() conditions = get_all_enabled_conditions( args.get('category'), args.get('name') ) conditions_entries = [condition_entry(condition) for condition in conditions] md_table = tableToMarkdown( 'Indicator "{}" Alerts on'.format(args.get('name')), conditions_entries ) entry = { 'Type': entryTypes['note'], 'Contents': conditions, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': md_table, 'EntryContext': { "FireEyeHX.Conditions(obj._id==val._id)": conditions } } demisto.results(entry) def get_indicator(): args = demisto.args() indicator = get_indicator_request( args.get('category'), args.get('name') ) md_table = tableToMarkdown( 'FireEye HX Get Indicator- {}'.format(args.get('name')), indicator_entry(indicator), headers=INDICATOR_MAIN_ATTRIBUTES ) entry = { 'Type': entryTypes['note'], 'Contents': indicator, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': md_table, 'EntryContext': { "FireEyeHX.Indicators(obj._id==val._id)": indicator } } demisto.results(entry) def get_indicators_request(category=None, search=None, limit=None, offset=None, share_mode=None, sort=None, created_by=None, alerted=None): url = '{}/indicators'.format(BASE_PATH) if category: url = url + '/' + category url_params = { 'search': search, 'limit': limit, 'offset': offset, 'category.share_mode': share_mode, 'sort': sort, 'created_by': created_by, 'stats.alerted_agents': alerted } # remove None value url_params = {k: v for k, v in url_params.items() if v} response = http_request( 'GET', url, url_params=url_params, headers=GET_HEADERS, ) try: response_body = response.json() data = response_body['data'] # no results found if data['total'] == 0: return None return data['entries'] except Exception as e: LOG(e) raise ValueError('Failed to parse response body') def get_all_indicators(category=None, search=None, share_mode=None, sort=None, created_by=None, alerted=None, limit=None): max_records = limit or float('inf') offset = 0 indicators = [] # type: List[Dict[str, str]] # get all results while len(indicators) < max_records: indicators_partial_results = get_indicators_request( category=category, search=search, offset=offset, share_mode=share_mode, sort=sort, created_by=created_by, alerted=alerted, limit=limit or 100 ) if not indicators_partial_results: break indicators.extend(indicators_partial_results) offset = len(indicators) # remove access results if len(indicators) > max_records: indicators[int(max_records) - 1: -1] = [] return indicators def get_indicators(): args = demisto.args() sort_map = { 'category': 'category', 'activeSince': 'active_since', 'createdBy': 'created_by', 'alerted': 'stats.alerted_agents' } if args.get('limit'): args['limit'] = int(args['limit']) if args.get('alerted'): args['alerted'] = args['alerted'] == 'yes' if args.get('sort'): args['sort'] = sort_map.get(args.get('sort')) # get all results indicators = get_all_indicators( category=args.get('category'), search=args.get('searchTerm'), share_mode=args.get('shareMode'), sort=args.get('sort'), created_by=args.get('createdBy'), alerted=args.get('alerted'), limit=args.get('limit') ) indicators_entries = [indicator_entry(indicator) for indicator in indicators] md_table = tableToMarkdown( 'FireEye HX Get Indicator- {}'.format(args.get('name')), indicators_entries, headers=INDICATOR_MAIN_ATTRIBUTES ) entry = { 'Type': entryTypes['note'], 'Contents': indicators, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': md_table, 'EntryContext': { "FireEyeHX.Indicators(obj._id==val._id)": indicators } } demisto.results(entry) """ SEARCH """ def search_request(query, host_set=None, hosts=None, exhaustive=False): url = '{}/searches'.format(BASE_PATH) body = {'query': query} if host_set: body['host_set'] = {'_id': int(host_set)} elif hosts: body['hosts'] = [{'_id': host} for host in hosts] if exhaustive: body['exhaustive'] = True try: response = http_request( 'POST', url, headers=POST_HEADERS, body=body ) except Exception as e: raise e if response.status_code == 409: raise ValueError('Request unsuccessful because the search limits \ (10 existing searches or 5 running searches) have been exceeded') return response.json().get('data') def get_search_information_request(search_id): """ returns the search information represented by a json object. """ url = '{}/searches/{}'.format(BASE_PATH, search_id) response = http_request( 'GET', url, headers=GET_HEADERS ) return response.json().get('data') def get_search_results_request(search_id): """ returns the search results represented by a json object. """ url = '{}/searches/{}/results'.format(BASE_PATH, search_id) response = http_request( 'GET', url, headers=GET_HEADERS ) return response.json().get('data', {}).get('entries', []) def stop_search_request(search_id): """ returns the search information represented by a json object. """ url = '{}/searches/{}/actions/stop'.format(BASE_PATH, search_id) response = http_request( 'POST', url, headers=POST_HEADERS ) return response.json() def delete_search_request(search_id): """ no return value on successful request """ url = '{}/searches/{}'.format(BASE_PATH, search_id) http_request( 'DELETE', url ) def search_results_to_context(results, search_id): for res in results: res["SearchID"] = search_id res["HostID"] = res.get("host", {}).get("_id") res["HostName"] = res.get("host", {}).get("hostname") res["HostUrl"] = res.get("host", {}).get("url") del res['host'] res["Results"] = res.get("results") del res["results"] for resData in res.get("Results"): resData.update(resData.get("data", {})) del resData['data'] return results def start_search(): args = demisto.args() ''' to search all hosts past none of the arguments? # validate at list one of the arguments 'agentsIds', 'hostsNames', 'hostSet' was passed if not any([args.get('agentsIds'), args.get('hostsNames'), args.get('hostSet'), args.get('searchAllHosts')]): raise ValueError('Please provide one of the followings: agentsIds, hostsNames, hostSet') ''' agents_ids = [] # type: List[Dict[str, str]] if args.get('agentsIds'): agents_ids = args['agentsIds'].split(',') elif args.get('hostsNames'): names = args.get('hostsNames').split(',') for name in names: try: agent_id = get_agent_id(name) agents_ids.append(agent_id) except Exception as e: LOG(e) pass if not agents_ids: raise ValueError('None of the host names were matched with an agent') # limit can't exceed 1000. limit = args.get('limit') if not limit or limit > 1000: limit = 1000 arg_to_query_field_map = { 'dnsHostname': 'DNS Hostname', 'fileFullPath': 'File Full Path', 'fileMD5Hash': 'File MD5 Hash', 'ipAddress': 'IP Address' } query = [] for arg in arg_to_query_field_map.keys(): if not args.get(arg): continue field_filter = { 'field': arg_to_query_field_map[arg], 'operator': args['{}Operator'.format(arg)], 'value': args[arg] } query.append(field_filter) search = search_request( query, hosts=agents_ids, host_set=args.get('hostSet'), exhaustive=args.get('exhaustive') == 'yes' ) search_id = search.get('_id') ''' loop to get search status once a minute. break on: search has stopped, matched results exceeded limit, or no more pending hosts. ''' while True: search_info = get_search_information_request(search_id) matched = search_info.get('stats', {}).get('search_state', {}).get('MATCHED', 0) pending = search_info.get('stats', {}).get('search_state', {}).get('PENDING', 0) if search_info.get('state') == 'STOPPED' or matched >= limit or pending == 0: break time.sleep(60) # pylint: disable=sleep-exists results = get_search_results_request(search_id) md_entries = [host_results_md_entry(host_results) for host_results in results] entry = { 'Type': entryTypes['note'], 'Contents': results, 'ContentsFormat': formats['json'], 'ReadableContentsFormat': formats['markdown'], 'HumanReadable': '## Search Results\n' + '\n'.join(md_entries), 'EntryContext': { "FireEyeHX.Search": search_results_to_context(results, search_id) } } demisto.results(entry) # finally stop or delete the search possible_error_message = None try: if args.get('stopSearch') == 'stop': possible_error_message = 'Failed to stop search' stop_search_request(search_id) # no need to stop a search before deleting it. if args.get('stopSearch') == 'stopAndDelete': possible_error_message = 'Failed to delete search' delete_search_request(search_id) possible_error_message = None except Exception as e: LOG('{}\n{}'.format(possible_error_message, e)) pass # add warning entry if necessary if possible_error_message: warning_entry = { 'Type': entryTypes['note'], 'Contents': possible_error_message, 'ContentsFormat': formats['text'], } demisto.results(warning_entry) """ ACQUISITIONS """ def file_acquisition_request(agent_id, file_name, file_path, comment=None, external_id=None, req_use_api=None): url = '{}/hosts/{}/files'.format(BASE_PATH, agent_id) body = { 'req_path': file_path, 'req_filename': file_name, 'comment': comment, 'external_id': external_id, 'req_use_api': req_use_api } # remove None values body = {k: v for k, v in body.items() if v is not None} response = http_request( 'POST', url, body=body, headers=POST_HEADERS ) return response.json().get('data') def file_acquisition_package_request(acquisition_id): url = '{}/acqs/files/{}.zip'.format(BASE_PATH, acquisition_id) response = http_request( 'GET', url ) return response.content def file_acquisition_information_request(acquisition_id): url = '{}/acqs/files/{}'.format(BASE_PATH, acquisition_id) response = http_request( 'GET', url, headers=GET_HEADERS ) return response.json().get('data') def delete_file_acquisition_request(acquisition_id): """ no return value on successful request """ url = '{}/acqs/files/{}'.format(BASE_PATH, acquisition_id) http_request( 'DELETE', url ) def delete_file_acquisition(): """ returns a success message to the war room """ acquisition_id = demisto.args().get('acquisitionId') delete_file_acquisition_request(acquisition_id) # successful request return { 'Type': entryTypes['note'], 'Contents': 'file acquisition {} deleted successfully'.format(acquisition_id), 'ContentsFormat': formats['text'], } def file_acquisition(): args = demisto.args() if not args.get('hostName') and not args.get('agentId'): raise ValueError('Please provide either agentId or hostName') if args.get('hostName'): args['agentId'] = get_agent_id(args['hostName']) use_api = args.get('acquireUsing') == 'API' acquisition_info = file_acquisition_request( args.get('agentId'), args.get('fileName'), args.get('filePath'), req_use_api=use_api ) acquisition_id = acquisition_info.get('_id') LOG('acquisition request was successful. Waiting for acquisition process to be complete.') while True: acquisition_info = file_acquisition_information_request(acquisition_id) state = acquisition_info.get('state') if state in ['COMPLETE', 'ERROR', 'FAILED']: break time.sleep(10) # pylint: disable=sleep-exists LOG('acquisition process has been complete. Fetching zip file.') acquired_file = file_acquisition_package_request(acquisition_id) message = '{} acquired successfully'.format(args.get('fileName')) if acquisition_info.get('error_message'): message = acquisition_info.get('error_message') entry = { 'Type': entryTypes['note'], 'Contents': '{}\nacquisition ID: {}'.format(message, acquisition_id), 'ContentsFormat': formats['text'], 'EntryContext': { "FireEyeHX.Acquisitions.Files(obj._id==val._id)": acquisition_info } } demisto.results(entry) demisto.results(fileResult('{}.zip'.format(os.path.splitext(args.get('fileName'))[0]), acquired_file)) def data_acquisition_request(agent_id, script_name, script): url = '{}/hosts/{}/live'.format(BASE_PATH, agent_id) body = { 'name': script_name, 'script': {'b64': script} } response = http_request( 'POST', url, body=body ) return response.json()['data'] def data_acquisition_information_request(acquisition_id): url = '{}/acqs/live/{}'.format(BASE_PATH, acquisition_id) response = http_request( 'GET', url, headers=GET_HEADERS ) return response.json()['data'] def data_collection_request(acquisition_id): url = '{}/acqs/live/{}.mans'.format(BASE_PATH, acquisition_id) response = http_request( 'GET', url ) return response.content def data_acquisition(): """ returns the mans file to the war room """ args = demisto.args() # validate the host name or agent ID was passed if not args.get('hostName') and not args.get('agentId'): raise ValueError('Please provide either agentId or hostName') if not args.get('defaultSystemScript') and not args.get('script'): raise ValueError('If the script is not provided, defaultSystemScript must be specified.') if args.get('script') and not args.get('scriptName'): raise ValueError('If the script is provided, script name must be specified as well.') if args.get('hostName'): args['agentId'] = get_agent_id(args['hostName']) # determine whether to use the default script sys = args.get('defaultSystemScript') if sys: args['script'] = json.dumps(SYS_SCRIPT_MAP[sys]) args['scriptName'] = '{}DefaultScript'.format(sys) acquisition_info = data_acquisition_request( args['agentId'], args['scriptName'], base64.b64encode(args['script']) ) acquisition_id = acquisition_info.get('_id') LOG('Acquisition request was successful. Waiting for acquisition process to be complete.') # loop to inquire acquisition state every 30 seconds # break when state is complete while True: acquisition_info = data_acquisition_information_request(acquisition_id) if acquisition_info.get('state') == 'COMPLETE': break time.sleep(30) # pylint: disable=sleep-exists LOG('Acquisition process has been complete. Fetching mans file.') message = '{} acquired successfully'.format(args.get('fileName')) if acquisition_info.get('error_message'): message = acquisition_info.get('error_message') # output file and acquisition information to the war room data = data_collection_request(acquisition_id) entry = { 'Type': entryTypes['note'], 'Contents': '{}\nacquisition ID: {}'.format(message, acquisition_id), 'ContentsFormat': formats['text'], 'EntryContext': { "FireEyeHX.Acquisitions.Data(obj._id==val._id)": acquisition_info } } demisto.results(entry) demisto.results(fileResult('agent_{}_data.mans'.format(args['agentId']), data)) def initiate_data_acquisition(): """ Initiate data acquisition """ args = demisto.args() # validate the host name or agent ID was passed if not args.get('hostName') and not args.get('agentId'): raise ValueError('Please provide either agentId or hostName') if not args.get('defaultSystemScript') and not args.get('script'): raise ValueError('If the script is not provided, defaultSystemScript must be specified.') if args.get('script') and not args.get('scriptName'): raise ValueError('If the script is provided, script name must be specified as well.') if args.get('hostName'): args['agentId'] = get_agent_id(args['hostName']) # determine whether to use the default script sys = args.get('defaultSystemScript') if sys: args['script'] = json.dumps(SYS_SCRIPT_MAP[sys]) args['scriptName'] = '{}DefaultScript'.format(sys) acquisition_info = data_acquisition_request( args['agentId'], args['scriptName'], base64.b64encode(bytes(args['script'], 'utf-8')).decode() ) # Add hostname to the host info of acquisition_info acquisition_info["host"]["hostname"] = args.get('hostName') # Add Integration Instance to the acquisition_info acquisition_info["instance"] = demisto.integrationInstance() entry = { 'Type': entryTypes['note'], 'Contents': 'Acquisition ID: {} on Instance: {}'.format(acquisition_info.get('_id'), demisto.integrationInstance()), 'ContentsFormat': formats['text'], 'EntryContext': { "FireEyeHX.Acquisitions.Data(obj._id==val._id && obj.instance==val.instance)": acquisition_info } } demisto.results(entry) def get_data_acquisition(): """ Wait for acquisition process to complete and fetch the data """ args = demisto.args() # validate the acquisitionId was passed if not args.get('acquisitionId'): raise ValueError('Please provide acquisitionId') acquisition_id = args.get("acquisitionId") acquisition_info = data_acquisition_information_request(acquisition_id) agent_id = acquisition_info.get('host').get('_id') host_info = get_host_by_agent_request(agent_id) hostname = host_info.get('hostname') # Add hostname to the host info of acquisition_info acquisition_info["host"]["hostname"] = hostname # Add Integration Instance to the acquisition_info acquisition_info["instance"] = demisto.integrationInstance() # if `state` equals to 'COMPLETE' if acquisition_info.get('state') == 'COMPLETE': message = 'Acquisition completed successfully.' if acquisition_info.get('error_message'): message = acquisition_info.get('error_message') # output file and acquisition information to the war room data = data_collection_request(acquisition_id) entry = { 'Type': EntryType.NOTE, 'Contents': '{}\nacquisition ID: {}'.format(message, acquisition_id), 'ContentsFormat': EntryFormat.TEXT, 'EntryContext': { 'FireEyeHX.Acquisitions.Data(obj._id==val._id)': acquisition_info } } demisto.results(entry) demisto.results(fileResult('{}_agent_{}_data.mans'.format(acquisition_id, agent_id), data)) return # else return message for states in [ NEW, ERROR, QUEUED, RUNNING, FAILED ] state = acquisition_info.get('state') message = "Acquisition process not yet completed." if acquisition_info.get('error_message'): message = acquisition_info.get('error_message') entry = { 'Type': EntryType.NOTE, 'Contents': '{}\nacquisition ID: {}\nstate: {}'.format(message, acquisition_id, state), 'ContentsFormat': EntryFormat.TEXT, 'EntryContext': { 'FireEyeHX.Acquisitions.Data(obj._id==val._id && obj.instance==val.instance)': acquisition_info } } demisto.results(entry) def delete_data_acquisition_request(acquisition_id): """ no return value on successful request """ url = '{}/acqs/live/{}'.format(BASE_PATH, acquisition_id) http_request( 'DELETE', url ) def delete_data_acquisition(): """ returns a success message to the war room """ acquisition_id = demisto.args().get('acquisitionId') delete_data_acquisition_request(acquisition_id) # successful request return { 'Type': entryTypes['note'], 'Contents': 'data acquisition {} deleted successfully'.format(acquisition_id), 'ContentsFormat': formats['text'], } """ FETCH INCIDENTS """ def fetch_incidents(): last_run = demisto.getLastRun() alerts = [] # type: List[Dict[str, str]] fetch_limit = int(demisto.params().get('fetch_limit') or '100') if last_run and last_run.get('min_id'): # get all alerts with id greater than min_id alerts = get_all_alerts( min_id=last_run.get('min_id'), sort='_id+ascending', limit=fetch_limit ) # results are sorted in ascending order - the last alert holds the greatest id min_id = alerts[-1].get('_id') if alerts else None else: # get the last 100 alerts alerts = get_all_alerts( sort='_id+descending', limit=fetch_limit ) # results are sorted in descending order - the first alert holds the greatest id min_id = alerts[0].get('_id') if alerts else None incidents = [parse_alert_to_incident(alert) for alert in alerts] demisto.incidents(incidents) if min_id is not None: demisto.setLastRun({'min_id': min_id}) @logger def parse_alert_to_incident(alert): event_type = alert.get('event_type') event_type = 'NewEvent' if not event_type else event_type event_values = alert.get('event_values', {}) event_indicators_map = { 'fileWriteEvent': 'fileWriteEvent/fileName', 'ipv4NetworkEvent': 'ipv4NetworkEvent/remoteIP', 'dnsLookupEvent': 'dnsLookupEvent/hostname', 'regKeyEvent': 'regKeyEvent/valueName' } event_indicator = event_indicators_map.get(event_type) event_indicator = 'No Indicator' if not event_indicator else event_indicator indicator = '' if isinstance(event_values, dict): indicator = event_values.get(event_indicator, '') incident_name = u'{event_type_parsed}: {indicator}'.format( event_type_parsed=re.sub("([a-z])([A-Z])", "\g<1> \g<2>", event_type).title(), indicator=indicator ) incident = { 'name': incident_name, 'rawJSON': json.dumps(alert) } return incident """ ENTRY ENTITIES """ def indicator_entry(indicator): indicator_entry = { 'OS': ', '.join(indicator.get('platforms', [])), 'Name': indicator.get('name'), 'Created By': indicator.get('created_by'), 'Active Since': indicator.get('active_since'), 'Category': indicator.get('category', {}).get('name'), 'Signature': indicator.get('signature'), 'Active Condition': indicator.get('stats', {}).get('active_conditions'), 'Hosts With Alerts': indicator.get('stats', {}).get('alerted_agents'), 'Source Alerts': indicator.get('stats', {}).get('source_alerts') } return indicator_entry def host_entry(host): host_entry = { 'Host Name': host.get('hostname'), 'Last Poll': host.get('last_poll_timestamp'), 'Agent ID': host.get('_id'), 'Agent Version': host.get('agent_version'), 'Host IP': host.get('primary_ip_address'), 'OS': host.get('os', {}).get('platform'), 'Containment State': host.get('containment_state'), 'Domain': host.get('domain'), 'Last Alert': host.get('last_alert') } return host_entry def host_set_entry(host_sets): host_set_entries = [{ 'Name': host_set.get('name'), 'ID': host_set.get('_id'), 'Type': host_set.get('type') } for host_set in host_sets] return host_set_entries def alert_entry(alert): alert_entry = { 'Alert ID': alert.get('_id'), 'Reported': alert.get('reported_at'), 'Event Type': alert.get('event_type'), 'Agent ID': alert.get('agent', {}).get('_id') } return alert_entry def condition_entry(condition): indicator_entry = { 'Event Type': condition.get('event_type'), 'Operator': condition.get('tests', {})[0].get('operator'), 'Value': condition.get('tests', {})[0].get('value'), } return indicator_entry def host_results_md_entry(host_entry): results = host_entry.get('results', []) host_info = host_entry.get('host', {}) entries = [] for result in results: data = result.get('data', {}) entry = { 'Item Type': result.get('type'), 'Summary': ' '.join(['**{}** {}'.format(k, v) for k, v in data.items()]) } entries.append(entry) md_table = tableToMarkdown( host_info.get('hostname'), entries, headers=['Item Type', 'Summary'] ) return md_table """ ADDITIONAL FUNCTIONS """ def http_request(method, url, body=None, headers={}, url_params=None, conditions_params=None): """ returns the http response """ # add token to headers headers['X-FeApi-Token'] = TOKEN request_kwargs = { 'headers': headers, 'verify': USE_SSL } # add optional arguments if specified if body: # request_kwargs['data'] = ' '.join(format(x, 'b') for x in bytearray(json.dumps(body))) request_kwargs['data'] = json.dumps(body) if url_params: request_kwargs['params'] = url_params if conditions_params: request_kwargs['data'] = conditions_params LOG('attempting {} request sent to {} with arguments:\n{}'.format(method, url, json.dumps(request_kwargs, indent=4))) try: response = requests.request( method, url, **request_kwargs ) except requests.exceptions.SSLError as e: LOG(e) raise ValueError('An SSL error occurred when trying to connect to the server. Consider configuring unsecure connection in \ the integration settings.') # handle request failure if response.status_code not in range(200, 205): message = parse_error_response(response) raise ValueError('Request failed with status code {}\n{}'.format(response.status_code, message)) return response def logout(): url = '{}/token'.format(BASE_PATH) try: http_request( 'DELETE', url ) except ValueError as e: LOG('Failed to logout with token') raise e LOG('logout successfully') def parse_error_response(response): try: res = response.json() msg = res.get('message') if res.get('details') is not None and res.get('details')[0].get('message') is not None: msg = msg + "\n" + json.dumps(res.get('details')[0]) except Exception as e: LOG(e) return response.text return msg def return_error_entry(message): error_entry = { 'Type': entryTypes['error'], 'Contents': message, 'ContentsFormat': formats['text'] } demisto.results(error_entry) """ EXECUTION """ def main(): global TOKEN set_proxies() command = demisto.command() LOG('Running command "{}"'.format(command)) # ask for a token using user credentials TOKEN = get_token() try: if command == 'test-module': # token generated - credentials are valid demisto.results('ok') elif command == 'fetch-incidents': fetch_incidents() elif command == 'fireeye-hx-get-alerts': get_alerts() elif command == 'fireeye-hx-cancel-containment': containment_cancellation() elif command == 'fireeye-hx-host-containment': containment() elif command == 'fireeye-hx-create-indicator': create_indicator() elif command == 'fireeye-hx-get-indicator': get_indicator() get_indicator_conditions() elif command == 'fireeye-hx-get-indicators': get_indicators() elif command == 'fireeye-hx-suppress-alert': suppress_alert() elif command == 'fireeye-hx-get-host-information': get_host_information() elif command == 'fireeye-hx-get-alert': get_alert() elif command == 'fireeye-hx-file-acquisition': file_acquisition() elif command == 'fireeye-hx-delete-file-acquisition': delete_file_acquisition() elif command == 'fireeye-hx-data-acquisition': data_acquisition() elif command == 'fireeye-hx-initiate-data-acquisition': initiate_data_acquisition() elif command == 'fireeye-hx-get-data-acquisition': get_data_acquisition() elif command == 'fireeye-hx-delete-data-acquisition': delete_data_acquisition() elif command == 'fireeye-hx-search': start_search() elif command == 'fireeye-hx-get-host-set-information': get_host_set_information() elif command == 'fireeye-hx-append-conditions': append_conditions() elif command == 'fireeye-hx-get-all-hosts-information': get_hosts_information() except ValueError as e: return_error(e) finally: logout() if __name__ in ('__main__', '__builtin__', 'builtins'): main()