Cortex XDR - IR CTF
Cortex XDR is the world's first detection and response app that natively integrates network, endpoint, and cloud data to stop sophisticated attacks.
Endpoint · Capture The Flag - 01
Details
| ID | Cortex XDR - IR CTF |
|---|---|
| Provider | Palo Alto Networks |
| Category | Endpoint |
| From Version | 8.2.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
README
This integration is a Mock customized only for the Capture The Flag challenge.
Commands
You can execute these commands from the Cortex XSOAR 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.
get-mapping-fields
Gets mapping fields from remote incident. Note: This method will not update the current incident, it’s here for debugging purposes.
Base Command
get-mapping-fields
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
There is no context output for this command.
xdr-get-incident-extra-data-ctf
Returns additional data for the specified incident, for example, related alerts, file artifacts, network artifacts, and so on.
Base Command
xdr-get-incident-extra-data-ctf
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The ID of the incident for which to get additional data. | Required |
| alerts_limit | Maximum number of alerts to return. Default is 1000. | Optional |
| return_only_updated_incident | Return data only if the incident was changed since the last time it was mirrored into Cortex XSOAR. This flag should be used only from within a Cortex XDR incident. Default is False. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Incident.incident_id | String | Unique ID assigned to each returned incident. |
| PaloAltoNetworksXDR.Incident.creation_time | Date | Date and time the incident was created on Cortex XDR. |
| PaloAltoNetworksXDR.Incident.modification_time | Date | Date and time that the incident was last modified. |
| PaloAltoNetworksXDR.Incident.detection_time | Date | Date and time that the first alert occurred in the incident. |
| PaloAltoNetworksXDR.Incident.status | String | Current status of the incident. Valid values are: |
| “new”,”under_investigation”,”resolved_known_issue”,”resolved_duplicate”,”resolved_false_positive”,”resolved_true_positive”,”resolved_security_testing”,”resolved_other”. | ||
| PaloAltoNetworksXDR.Incident.severity | String | Calculated severity of the incident. Valid values are: “low”,”medium”,”high”. |
| PaloAltoNetworksXDR.Incident.description | String | Dynamic calculated description of the incident. |
| PaloAltoNetworksXDR.Incident.assigned_user_mail | String | Email address of the assigned user. |
| PaloAltoNetworksXDR.Incident.assigned_user_pretty_name | String | Full name of the user assigned to the incident. |
| PaloAltoNetworksXDR.Incident.alert_count | Number | Total number of alerts in the incident. |
| PaloAltoNetworksXDR.Incident.low_severity_alert_count | Number | Number of alerts with the severity LOW. |
| PaloAltoNetworksXDR.Incident.med_severity_alert_count | Number | Number of alerts with the severity MEDIUM. |
| PaloAltoNetworksXDR.Incident.high_severity_alert_count | Number | Number of alerts with the severity HIGH. |
| PaloAltoNetworksXDR.Incident.user_count | Number | Number of users involved in the incident. |
| PaloAltoNetworksXDR.Incident.host_count | Number | Number of hosts involved in the incident. |
| PaloAltoNetworksXDR.Incident.notes | Unknown | Comments entered by the user regarding the incident. |
| PaloAltoNetworksXDR.Incident.resolve_comment | String | Comments entered by the user when the incident was resolved. |
| PaloAltoNetworksXDR.Incident.manual_severity | String | Incident severity assigned by the user. This does not affect the calculated severity of low, medium, or high. |
| PaloAltoNetworksXDR.Incident.manual_description | String | Incident description provided by the user. |
| PaloAltoNetworksXDR.Incident.xdr_url | String | A link to the incident view on Cortex XDR. |
| PaloAltoNetworksXDR.Incident.starred | Boolean | Incident starred. |
| PaloAltoNetworksXDR.Incident.wildfire_hits.mitre_techniques_ids_and_names | String | Incident Mitre techniques IDs and names. |
| PaloAltoNetworksXDR.Incident.wildfire_hits.mitre_tactics_ids_and_names | String | Incident Mitre tactics ids and names. |
| PaloAltoNetworksXDR.Incident.alerts.alert_id | String | Unique ID for each alert. |
| PaloAltoNetworksXDR.Incident.alerts.detection_timestamp | Date | Date and time that the alert occurred. |
| PaloAltoNetworksXDR.Incident.alerts.source | String | Source of the alert. The product/vendor this alert came from. |
| PaloAltoNetworksXDR.Incident.alerts.severity | String | Severity of the alert.Valid values are: “low”,”medium”,”high”””. |
| PaloAltoNetworksXDR.Incident.alerts.name | String | Calculated name of the alert. |
| PaloAltoNetworksXDR.Incident.alerts.category | String | Category of the alert, for example, Spyware Detected via Anti-Spyware profile. |
| PaloAltoNetworksXDR.Incident.alerts.description | String | Textual description of the alert. |
| PaloAltoNetworksXDR.Incident.alerts.host_ip_list | Unknown | Host IP involved in the alert. |
| PaloAltoNetworksXDR.Incident.alerts.host_name | String | Host name involved in the alert. |
| PaloAltoNetworksXDR.Incident.alerts.user_name | String | User name involved with the alert. |
| PaloAltoNetworksXDR.Incident.alerts.event_type | String | Event type. Valid values are: “Process Execution”,”Network Event”,”File Event”,”Registry Event”,”Injection Event”,”Load Image Event”,”Windows Event Log”. |
| PaloAltoNetworksXDR.Incident.alerts.action | String | The action that triggered the alert. Valid values are: “REPORTED”, “BLOCKED”, “POST_DETECTED”, “SCANNED”, “DOWNLOAD”, “PROMPT_ALLOW”, “PROMPT_BLOCK”, “DETECTED”, “BLOCKED_1”, “BLOCKED_2”, “BLOCKED_3”, “BLOCKED_5”, “BLOCKED_6”, “BLOCKED_7”, “BLOCKED_8”, “BLOCKED_9”, “BLOCKED_10”, “BLOCKED_11”, “BLOCKED_13”, “BLOCKED_14”, “BLOCKED_15”, “BLOCKED_16”, “BLOCKED_17”, “BLOCKED_24”, “BLOCKED_25”, “DETECTED_0”, “DETECTED_4”, “DETECTED_18”, “DETECTED_19”, “DETECTED_20”, “DETECTED_21”, “DETECTED_22”, “DETECTED_23”. |
| PaloAltoNetworksXDR.Incident.alerts.action_pretty | String | The action that triggered the alert. Valid values are: “Detected (Reported)” “Prevented (Blocked)” “Detected (Post Detected)” “Detected (Scanned)” “Detected (Download)” “Detected (Prompt Allow)” “Prevented (Prompt Block)” “Detected” “Prevented (Denied The Session)” “Prevented (Dropped The Session)” “Prevented (Dropped The Session And Sent a TCP Reset)” “Prevented (Blocked The URL)” “Prevented (Blocked The IP)” “Prevented (Dropped The Packet)” “Prevented (Dropped All Packets)” “Prevented (Terminated The Session And Sent a TCP Reset To Both Sides Of The Connection)” “Prevented (Terminated The Session And Sent a TCP Reset To The Client)” “Prevented (Terminated The Session And Sent a TCP Reset To The Server)” “Prevented (Continue)” “Prevented (Block-Override)” “Prevented (Override-Lockout)” “Prevented (Override)” “Prevented (Random-Drop)” “Prevented (Silently Dropped The Session With An ICMP Unreachable Message To The Host Or Application)” “Prevented (Block)” “Detected (Allowed The Session)” “Detected (Raised An Alert)” “Detected (Syncookie Sent)” “Detected (Forward)” “Detected (Wildfire Upload Success)” “Detected (Wildfire Upload Failure)” “Detected (Wildfire Upload Skip)” “Detected (Sinkhole)”. |
| PaloAltoNetworksXDR.Incident.alerts.actor_process_image_name | String | Image name. |
| PaloAltoNetworksXDR.Incident.alerts.actor_process_command_line | String | Command line. |
| PaloAltoNetworksXDR.Incident.alerts.actor_process_signature_status | String | Signature status. Valid values are: “Signed” “Invalid Signature” “Unsigned” “Revoked” “Signature Fail” “N/A” “Weak Hash”. |
| PaloAltoNetworksXDR.Incident.alerts.actor_process_signature_vendor | String | Signature vendor name. |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_process_image_name | String | Image name. |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_process_command_line | String | Command line. |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_process_signature_status | String | Signature status. Valid values are: “Signed” “Invalid Signature” “Unsigned” “Revoked” “Signature Fail” “N/A” “Weak Hash”. |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_process_signature_vendor | String | Signature vendor. |
| PaloAltoNetworksXDR.Incident.alerts.causality_actor_causality_id | Unknown | Causality ID. |
| PaloAltoNetworksXDR.Incident.alerts.action_process_image_name | String | Image name. |
| PaloAltoNetworksXDR.Incident.alerts.action_process_image_command_line | String | Command line. |
| PaloAltoNetworksXDR.Incident.alerts.action_process_image_sha256 | String | Image SHA256. |
| PaloAltoNetworksXDR.Incident.alerts.action_process_signature_status | String | Signature status. Valid values are: “Signed” “Invalid Signature” “Unsigned” “Revoked” “Signature Fail” “N/A” “Weak Hash”. |
| PaloAltoNetworksXDR.Incident.alerts.action_process_signature_vendor | String | Signature vendor name. |
| PaloAltoNetworksXDR.Incident.alerts.action_file_path | String | File path. |
| PaloAltoNetworksXDR.Incident.alerts.action_file_md5 | String | File MD5. |
| PaloAltoNetworksXDR.Incident.alerts.action_file_sha256 | String | File SHA256. |
| PaloAltoNetworksXDR.Incident.alerts.action_registry_data | String | Registry data. |
| PaloAltoNetworksXDR.Incident.alerts.action_registry_full_key | String | Registry full key. |
| PaloAltoNetworksXDR.Incident.alerts.action_local_ip | String | Local IP. |
| PaloAltoNetworksXDR.Incident.alerts.action_local_port | Number | Local port. |
| PaloAltoNetworksXDR.Incident.alerts.action_remote_ip | String | Remote IP. |
| PaloAltoNetworksXDR.Incident.alerts.action_remote_port | Number | Remote port. |
| PaloAltoNetworksXDR.Incident.alerts.action_external_hostname | String | External hostname. |
| PaloAltoNetworksXDR.Incident.alerts.fw_app_id | Unknown | Firewall app id. |
| PaloAltoNetworksXDR.Incident.alerts.is_whitelisted | String | Is the alert on allow list. Valid values are: “Yes” “No”. |
| PaloAltoNetworksXDR.Incident.alerts.starred | Boolean | Alert starred. |
| PaloAltoNetworksXDR.Incident.network_artifacts.type | String | Network artifact type. |
| PaloAltoNetworksXDR.Incident.network_artifacts.network_remote_port | number | The remote port related to the artifact. |
| PaloAltoNetworksXDR.Incident.network_artifacts.alert_count | number | Number of alerts related to the artifact. |
| PaloAltoNetworksXDR.Incident.network_artifacts.network_remote_ip | String | The remote IP related to the artifact. |
| PaloAltoNetworksXDR.Incident.network_artifacts.is_manual | boolean | Whether the artifact was created by the user (manually). |
| PaloAltoNetworksXDR.Incident.network_artifacts.network_domain | String | The domain related to the artifact. |
| PaloAltoNetworksXDR.Incident.network_artifacts.type | String | The artifact type. Valid values are: “META”, “GID”, “CID”, “HASH”, “IP”, “DOMAIN”, “REGISTRY”, “HOSTNAME”. |
| PaloAltoNetworksXDR.Incident.network_artifacts.network_country | String | The country related to the artifact. |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_signature_status | String | Digital signature status of the file. Valid values are: “SIGNATURE_UNAVAILABLE” “SIGNATURE_SIGNED” “SIGNATURE_INVALID” “SIGNATURE_UNSIGNED” “SIGNATURE_WEAK_HASH”. |
| PaloAltoNetworksXDR.Incident.file_artifacts.is_process | boolean | Whether the file artifact is related to a process execution. |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_name | String | Name of the file. |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_wildfire_verdict | String | The file verdict, calculated by Wildfire. Valid values are: “BENIGN” “MALWARE” “GRAYWARE” “PHISHING” “UNKNOWN”. |
| PaloAltoNetworksXDR.Incident.file_artifacts.alert_count | number | Number of alerts related to the artifact. |
| PaloAltoNetworksXDR.Incident.file_artifacts.is_malicious | boolean | Whether the artifact is malicious, as decided by the Wildfire verdict. |
| PaloAltoNetworksXDR.Incident.file_artifacts.is_manual | boolean | Whether the artifact was created by the user (manually). |
| PaloAltoNetworksXDR.Incident.file_artifacts.type | String | The artifact type. Valid values are: “META” “GID” “CID” “HASH” “IP” “DOMAIN” “REGISTRY” “HOSTNAME”. |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_sha256 | String | SHA256 hash of the file. |
| PaloAltoNetworksXDR.Incident.file_artifacts.file_signature_vendor_name | String | File signature vendor name. |
| Account.Username | String | The username in the relevant system. |
| Endpoint.Hostname | String | The hostname that is mapped to this endpoint. |
| File.Path | String | The path where the file is located. |
| File.MD5 | String | The MD5 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Name | String | The full file name (including file extension). |
| Process.Name | String | The name of the process. |
| Process.MD5 | String | The MD5 hash of the process. |
| Process.SHA256 | String | The SHA256 hash of the process. |
| Process.PID | String | The PID of the process. |
| Process.Path | String | The file system path to the binary file. |
| Process.Start Time | String | The timestamp of the process start time. |
| Process.CommandLine | String | The full command line (including arguments). |
| IP.Address | String | IP address. |
| IP.Geo.Country | String | The country in which the IP address is located. |
| Domain.Name | String | The domain name, for example: “google.com”. |
xdr-endpoint-isolate-ctf
Isolates the specified endpoint.
Base Command
xdr-endpoint-isolate-ctf
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | Allows linking the response action to the incident that triggered it. | Optional |
| endpoint_id | The endpoint ID (string) to isolate. You can retrieve the string from the xdr-get-endpoints command. | Required |
| suppress_disconnected_endpoint_error | Whether to suppress an error when trying to isolate a disconnected endpoint. When sets to false, an error will be returned. Possible values are: true, false. Default is false. | Optional |
| interval_in_seconds | Interval in seconds between each poll. | Optional |
| timeout_in_seconds | Polling timeout in seconds. | Optional |
| action_id | For polling use. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Isolation.endpoint_id | String | The endpoint ID. |
xdr-file-retrieve-ctf
Retrieves files from selected endpoints. You can retrieve up to 20 files, from no more than 10 endpoints. At least one endpoint ID and one file path are necessary in order to run the command. After running this command, you can use the xdr-action-status-get command with returned action_id, to check the action status.
Base Command
xdr-file-retrieve-ctf
Input
| Argument Name | Description | Required |
|---|---|---|
| endpoint_ids | A comma-separated list of endpoint IDs. | Required |
| generic_file_path | A comma-separated list of file paths in any platform. Can be used instead of the mac/windows/linux file paths. The order of the files path list must be parallel to the endpoints list order, so the first file path in the list is related to the first endpoint and so on. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.RetrievedFiles.action_id | string | ID of the action to retrieve files from selected endpoints. |
| PaloAltoNetworksXDR.RetrievedFiles.endpoint_id | string | Endpoint ID. Added only when the operation is successful. |
| PaloAltoNetworksXDR.RetrievedFiles.file_link | string | Link to the file. Added only when the operation is successful. |
| PaloAltoNetworksXDR.RetrievedFiles.status | string | The action status. Added only when the operation is unsuccessful. |
xdr-get-alerts-ctf
Returns a list of alerts and their metadata, which you can filter by built-in arguments or use the custom_filter to input a JSON filter object.
Multiple filter arguments will be concatenated using the AND operator, while arguments that support a comma-separated list of values will use an OR operator between each value.
Base Command
xdr-get-alerts-ctf
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | The unique ID of the alert. | Optional |
| severity | The severity of the alert. Possible values are: low, medium, high. | Optional |
| custom_filter | a custom filter, when using this argument, other filter arguments are not relevant. example: {<br/> "OR": [<br/> {<br/> "SEARCH_FIELD": "actor_process_command_line",<br/> "SEARCH_TYPE": "EQ",<br/> "SEARCH_VALUE": "path_to_file"<br/> }<br/> ]<br/> }. |
Optional |
| Identity_type | Account type. Possible values are: ANONYMOUS, APPLICATION, COMPUTE, FEDERATED_IDENTITY, SERVICE, SERVICE_ACCOUNT, TEMPORARY_CREDENTIALS, TOKEN, UNKNOWN, USER. | Optional |
| agent_id | A unique identifier per agent. | Optional |
| action_external_hostname | The host name to connect to. In case of a proxy connection, this value will differ from action_remote_ip. | Optional |
| rule_id | A string identifying the user rule. | Optional |
| rule_name | The name of the user rule. | Optional |
| alert_name | The alert name. | Optional |
| alert_source | The alert source. | Optional |
| time_frame | Supports relative times or “custom” time option. If you choose the “custom” option, you should use start_time and end_time arguments. Possible values are: 60 minutes, 3 hours, 12 hours, 24 hours, 2 days, 7 days, 14 days, 30 days, custom. | Optional |
| user_name | The name assigned to the user_id during agent runtime. | Optional |
| actor_process_image_name | The file name of the binary file. | Optional |
| causality_actor_process_image_command_line | CGO CMD. | Optional |
| actor_process_image_command_line | Trimmed to 128 unicode chars during event serialization. Full value reported as part of the original process event. |
Optional |
| action_process_image_command_line | The command line of the process created. | Optional |
| actor_process_image_sha256 | SHA256 of the binary file. | Optional |
| causality_actor_process_image_sha256 | SHA256 of the binary file. | Optional |
| action_process_image_sha256 | SHA256 of the binary file. | Optional |
| action_file_image_sha256 | SHA256 of the file related to the event. | Optional |
| action_registry_name | The name of the registry. | Optional |
| action_registry_key_data | The key data of the registry. | Optional |
| host_ip | The host IP. | Optional |
| action_local_ip | The local IP address for the connection. | Optional |
| action_remote_ip | Remote IP address for the connection. | Optional |
| alert_action_status | Alert action status. Possible values are: detected, detected (allowed the session), detected (download), detected (forward), detected (post detected), detected (prompt allow), detected (raised an alert), detected (reported), detected (on write), detected (scanned), detected (sinkhole), detected (syncookie sent), detected (wildfire upload failure), detected (wildfire upload success), detected (wildfire upload skip), detected (xdr managed threat hunting), prevented (block), prevented (blocked), prevented (block-override), prevented (blocked the url), prevented (blocked the ip), prevented (continue), prevented (denied the session), prevented (dropped all packets), prevented (dropped the session), prevented (dropped the session and sent a tcp reset), prevented (dropped the packet), prevented (override), prevented (override-lockout), prevented (post detected), prevented (prompt block), prevented (random-drop), prevented (silently dropped the session with an icmp unreachable message to the host or application), prevented (terminated the session and sent a tcp reset to both sides of the connection), prevented (terminated the session and sent a tcp reset to the client), prevented (terminated the session and sent a tcp reset to the server), prevented (on write). | Optional |
| action_local_port | The local IP address for the connection. | Optional |
| action_remote_port | The remote port for the connection. | Optional |
| dst_action_external_hostname | The hostname we connect to. In case of a proxy connection, this value will differ from action_remote_ip. | Optional |
| sort_field | The field by which we sort the results. Default is source_insert_ts. | Optional |
| sort_order | The order in which we sort the results. Possible values are: DESC, ASC. | Optional |
| offset | The first page from which we bring the alerts. Default is 0. | Optional |
| limit | The last page from which we bring the alerts. Default is 50. | Optional |
| start_time | Relevant when “time_frame” argument is “custom”. Supports Epoch timestamp and simplified extended ISO format (YYYY-MM-DDThh:mm:ss.000Z). | Optional |
| end_time | Relevant when “time_frame” argument is “custom”. Supports Epoch timestamp and simplified extended ISO format (YYYY-MM-DDThh:mm:ss.000Z). | Optional |
| starred | Whether the alert is starred or not. Possible values are: true, false. | Optional |
| mitre_technique_id_and_name | The MITRE attack technique. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PaloAltoNetworksXDR.Alert.internal_id | String | The unique ID of the alert. |
| PaloAltoNetworksXDR.Alert.source_insert_ts | Number | The detection timestamp. |
| PaloAltoNetworksXDR.Alert.alert_name | String | The name of the alert. |
| PaloAltoNetworksXDR.Alert.severity | String | The severity of the alert. |
| PaloAltoNetworksXDR.Alert.alert_category | String | The category of the alert. |
| PaloAltoNetworksXDR.Alert.alert_action_status | String | The alert action. Possible values. |
DETECTED: detected
DETECTED_0: detected (allowed the session)
DOWNLOAD: detected (download)
DETECTED_19: detected (forward)
POST_DETECTED: detected (post detected)
PROMPT_ALLOW: detected (prompt allow)
DETECTED_4: detected (raised an alert)
REPORTED: detected (reported)
REPORTED_TRIGGER_4: detected (on write)
SCANNED: detected (scanned)
DETECTED_23: detected (sinkhole)
DETECTED_18: detected (syncookie sent)
DETECTED_21: detected (wildfire upload failure)
DETECTED_20: detected (wildfire upload success)
DETECTED_22: detected (wildfire upload skip)
DETECTED_MTH: detected (xdr managed threat hunting)
BLOCKED_25: prevented (block)
BLOCKED: prevented (blocked)
BLOCKED_14: prevented (block-override)
BLOCKED_5: prevented (blocked the url)
BLOCKED_6: prevented (blocked the ip)
BLOCKED_13: prevented (continue)
BLOCKED_1: prevented (denied the session)
BLOCKED_8: prevented (dropped all packets)
BLOCKED_2: prevented (dropped the session)
BLOCKED_3: prevented (dropped the session and sent a tcp reset)
BLOCKED_7: prevented (dropped the packet)
BLOCKED_16: prevented (override)
BLOCKED_15: prevented (override-lockout)
BLOCKED_26: prevented (post detected)
PROMPT_BLOCK: prevented (prompt block)
BLOCKED_17: prevented (random-drop)
BLOCKED_24: prevented (silently dropped the session with an icmp unreachable message to the host or application)
BLOCKED_9: prevented (terminated the session and sent a tcp reset to both sides of the connection)
BLOCKED_10: prevented (terminated the session and sent a tcp reset to the client)
BLOCKED_11: prevented (terminated the session and sent a tcp reset to the server)
BLOCKED_TRIGGER_4: prevented (on write). |
| PaloAltoNetworksXDR.Alert.alert_action_status_readable | String | The alert action. |
| PaloAltoNetworksXDR.Alert.alert_name | String | The alert name. |
| PaloAltoNetworksXDR.Alert.alert_description | String | The alert description. |
| PaloAltoNetworksXDR.Alert.agent_ip_addresses | String | The host IP. |
| PaloAltoNetworksXDR.Alert.agent_hostname | String | The host name. |
| PaloAltoNetworksXDR.Alert.mitre_tactic_id_and_name | String | The MITRE attack tactic. |
| PaloAltoNetworksXDR.Alert.mitre_technique_id_and_name | String | The MITRE attack technique. |
| PaloAltoNetworksXDR.Alert.starred | Boolean | Whether the alert is starred or not. |
Configuration parameters
isFetch— Fetch incidentsincidentType— Incident typemirror_direction— Incident Mirroring Directiontimeout— HTTP Timeoutmax_fetch— Maximum number of incidents per fetchstarred— Only fetch starred incidentsstarred_incidents_fetch_window— Starred incidents fetch windowfetch_time— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days)sync_owners— Sync Incident Ownersinsecure— Trust any certificate (not secure)proxy— Use system proxy settingsprevent_only— Prevent Only Modestatus— Incident Statuses to FetchincidentFetchInterval— Incidents Fetch Interval
Commands (5)
-
get-mapping-fieldsGets mapping fields from remote incident. Note: This method will not update the current incident, it's here for debugging purposes.
-
xdr-endpoint-isolate-ctfIsolates the specified endpoint.
-
xdr-file-retrieve-ctfRetrieves files from selected endpoints. You can retrieve up to 20 files, from no more than 10 endpoints. At least one endpoint ID and one file path are necessary in order to run the command. After running this command, you can use the xdr-action-status-get command with returned action_id, to check the action status.
-
xdr-get-alerts-ctfReturns a list of alerts and their metadata, which you can filter by built-in arguments or use the custom_filter to input a JSON filter object. Multiple filter arguments will be concatenated using the AND operator, while arguments that support a comma-separated list of values will use an OR operator between each value.
-
xdr-get-incident-extra-data-ctfReturns additional data for the specified incident, for example, related alerts, file artifacts, network artifacts, and so on.
import hashlib import secrets import string from itertools import zip_longest import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 from CoreIRApiModule import * # Disable insecure warnings urllib3.disable_warnings() TIME_FORMAT = "%Y-%m-%dT%H:%M:%S" NONCE_LENGTH = 64 API_KEY_LENGTH = 128 INTEGRATION_CONTEXT_BRAND = "PaloAltoNetworksXDR" XDR_INCIDENT_TYPE_NAME = "Cortex XDR Incident" INTEGRATION_NAME = "Cortex XDR - IR" XDR_INCIDENT_FIELDS = { "status": { "description": 'Current status of the incident: "new","under_' 'investigation","resolved_known_issue",' '"resolved_duplicate","resolved_false_positive",' '"resolved_true_positive","resolved_security_testing","resolved_other"', "xsoar_field_name": "xdrstatusv2", }, "assigned_user_mail": {"description": "Email address of the assigned user.", "xsoar_field_name": "xdrassigneduseremail"}, "assigned_user_pretty_name": { "description": "Full name of the user assigned to the incident.", "xsoar_field_name": "xdrassigneduserprettyname", }, "resolve_comment": { "description": "Comments entered by the user when the incident was resolved.", "xsoar_field_name": "xdrresolvecomment", }, "manual_severity": { "description": "Incident severity assigned by the user. This does not affect the calculated severity low medium high", "xsoar_field_name": "severity", }, } XSOAR_RESOLVED_STATUS_TO_XDR = { "Other": "resolved_other", "Duplicate": "resolved_duplicate", "False Positive": "resolved_false_positive", "Resolved": "resolved_true_positive", } MIRROR_DIRECTION = {"None": None, "Incoming": "In", "Outgoing": "Out", "Both": "Both"} def convert_epoch_to_milli(timestamp): if timestamp is None: return None if 9 < len(str(timestamp)) < 13: timestamp = int(timestamp) * 1000 return int(timestamp) def convert_datetime_to_epoch(the_time=0): if the_time is None: return None try: if isinstance(the_time, datetime): return int(the_time.strftime("%s")) except Exception as err: demisto.debug(err) return 0 def convert_datetime_to_epoch_millis(the_time=0): return convert_epoch_to_milli(convert_datetime_to_epoch(the_time=the_time)) def generate_current_epoch_utc(): return convert_datetime_to_epoch_millis(datetime.now(timezone.utc)) def generate_key(): return "".join([secrets.choice(string.ascii_letters + string.digits) for _ in range(API_KEY_LENGTH)]) def create_auth(api_key): nonce = "".join([secrets.choice(string.ascii_letters + string.digits) for _ in range(NONCE_LENGTH)]) timestamp = str(generate_current_epoch_utc()) # Get epoch time utc millis hash_ = hashlib.sha256() hash_.update((api_key + nonce + timestamp).encode("utf-8")) return nonce, timestamp, hash_.hexdigest() def clear_trailing_whitespace(res): index = 0 while index < len(res): for key, value in res[index].items(): if isinstance(value, str): res[index][key] = value.rstrip() index += 1 return res def filter_and_save_unseen_incident(incidents: List, limit: int, number_of_already_filtered_incidents: int) -> List: """ Filters incidents that were seen already and saves the unseen incidents to LastRun object. :param incidents: List of incident - must be list :param limit: the maximum number of incident per fetch :param number_of_already_filtered_incidents: number of incidents that were fetched already :return: the filtered incidents. """ last_run_obj = demisto.getLastRun() fetched_starred_incidents = last_run_obj.pop("fetched_starred_incidents", {}) filtered_incidents = [] for incident in incidents: incident_id = incident.get("incident_id") if incident_id in fetched_starred_incidents: demisto.debug(f"incident (ID {incident_id}) was already fetched in the past.") continue fetched_starred_incidents[incident_id] = True filtered_incidents.append(incident) number_of_already_filtered_incidents += 1 if number_of_already_filtered_incidents >= limit: break last_run_obj["fetched_starred_incidents"] = fetched_starred_incidents demisto.setLastRun(last_run_obj) return filtered_incidents class Client(CoreClient): def test_module(self, first_fetch_time): """ Performs basic get request to get item samples """ last_one_day, _ = parse_date_range(first_fetch_time, TIME_FORMAT) try: self.get_incidents(lte_creation_time=last_one_day, limit=1) except Exception as err: if "API request Unauthorized" in str(err): # this error is received from the XDR server when the client clock is not in sync to the server raise DemistoException(f"{err!s} please validate that your both XSOAR and XDR server clocks are in sync") else: raise def handle_fetch_starred_incidents(self, limit: int, page_number: int, request_data: dict) -> List: """ handles pagination and filter of starred incidents that were fetched. :param limit: the maximum number of incident per fetch :param page_number: page number :param request_data: the api call request data :return: the filtered starred incidents. """ res = self._http_request( method="POST", url_suffix="/incidents/get_incidents/", json_data={"request_data": request_data}, timeout=self.timeout ) raw_incidents = res.get("reply", {}).get("incidents", []) # we want to avoid duplications of starred incidents in the fetch-incident command (we fetch all incidents # in the fetch window). filtered_incidents = filter_and_save_unseen_incident(raw_incidents, limit, 0) # we want to support pagination on starred incidents. while len(filtered_incidents) < limit: page_number += 1 search_from = page_number * limit search_to = search_from + limit request_data["search_from"] = search_from request_data["search_to"] = search_to res = self._http_request( method="POST", url_suffix="/incidents/get_incidents/", json_data={"request_data": request_data}, timeout=self.timeout, ) raw_incidents = res.get("reply", {}).get("incidents", []) if not raw_incidents: break filtered_incidents += filter_and_save_unseen_incident(raw_incidents, limit, len(filtered_incidents)) return filtered_incidents def get_incidents( # type: ignore[override] self, incident_id_list=None, lte_modification_time=None, gte_modification_time=None, lte_creation_time=None, gte_creation_time=None, status=None, starred=None, starred_incidents_fetch_window=None, sort_by_modification_time=None, sort_by_creation_time=None, page_number=0, limit=1000, gte_creation_time_milliseconds=0, ): """ Filters and returns incidents :param incident_id_list: List of incident ids - must be list :param lte_modification_time: string of time format "2019-12-31T23:59:00" :param gte_modification_time: string of time format "2019-12-31T23:59:00" :param lte_creation_time: string of time format "2019-12-31T23:59:00" :param gte_creation_time: string of time format "2019-12-31T23:59:00" :param starred_incidents_fetch_window: string of time format "2019-12-31T23:59:00" :param starred: True if the incident is starred, else False :param status: string of status :param sort_by_modification_time: optional - enum (asc,desc) :param sort_by_creation_time: optional - enum (asc,desc) :param page_number: page number :param limit: maximum number of incidents to return per page :param gte_creation_time_milliseconds: greater than time in milliseconds :return: """ search_from = page_number * limit search_to = search_from + limit request_data = { "search_from": search_from, "search_to": search_to, } if sort_by_creation_time and sort_by_modification_time: raise ValueError("Should be provide either sort_by_creation_time or sort_by_modification_time. Can't provide both") if sort_by_creation_time: request_data["sort"] = {"field": "creation_time", "keyword": sort_by_creation_time} elif sort_by_modification_time: request_data["sort"] = {"field": "modification_time", "keyword": sort_by_modification_time} filters = [] if incident_id_list is not None and len(incident_id_list) > 0: filters.append({"field": "incident_id_list", "operator": "in", "value": incident_id_list}) if status: filters.append({"field": "status", "operator": "eq", "value": status}) if starred and starred_incidents_fetch_window: filters.append({"field": "starred", "operator": "eq", "value": True}) filters.append({"field": "creation_time", "operator": "gte", "value": starred_incidents_fetch_window}) if demisto.command() == "fetch-incidents": if len(filters) > 0: request_data["filters"] = filters incidents = self.handle_fetch_starred_incidents(limit, page_number, request_data) return incidents else: if lte_creation_time: filters.append( {"field": "creation_time", "operator": "lte", "value": date_to_timestamp(lte_creation_time, TIME_FORMAT)} ) if gte_creation_time: filters.append( {"field": "creation_time", "operator": "gte", "value": date_to_timestamp(gte_creation_time, TIME_FORMAT)} ) if lte_modification_time: filters.append( { "field": "modification_time", "operator": "lte", "value": date_to_timestamp(lte_modification_time, TIME_FORMAT), } ) if gte_modification_time: filters.append( { "field": "modification_time", "operator": "gte", "value": date_to_timestamp(gte_modification_time, TIME_FORMAT), } ) if gte_creation_time_milliseconds > 0: filters.append({"field": "creation_time", "operator": "gte", "value": gte_creation_time_milliseconds}) if len(filters) > 0: request_data["filters"] = filters res = self._http_request( method="POST", url_suffix="/incidents/get_incidents/", json_data={"request_data": request_data}, timeout=self.timeout ) incidents = res.get("reply", {}).get("incidents", []) return incidents def get_incident_extra_data(self, incident_id, alerts_limit=1000): """ Returns incident by id :param incident_id: The id of incident :param alerts_limit: Maximum number alerts to get :return: """ request_data = { "incident_id": incident_id, "alerts_limit": alerts_limit, "full_alert_fields": True, } reply = self._http_request( method="POST", url_suffix="/incidents/get_incident_extra_data/", json_data={"request_data": request_data}, timeout=self.timeout, ) incident = reply.get("reply") return incident def save_modified_incidents_to_integration_context(self): last_modified_incidents = self.get_incidents(limit=100, sort_by_modification_time="desc") modified_incidents_context = {} for incident in last_modified_incidents: incident_id = incident.get("incident_id") modified_incidents_context[incident_id] = incident.get("modification_time") set_integration_context({"modified_incidents": modified_incidents_context}) def get_contributing_event_by_alert_id(self, alert_id: int) -> dict: request_data = { "request_data": { "alert_id": alert_id, } } reply = self._http_request( method="POST", url_suffix="/alerts/get_correlation_alert_data/", json_data=request_data, timeout=self.timeout, ) return reply.get("reply", {}) def replace_featured_field(self, field_type: str, fields: list[dict]) -> dict: request_data = {"request_data": {"fields": fields}} reply = self._http_request( method="POST", url_suffix=f"/featured_fields/replace_{field_type}", json_data=request_data, timeout=self.timeout, raise_on_status=True, ) return reply.get("reply") def get_tenant_info(self): reply = self._http_request( method="POST", url_suffix="/system/get_tenant_info/", json_data={"request_data": {}}, timeout=self.timeout ) return reply.get("reply", {}) def get_tenant_info_command(client: Client): tenant_info = client.get_tenant_info() readable_output = tableToMarkdown( "Tenant Information", tenant_info, headerTransform=pascalToSpace, removeNull=True, is_auto_json_transform=True ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.TenantInformation", outputs=tenant_info, raw_response=tenant_info, ) def check_if_incident_was_modified_in_xdr(incident_id, last_mirrored_in_time_timestamp, last_modified_incidents_dict): if incident_id in last_modified_incidents_dict: # search the incident in the dict of modified incidents incident_modification_time_in_xdr = int(str(last_modified_incidents_dict[incident_id])) demisto.debug( f"XDR incident {incident_id}\n" f"modified time: {incident_modification_time_in_xdr}\n" f"last mirrored in time: {last_mirrored_in_time_timestamp}" ) if incident_modification_time_in_xdr > last_mirrored_in_time_timestamp: # need to update this incident demisto.info(f"Incident '{incident_id}' was modified. performing extra-data request.") return True # the incident was not modified return False def get_last_mirrored_in_time(args): demisto_incidents = demisto.get_incidents() # type: ignore if demisto_incidents: # handling 5.5 version demisto_incident = demisto_incidents[0] last_mirrored_in_time = demisto_incident.get("CustomFields", {}).get("lastmirroredintime") if not last_mirrored_in_time: # this is an old incident, update anyway return 0 last_mirrored_in_timestamp = arg_to_timestamp(last_mirrored_in_time, "last_mirrored_in_time") else: # handling 6.0 version last_mirrored_in_time = arg_to_timestamp(args.get("last_update"), "last_update") last_mirrored_in_timestamp = last_mirrored_in_time - (120 * 1000) return last_mirrored_in_timestamp def get_incident_extra_data_command(client, args): """ This function was changed to retrieve predefined data , based in customized incident. The incident data was masked and changed Note that the data is used to retrive information on the same incident that the integration fetches. See Fetch_Incidents funtion. :param client: N.A. :param args: N.A. :return: Json on predefined incident data """ incident_id = args.get("incident_id") int(args.get("alerts_limit", 1000)) return_only_updated_incident = argToBoolean(args.get("return_only_updated_incident", "False")) if return_only_updated_incident: last_mirrored_in_time = get_last_mirrored_in_time(args) last_modified_incidents_dict = get_integration_context().get("modified_incidents", {}) if check_if_incident_was_modified_in_xdr(incident_id, last_mirrored_in_time, last_modified_incidents_dict): pass # the incident was modified. continue to perform extra-data request else: # the incident was not modified return "The incident was not modified in XDR since the last mirror in.", {}, {} demisto.debug(f"Performing extra-data request on incident: {incident_id}") raw_incident = { "incident": { "incident_id": "413", "is_blocked": False, "incident_name": None, "creation_time": 1671731222757, "modification_time": 1675721186878, "detection_time": None, "status": "resolved_false_positive", "severity": "low", "description": "'Possible external RDP Brute-Force' generated by XDR Analytics detected" " on host dc1env12apc05 involving user env12\\administrator", "assigned_user_mail": None, "assigned_user_pretty_name": None, "alert_count": 1, "low_severity_alert_count": 1, "med_severity_alert_count": 0, "high_severity_alert_count": 0, "critical_severity_alert_count": 0, "user_count": 1, "host_count": 1, "notes": None, "resolve_comment": None, "resolved_timestamp": 1675721186878, "manual_severity": None, "manual_description": None, "xdr_url": "https://mytenanet.xdr.us.paloaltonetworks.com/incident-view?caseId=413", "starred": False, "hosts": ["dc1env12apc05:f6ba1a18c35d416c8e27a319cc2fea09"], "users": ["env12\\administrator"], "incident_sources": ["XDR Analytics"], "rule_based_score": None, "predicted_score": None, "manual_score": None, "aggregated_score": None, "wildfire_hits": 0, "alerts_grouping_status": "Disabled", "mitre_tactics_ids_and_names": ["TA0006 - Credential Access"], "mitre_techniques_ids_and_names": ["T1110.001 - Brute Force: Password Guessing"], "alert_categories": ["Credential Access"], "original_tags": ["DS:PANW/XDR Agent"], "tags": ["DS:PANW/XDR Agent"], }, "alerts": { "total_count": 1, "data": [ { "external_id": "2a6a3f42-9d2d-4226-922f-28e4c2a3147f", "severity": "low", "matching_status": "MATCHED", # noqa: E501 "end_match_attempt_ts": None, "local_insert_ts": 1671731192490, "last_modified_ts": None, "bioc_indicator": None, # noqa: E501 "matching_service_rule_id": "fd879de7-fb74-44f0-b699-805d0b08b1fd", "attempt_counter": None, # noqa: E501 "bioc_category_enum_key": None, "case_id": 413, "is_whitelisted": False, "starred": False, "deduplicate_tokens": None, # noqa: E501 "filter_rule_id": None, "mitre_technique_id_and_name": "T1110.001 - Brute Force: Password Guessing", # noqa: E501 "mitre_tactic_id_and_name": "TA0006 - Credential Access", "agent_version": "7.9.0.18674", "agent_ip_addresses_v6": None, # noqa: E501 "agent_device_domain": None, "agent_fqdn": None, "agent_os_type": "Windows", "agent_os_sub_type": "Windows 10 [10.0 (Build 19044)]", "agent_data_collection_status": None, "mac": None, # noqa: E501 "agent_is_vdi": None, "agent_install_type": "STANDARD", "agent_host_boot_time": 1671032983204, "event_sub_type": 1, # noqa: E501 "module_id": None, "association_strength": 50, "dst_association_strength": 0, "story_id": "ODczNjk1Mzc1MTMwMzI1NjA1Nw==", # noqa: E501 "event_id": "ODczNjk1Mzc1MTMwMzI1NjA1Nw==", "event_type": "Login", "event_timestamp": 1671730625375, # noqa: E501 "actor_process_instance_id": "AdkP08aY7RwAAAL0AAAAAA==", "actor_process_image_path": "C:\\Windows\\System32\\lsass.exe", # noqa: E501 "actor_process_image_name": "lsass.exe", "actor_process_command_line": "C:\\WINDOWS\\system32\\lsass.exe", # noqa: E501 "actor_process_signature_status": "Signed", "actor_process_signature_vendor": "Microsoft Corporation", # noqa: E501 "actor_process_image_sha256": "0777fd312394ae1afeed0ad48ae2d7b5ed6e577117a4f40305eaeb4129233650", # noqa: E501 "actor_process_image_md5": "289d6a47b7692510e2fd3b51979a9fed", "actor_process_causality_id": "AdkP08aY7RwAAAL0AAAAAA==", # noqa: E501 "actor_causality_id": "AdkP08aY7RwAAAL0AAAAAA==", "actor_process_os_pid": 756, "actor_thread_thread_id": 4020, # noqa: E501 "causality_actor_process_image_name": "lsass.exe", "causality_actor_process_command_line": "C:\\WINDOWS\\system32\\lsass.exe", "causality_actor_process_image_path": "C:\\Windows\\System32\\lsass.exe", "causality_actor_process_signature_vendor": "Microsoft Corporation", "causality_actor_process_signature_status": "Signed", "causality_actor_causality_id": "AdkP08aY7RwAAAL0AAAAAA==", # noqa: E501 "causality_actor_process_execution_time": 1671033022857, "causality_actor_process_image_md5": "289d6a47b7692510e2fd3b51979a9fed", "causality_actor_process_image_sha256": "0777fd312394ae1afeed0ad48ae2d7b5ed6e577117a4f40305eaeb4129233650", # noqa: E501 "action_file_path": None, "action_file_name": None, "action_file_md5": None, "action_file_sha256": None, "action_file_macro_sha256": None, "action_registry_data": None, # noqa: E501 "action_registry_key_name": None, "action_registry_value_name": None, "action_registry_full_key": None, # noqa: E501 "action_local_ip": "None", "action_local_ip_v6": None, "action_local_port": 0, "action_remote_ip": "137.184.208.116", # noqa: E501 "action_remote_ip_v6": None, "action_remote_port": 0, "action_external_hostname": "kali", "action_country": "UNKNOWN", # noqa: E501 "action_process_instance_id": None, "action_process_causality_id": None, "action_process_image_name": None, # noqa: E501 "action_process_image_sha256": None, "action_process_image_command_line": None, "action_process_signature_status": "N/A", # noqa: E501 "action_process_signature_vendor": None, "os_actor_effective_username": None, "os_actor_process_instance_id": "AdkP08aY7RwAAAL0AAAAAA==", "os_actor_process_image_path": "C:\\Windows\\System32\\lsass.exe", "os_actor_process_image_name": "lsass.exe", # noqa: E501 "os_actor_process_command_line": "C:\\WINDOWS\\system32\\lsass.exe", "os_actor_process_signature_status": "Signed", # noqa: E501 "os_actor_process_signature_vendor": "Microsoft Corporation", "os_actor_process_image_sha256": "0777fd312394ae1afeed0ad48ae2d7b5ed6e577117a4f40305eaeb4129233650", # noqa: E501 "os_actor_process_causality_id": "AdkP08aY7RwAAAL0AAAAAA==", "os_actor_causality_id": None, "os_actor_process_os_pid": 756, "os_actor_thread_thread_id": 4020, "fw_app_id": "", "fw_interface_from": "", # noqa: E501 "fw_interface_to": "", "fw_rule": "", "fw_rule_id": None, "fw_device_name": "", "fw_serial_number": "", # noqa: E501 "fw_url_domain": None, "fw_email_subject": None, "fw_email_sender": None, "fw_email_recipient": None, # noqa: E501 "fw_app_subcategory": None, "fw_app_category": None, "fw_app_technology": None, "fw_vsys": None, "fw_xff": None, # noqa: E501 "fw_misc": None, "fw_is_phishing": "N/A", "dst_agent_id": "", "dst_causality_actor_process_execution_time": None, # noqa: E501 "dns_query_name": None, "dst_action_external_hostname": None, "dst_action_country": "-", "dst_action_external_port": None, "is_pcap": False, "contains_featured_host": "NO", "contains_featured_user": "NO", # noqa: E501 "contains_featured_ip": "NO", "image_name": None, "container_id": None, "cluster_name": None, # noqa: E501 "referenced_resource": None, "operation_name": None, "identity_sub_type": None, "identity_type": None, "project": None, # noqa: E501 "cloud_provider": None, "resource_type": None, "resource_sub_type": None, "user_agent": None, # noqa: E501 "alert_type": "Unclassified", "resolution_status": "STATUS_010_NEW", "resolution_comment": None, "dynamic_fields": None, # noqa: E501 "tags": "DS:PANW/XDR Agent", "events_length": 1, "alert_id": "150807", "detection_timestamp": 1671730626096, # noqa: E501 "name": "Possible external RDP Brute-Force", "category": "Credential Access", "endpoint_id": "f6ba1a18c35d416c8e27a319cc2fea09", "description": "DC1ENV12APC05 successfully accessed administrator by systematically guessing the user's password" # noqa: E501 " 22 times over an hour with 2 successful logons and 20 failed attempts. The user did not log in" # noqa: E501 " successfully from 137.184.208.116 during the last 30 days. Over the past 30 days, DC1ENV12APC05 has " # noqa: E501 "had an average of 0 failed login attempts with the user administrator from 137.184.208.116 per day", # noqa: E501 "host_ip": "172.16.12.40", "host_name": "DC1ENV12APC05", "source": "XDR Analytics", "action": "DETECTED", # noqa: E501 "action_pretty": "Detected", "user_name": "administrator", "original_tags": "DS:PANW/XDR Agent", } ], }, # noqa: E501 "network_artifacts": { "total_count": 1, "data": [ { "type": "DOMAIN", "alert_count": 1, "is_manual": False, "network_domain": "kali", "network_remote_ip": None, "network_remote_port": 0, "network_country": "UNKNOWN", } ], }, "file_artifacts": { "total_count": 1, "data": [ { "type": "HASH", "alert_count": 1, "is_manual": False, "is_malicious": False, "is_process": True, "file_name": "lsass.exe", "file_sha256": "0777fd312394ae1afeed0ad48ae2d7b5ed6e577117a4f40305eaeb4129233650", "file_signature_status": "SIGNATURE_SIGNED", "file_signature_vendor_name": "Microsoft Corporation", "file_wildfire_verdict": "BENIGN", "low_confidence": False, } ], }, } # client.get_incident_extra_data(incident_id, alerts_limit) incident = raw_incident.get("incident") incident_id = incident.get("incident_id") # type:ignore[union-attr] raw_alerts = raw_incident.get("alerts", {}).get("data") context_alerts = clear_trailing_whitespace(raw_alerts) for alert in context_alerts: alert["host_ip_list"] = alert.get("host_ip").split(",") if alert.get("host_ip") else [] file_artifacts = raw_incident.get("file_artifacts", {}).get("data") network_artifacts = raw_incident.get("network_artifacts", {}).get("data") readable_output = [tableToMarkdown(f"Incident {incident_id}", incident)] if len(context_alerts) > 0: readable_output.append( tableToMarkdown("Alerts", context_alerts, headers=[key for key in context_alerts[0] if key != "host_ip"]) ) else: readable_output.append(tableToMarkdown("Alerts", [])) if len(network_artifacts) > 0: # type: ignore[arg-type] readable_output.append(tableToMarkdown("Network Artifacts", network_artifacts)) else: readable_output.append(tableToMarkdown("Network Artifacts", [])) if len(file_artifacts) > 0: # type: ignore[arg-type] readable_output.append(tableToMarkdown("File Artifacts", file_artifacts)) else: readable_output.append(tableToMarkdown("File Artifacts", [])) incident.update( # type:ignore[union-attr] { "alerts": context_alerts, "file_artifacts": file_artifacts, "network_artifacts": network_artifacts, } ) account_context_output = assign_params(Username=incident.get("users", "")) # type:ignore[union-attr] endpoint_context_output = [] for alert in incident.get("alerts") or []: # type:ignore[union-attr] alert_context = {} if hostname := alert.get("host_name"): alert_context["Hostname"] = hostname if endpoint_id := alert.get("endpoint_id"): alert_context["ID"] = endpoint_id if alert_context: endpoint_context_output.append(alert_context) context_output = {f"{INTEGRATION_CONTEXT_BRAND}.Incident(val.incident_id==obj.incident_id)": incident} if account_context_output: context_output["Account(val.Username==obj.Username)"] = account_context_output if endpoint_context_output: context_output["Endpoint(val.Hostname==obj.Hostname)"] = endpoint_context_output # type:ignore[assignment] file_context, process_context, domain_context, ip_context = get_indicators_context(incident) if file_context: context_output[Common.File.CONTEXT_PATH] = file_context if domain_context: context_output[Common.Domain.CONTEXT_PATH] = domain_context if ip_context: context_output[Common.IP.CONTEXT_PATH] = ip_context if process_context: context_output["Process(val.Name && val.Name == obj.Name)"] = process_context return ("\n".join(readable_output), context_output, raw_incident) def create_parsed_alert( product, vendor, local_ip, local_port, remote_ip, remote_port, event_timestamp, severity, alert_name, alert_description ): alert = { "product": product, "vendor": vendor, "local_ip": local_ip, "local_port": local_port, "remote_ip": remote_ip, "remote_port": remote_port, "event_timestamp": event_timestamp, "severity": severity, "alert_name": alert_name, "alert_description": alert_description, } return alert def insert_parsed_alert_command(client, args): product = args.get("product") vendor = args.get("vendor") local_ip = args.get("local_ip") local_port = arg_to_int(arg=args.get("local_port"), arg_name="local_port") remote_ip = args.get("remote_ip") remote_port = arg_to_int(arg=args.get("remote_port"), arg_name="remote_port") severity = args.get("severity") alert_name = args.get("alert_name") alert_description = args.get("alert_description", "") if args.get("event_timestamp") is None: # get timestamp now if not provided event_timestamp = int(round(time.time() * 1000)) else: event_timestamp = int(args.get("event_timestamp")) alert = create_parsed_alert( product=product, vendor=vendor, local_ip=local_ip, local_port=local_port, remote_ip=remote_ip, remote_port=remote_port, event_timestamp=event_timestamp, severity=severity, alert_name=alert_name, alert_description=alert_description, ) client.insert_alerts([alert]) return ("Alert inserted successfully", None, None) def insert_cef_alerts_command(client, args): # parsing alerts list. the reason we don't use argToList is because cef_alerts could contain comma (,) so # we shouldn't split them by comma alerts = args.get("cef_alerts") if isinstance(alerts, list): pass elif isinstance(alerts, str): if alerts[0] == "[" and alerts[-1] == "]": # if the string contains [] it means it is a list and must be parsed alerts = json.loads(alerts) else: # otherwise it is a single alert alerts = [alerts] else: raise ValueError('Invalid argument "cef_alerts". It should be either list of strings (cef alerts), or single string') client.insert_cef_alerts(alerts) return ("Alerts inserted successfully", None, None) def sort_all_list_incident_fields(incident_data): """Sorting all lists fields in an incident - without this, elements may shift which results in false identification of changed fields""" if incident_data.get("hosts", []): incident_data["hosts"] = sorted(incident_data.get("hosts", [])) incident_data["hosts"] = [host.upper() for host in incident_data.get("hosts", [])] if incident_data.get("users", []): incident_data["users"] = sorted(incident_data.get("users", [])) incident_data["users"] = [user.upper() for user in incident_data.get("users", [])] if incident_data.get("incident_sources", []): incident_data["incident_sources"] = sorted(incident_data.get("incident_sources", [])) if incident_data.get("alerts", []): incident_data["alerts"] = sort_by_key(incident_data.get("alerts", []), main_key="alert_id", fallback_key="name") reformat_sublist_fields(incident_data["alerts"]) if incident_data.get("file_artifacts", []): incident_data["file_artifacts"] = sort_by_key( incident_data.get("file_artifacts", []), main_key="file_name", fallback_key="file_sha256" ) reformat_sublist_fields(incident_data["file_artifacts"]) if incident_data.get("network_artifacts", []): incident_data["network_artifacts"] = sort_by_key( incident_data.get("network_artifacts", []), main_key="network_domain", fallback_key="network_remote_ip" ) reformat_sublist_fields(incident_data["network_artifacts"]) def sync_incoming_incident_owners(incident_data): if incident_data.get("assigned_user_mail") and demisto.params().get("sync_owners"): user_info = demisto.findUser(email=incident_data.get("assigned_user_mail")) if user_info: demisto.debug( f"Syncing incident owners: XDR incident {incident_data.get('incident_id')}, owner {user_info.get('username')}" ) incident_data["owner"] = user_info.get("username") else: demisto.debug(f"The user assigned to XDR incident {incident_data.get('incident_id')} is not registered on XSOAR") def handle_incoming_user_unassignment(incident_data): incident_data["assigned_user_mail"] = "" incident_data["assigned_user_pretty_name"] = "" if demisto.params().get("sync_owners"): demisto.debug(f'Unassigning owner from XDR incident {incident_data.get("incident_id")}') incident_data["owner"] = "" def handle_incoming_closing_incident(incident_data): closing_entry = {} # type: Dict if incident_data.get("status") in XDR_RESOLVED_STATUS_TO_XSOAR: demisto.debug(f"Closing XDR issue {incident_data.get('incident_id')}") closing_entry = { "Type": EntryType.NOTE, "Contents": { "dbotIncidentClose": True, "closeReason": XDR_RESOLVED_STATUS_TO_XSOAR.get(incident_data.get("status")), "closeNotes": incident_data.get("resolve_comment", ""), }, "ContentsFormat": EntryFormat.JSON, } incident_data["closeReason"] = closing_entry["Contents"]["closeReason"] incident_data["closeNotes"] = closing_entry["Contents"]["closeNotes"] if incident_data.get("status") == "resolved_known_issue": close_notes = f'Known Issue.\n{incident_data.get("closeNotes", "")}' closing_entry["Contents"]["closeNotes"] = close_notes incident_data["closeNotes"] = close_notes return closing_entry def get_mapping_fields_command(): xdr_incident_type_scheme = SchemeTypeMapping(type_name=XDR_INCIDENT_TYPE_NAME) for field in XDR_INCIDENT_FIELDS: xdr_incident_type_scheme.add_field(name=field, description=XDR_INCIDENT_FIELDS[field].get("description")) mapping_response = GetMappingFieldsResponse() mapping_response.add_scheme_type(xdr_incident_type_scheme) return mapping_response def get_modified_remote_data_command(client, args): remote_args = GetModifiedRemoteDataArgs(args) last_update = remote_args.last_update # In the first run, this value will be set to 1 minute earlier demisto.debug(f"Performing get-modified-remote-data command. Last update is: {last_update}") last_update_utc = dateparser.parse(last_update, settings={"TIMEZONE": "UTC"}) # convert to utc format last_update_without_ms = last_update_utc.isoformat().split(".")[0] if last_update_utc else "" raw_incidents = client.get_incidents(gte_modification_time=last_update_without_ms, limit=100) modified_incident_ids = [] for raw_incident in raw_incidents: incident_id = raw_incident.get("incident_id") modified_incident_ids.append(incident_id) return GetModifiedRemoteDataResponse(modified_incident_ids) def get_remote_data_command(client, args): remote_args = GetRemoteDataArgs(args) demisto.debug(f"Performing get-remote-data command with incident id: {remote_args.remote_incident_id}") incident_data = {} try: # when Demisto version is 6.1.0 and above, this command will only be automatically executed on incidents # returned from get_modified_remote_data_command so we want to perform extra-data request on those incidents. return_only_updated_incident = not is_demisto_version_ge("6.1.0") # True if version is below 6.1 else False incident_data = get_incident_extra_data_command( client, { "incident_id": remote_args.remote_incident_id, "alerts_limit": 1000, "return_only_updated_incident": return_only_updated_incident, "last_update": remote_args.last_update, }, ) if "The incident was not modified" not in incident_data[0]: demisto.debug(f"Updating XDR incident {remote_args.remote_incident_id}") incident_data = incident_data[2].get("incident") incident_data["id"] = incident_data.get("incident_id") sort_all_list_incident_fields(incident_data) # deleting creation time as it keeps updating in the system del incident_data["creation_time"] # handle unasignment if incident_data.get("assigned_user_mail") is None: handle_incoming_user_unassignment(incident_data) else: # handle owner sync sync_incoming_incident_owners(incident_data) # handle closed issue in XDR and handle outgoing error entry entries = [handle_incoming_closing_incident(incident_data)] reformatted_entries = [] for entry in entries: if entry: reformatted_entries.append(entry) incident_data["in_mirror_error"] = "" return GetRemoteDataResponse(mirrored_object=incident_data, entries=reformatted_entries) else: # no need to update this incident incident_data = {"id": remote_args.remote_incident_id, "in_mirror_error": ""} return GetRemoteDataResponse(mirrored_object=incident_data, entries=[]) except Exception as e: demisto.debug(f"Error in XDR incoming mirror for incident {remote_args.remote_incident_id} \nError message: {e!s}") if "Rate limit exceeded" in str(e): return_error("API rate limit") if incident_data: incident_data["in_mirror_error"] = str(e) sort_all_list_incident_fields(incident_data) # deleting creation time as it keeps updating in the system del incident_data["creation_time"] else: incident_data = {"id": remote_args.remote_incident_id, "in_mirror_error": str(e)} return GetRemoteDataResponse(mirrored_object=incident_data, entries=[]) def createIncidentsListCTF3(max_fetch): """ Custom function to mange which predefinded incident will ve fethced. :param max_fetch: not in use -> the idea was to generate another CTF, however, won't be in use. :return: list of incident to be generated in XSOAR [currently only 1]. """ incidents = [ { "alert_categories": ["Credential Access"], "alert_count": 1, "alerts": [ { "description": "DC1ENV12APC05 successfully accessed administrator by systematically guessing the user's " "password 22 times over an hour with 2 successful logons and 20 failed attempts. " "The user did not log in successfully from 137.184.208.116 during the last 30 days. " "Over the past 30 days, DC1ENV12APC05 has had an average of 0 failed login attempts with " "the user administrator from 137.184.208.116 per day", "action": "DETECTED", "action_country": "UNKNOWN", "action_external_hostname": "kali", "action_file_macro_sha256": None, "action_file_md5": None, "action_file_name": None, "action_file_path": None, "action_file_sha256": None, "action_local_ip": None, "action_local_ip_v6": None, "action_local_port": 0, "action_pretty": "Detected", "action_process_causality_id": None, "action_process_image_command_line": None, "action_process_image_name": None, "action_process_image_sha256": None, "action_process_instance_id": None, "action_process_signature_status": "N/A", "action_process_signature_vendor": None, "action_registry_data": None, "action_registry_full_key": None, "action_registry_key_name": None, "action_registry_value_name": None, "action_remote_ip": "137.184.208.116", "action_remote_ip_v6": None, "action_remote_port": "3889", "actor_causality_id": "AdkP08aY7RwAAAL0AAAAAA==", "actor_process_causality_id": "AdkP08aY7RwAAAL0AAAAAA==", "actor_process_command_line": "C:\\WINDOWS\\system32\\lsass.exe", "actor_process_image_md5": "289d6a47b7692510e2fd3b51979a9fed", "actor_process_image_name": "lsass.exe", "actor_process_image_path": "C:\\Windows\\System32\\lsass.exe", "actor_process_image_sha256": "0777fd312394ae1afeed0ad48ae2d7b5ed6e577117a4f40305eaeb4129233650", "actor_process_instance_id": "AdkP08aY7RwAAAL0AAAAAA==", "actor_process_os_pid": 756, "actor_process_signature_status": "Signed", "actor_process_signature_vendor": "Microsoft Corporation", "actor_thread_thread_id": 4020, "agent_data_collection_status": None, "agent_device_domain": None, "agent_fqdn": None, "agent_host_boot_time": 1671032983204, "agent_install_type": "STANDARD", "agent_ip_addresses_v6": None, "agent_is_vdi": None, "agent_os_sub_type": "Windows 10 [10.0 (Build 19044)]", "agent_os_type": "Windows", "agent_version": "7.9.0.18674", "alert_id": "150807", "alert_type": "Unclassified", "association_strength": 50, "attempt_counter": None, "bioc_category_enum_key": None, "bioc_indicator": None, "case_id": 413, "category": "Credential Access", "causality_actor_causality_id": "AdkP08aY7RwAAAL0AAAAAA==", "causality_actor_process_command_line": "C:\\WINDOWS\\system32\\lsass.exe", "causality_actor_process_execution_time": 1671033022857, "causality_actor_process_image_md5": "289d6a47b7692510e2fd3b51979a9fed", "causality_actor_process_image_name": "lsass.exe", "causality_actor_process_image_path": "C:\\Windows\\System32\\lsass.exe", "causality_actor_process_image_sha256": "0777fd312394ae1afeed0ad48ae2d7b5ed6e577117a4f40305eaeb4129233650", "causality_actor_process_signature_status": "Signed", "causality_actor_process_signature_vendor": "Microsoft Corporation", "cloud_provider": None, "cluster_name": None, "container_id": None, "contains_featured_host": "NO", "contains_featured_ip": "NO", "contains_featured_user": "NO", "deduplicate_tokens": None, "detection_timestamp": 1671730626096, "dns_query_name": None, "dst_action_country": "-", "dst_action_external_hostname": None, "dst_action_external_port": None, "dst_agent_id": "", "dst_association_strength": 0, "dst_causality_actor_process_execution_time": None, "dynamic_fields": None, "end_match_attempt_ts": None, "endpoint_id": "f6ba1a18c35d416c8e27a319cc2fea09", "event_id": "ODczNjk1Mzc1MTMwMzI1NjA1Nw==", "event_sub_type": 1, "event_timestamp": 1671730625375, "event_type": "Login", "events_length": 1, "external_id": "2a6a3f42-9d2d-4226-922f-28e4c2a3147f", "filter_rule_id": None, "fw_app_category": None, "fw_app_id": "", "fw_app_subcategory": None, "fw_app_technology": None, "fw_device_name": "", "fw_email_recipient": None, "fw_email_sender": None, "fw_email_subject": None, "fw_interface_from": "", "fw_interface_to": "", "fw_is_phishing": "N/A", "fw_misc": None, "fw_rule": "", "fw_rule_id": None, "fw_serial_number": "", "fw_url_domain": None, "fw_vsys": None, "fw_xff": None, "host_ip": "172.16.12.40", "host_ip_list": ["172.16.12.40"], "host_name": "DC1ENV12APC05", "identity_sub_type": None, "identity_type": None, "image_name": None, "is_pcap": False, "is_whitelisted": False, "last_modified_ts": None, "local_insert_ts": 1671731192490, "mac": None, "matching_service_rule_id": "fd879de7-fb74-44f0-b699-805d0b08b1fd", "matching_status": "MATCHED", "mitre_tactic_id_and_name": "TA0006 - Credential Access", "mitre_technique_id_and_name": "T1110.001 - Brute Force: Password Guessing", "module_id": None, "name": "Possible external RDP Brute-Force", "operation_name": None, "original_tags": "DS:PANW/XDR Agent", "os_actor_causality_id": None, "os_actor_effective_username": None, "os_actor_process_causality_id": "AdkP08aY7RwAAAL0AAAAAA==", "os_actor_process_command_line": "C:\\WINDOWS\\system32\\lsass.exe", "os_actor_process_image_name": "lsass.exe", "os_actor_process_image_path": "C:\\Windows\\System32\\lsass.exe", "os_actor_process_image_sha256": "0777fd312394ae1afeed0ad48ae2d7b5ed6e577117a4f40305eaeb4129233650", "os_actor_process_instance_id": "AdkP08aY7RwAAAL0AAAAAA==", "os_actor_process_os_pid": 756, "os_actor_process_signature_status": "Signed", "os_actor_process_signature_vendor": "Microsoft Corporation", "os_actor_thread_thread_id": 4020, "project": None, "referenced_resource": None, "resolution_comment": None, "resolution_status": "STATUS_010_NEW", "resource_sub_type": None, "resource_type": None, "severity": "low", "source": "XDR Analytics", "starred": False, "story_id": "ODczNjk1Mzc1MTMwMzI1NjA1Nw==", "tags": "DS:PANW/XDR Agent", "user_agent": None, "user_name": "administrator", } ], "alerts_grouping_status": "Disabled", "assigned_user_mail": None, "assigned_user_pretty_name": None, "creation_time": 1671731222757, "critical_severity_alert_count": 0, "description": "'Possible external RDP Brute-Force' generated by XDR" " Analytics detected on host dc1env12apc05 involving " "user env12\\administrator", "file_artifacts": [ { "alert_count": 1, "file_name": "lsass.exe", "file_sha256": "0777fd312394ae1afeed0ad48ae2d7b5ed6e577117a4f40305eaeb4129233650", "file_signature_status": "SIGNATURE_SIGNED", "file_signature_vendor_name": "Microsoft Corporation", "file_wildfire_verdict": "BENIGN", "is_malicious": False, "is_manual": False, "is_process": True, "low_confidence": False, "type": "HASH", } ], "detection_time": None, "high_severity_alert_count": 0, "host_count": 1, "hosts": ["dc1env12apc05:f6ba1a18c35d416c8e27a319cc2fea09"], "incident_id": "413", "incident_name": None, "incident_sources": ["XDR Analytics"], "is_blocked": False, "low_severity_alert_count": 1, "manual_description": None, "manual_score": None, "manual_severity": None, "med_severity_alert_count": 0, "mitre_tactics_ids_and_names": ["TA0006 - Credential Access"], "mitre_techniques_ids_and_names": ["T1110.001 - Brute Force: Password Guessing"], "modification_time": 1675069594952, "network_artifacts": [ { "alert_count": 1, "is_manual": False, "network_country": "UNKNOWN", "network_domain": "kali", "network_remote_ip": None, "network_remote_port": 0, "type": "DOMAIN", } ], "original_tags": ["DS:PANW/XDR Agent"], "notes": None, "predicted_score": None, "resolve_comment": None, "resolved_timestamp": None, "rule_based_score": None, "severity": "low", "starred": False, "status": "new", "tags": ["DS:PANW/XDR Agent"], "user_count": 1, "users": ["env12\\administrator"], "wildfire_hits": 0, "xdr_url": "https://mytenanet.xdr.us.paloaltonetworks.com/incident-view?caseId=413", "aggregated_score": None, } ] # for i in range(1, max_fetch): # new_data = rawJson # new_data["description"] = f"<{i}>'Image File Execution Options Registry key injection by scripting engine' # generated by XDR BIOC detected on host dc1env12apc02 involving user dc1env12apc02\\win10-regression" # incidents.append(dict(new_data)) return incidents def fetch_incidents( client, first_fetch_time, integration_instance, last_run: dict = None, max_fetch: int = 10, statuses: List = [], starred: Optional[bool] = None, starred_incidents_fetch_window: str = None, ): """ This function will fetch predefined and customized incident using the createIncidentsListCTF3. :param client: N.A. :param first_fetch_time: N.A. :param integration_instance: :param last_run: N.A. :param max_fetch: N.A. :param statuses: N.A. :param starred: N.A. :param starred_incidents_fetch_window: N.A. :return: Incident in the system. """ # Get the last fetch time, if exists last_fetch = last_run.get("time") if isinstance(last_run, dict) else None incidents_from_previous_run = last_run.get("incidents_from_previous_run", []) if isinstance(last_run, dict) else [] # Handle first time fetch, fetch incidents retroactively if last_fetch is None: last_fetch, _ = parse_date_range(first_fetch_time, to_timestamp=True) if starred: starred_incidents_fetch_window, _ = parse_date_range(starred_incidents_fetch_window, to_timestamp=True) incidents = [] if incidents_from_previous_run: raw_incidents = incidents_from_previous_run else: if statuses: raw_incidents = [] # for status in statuses: # raw_incidents += client.get_incidents(gte_creation_time_milliseconds=last_fetch, status=status, # limit=max_fetch, sort_by_creation_time='asc', starred=starred, # starred_incidents_fetch_window=starred_incidents_fetch_window) raw_incidents = sorted(raw_incidents, key=lambda inc: inc["creation_time"]) raw_incidents = createIncidentsListCTF3(max_fetch) else: # raw_incidents = client.get_incidents(gte_creation_time_milliseconds=last_fetch, limit=max_fetch, # sort_by_creation_time='asc', starred=starred, # starred_incidents_fetch_window=starred_incidents_fetch_window) raw_incidents = createIncidentsListCTF3(max_fetch) # save the last 100 modified incidents to the integration context - for mirroring purposes # client.save_modified_incidents_to_integration_context() # maintain a list of non created incidents in a case of a rate limit exception non_created_incidents: list = raw_incidents.copy() next_run = {} try: # The count of incidents, so as not to pass the limit count_incidents = 0 for raw_incident in raw_incidents: incident_id = raw_incident.get("incident_id") # incident_data = get_incident_extra_data_command(client, {"incident_id": incident_id, # "alerts_limit": 1000})[2].get('incident') incident_data = raw_incident sort_all_list_incident_fields(incident_data) incident_data["mirror_direction"] = MIRROR_DIRECTION.get(demisto.params().get("mirror_direction", "None"), None) incident_data["mirror_instance"] = integration_instance incident_data["last_mirrored_in"] = int(datetime.now().timestamp() * 1000) description = raw_incident.get("description") occurred = timestamp_to_datestring(raw_incident["creation_time"], TIME_FORMAT + "Z") incident = { "name": f"XDR Incident {incident_id} - {description}", "occurred": occurred, "rawJSON": json.dumps(incident_data), } if demisto.params().get("sync_owners") and incident_data.get("assigned_user_mail"): incident["owner"] = demisto.findUser(email=incident_data.get("assigned_user_mail")).get("username") # Update last run and add incident if the incident is newer than last fetch if raw_incident["creation_time"] > last_fetch: last_fetch = raw_incident["creation_time"] incidents.append(incident) non_created_incidents.remove(raw_incident) count_incidents += 1 if count_incidents == max_fetch: break except Exception as e: if "Rate limit exceeded" in str(e): demisto.info( f"Cortex XDR - rate limit exceeded, number of non created incidents is: " f"'{len(non_created_incidents)}'.\n The incidents will be created in the next fetch" ) else: raise if non_created_incidents: next_run["incidents_from_previous_run"] = non_created_incidents else: next_run["incidents_from_previous_run"] = [] next_run["time"] = last_fetch + 1 return next_run, incidents def get_endpoints_by_status_command(client: Client, args: Dict) -> CommandResults: status = args.get("status") status = argToList(status) last_seen_gte = arg_to_timestamp(arg=args.get("last_seen_gte"), arg_name="last_seen_gte") last_seen_lte = arg_to_timestamp(arg=args.get("last_seen_lte"), arg_name="last_seen_lte") endpoints_count, raw_res = client.get_endpoints_by_status(status, last_seen_gte=last_seen_gte, last_seen_lte=last_seen_lte) ec = {"status": status, "count": endpoints_count} return CommandResults( readable_output=f"{status} endpoints count: {endpoints_count}", outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.EndpointsStatus", outputs_key_field="status", outputs=ec, raw_response=raw_res, ) def file_details_results(client: Client, args: Dict, add_to_context: bool) -> None: return_entry, file_results = retrieve_file_details_command(client, args, add_to_context) demisto.results(return_entry) if file_results: demisto.results(file_results) def get_alerts_by_filter_command_ctf(client: CoreClient, args: Dict) -> CommandResults: # type:ignore[no-redef] """ This command was changed to return predefined alerts. Instead of using the passed client, the raw_response will contain the returned json. :param client: N.A. :param args: N.A. :return: List of predefined json alerts. """ prefix = "PaloAltoNetworksXDR" # filter_data['filter'] = filter_res # demisto.debug(f'sending the following request data: {request_data}') # raw_response = client.get_alerts_by_filter_data(request_data) raw_response = { "alerts": [ { "alert_fields": { "action_country": ["UNKNOWN"], "action_file_name": ["dnsapi.dll"], "action_file_sha256": ["7A31418E4ABC333EC28E11A05ED794A6EE930D6B2CDE84DA4F7B959B49335FE4"], "action_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "activated": "0001-01-01T00:00:00Z", "activatingingUserId": "", "actor_effective_username": ["env4.local\\Administrator"], "actor_process_command_line": ["C:\\Users\\administrator.ENV4\\Downloads\\8866115678\\example.exe"], "actor_process_image_md5": ["1392aef7cd09a1b87ef651a0bf1c011"], "actor_process_image_name": ["example.exe"], "actor_process_image_path": ["C:\\Users\\administrator.ENV4\\Downloads\\8866115678\\example.exe"], "actor_process_image_sha256": ["7734984082dfe13fas24264ad1c2cdc79180db273fa196bd3d2e48915d9d1e4b"], "actor_process_instance_id": ["AdkwzkxP2AYAAB/YAAAAAA=="], "actor_process_os_pid": [8152], "actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "agent_data_collection_status": False, "agent_device_domain": "env4.local", "agent_file_path": ["C:\\\\Windows\\\\system32\\\\dnsapi.dll"], "agent_fqdn": "DC1ENV4APC01.env4.local", "agent_hostname": "DC1ENV4APC01", "agent_id": "ac848acbd7504115b6624c9b1d755000", "agent_install_type": "STANDARD", "agent_ip_addresses": ["172.16.4.122"], "agent_os_sub_type": "10.0.19044", "agent_os_type": "AGENT_OS_WINDOWS", "agent_version": "7.9.0.20664", "agentversion": ["7.9.0.20664"], "alert_action_status": "BLOCKED", "alert_action_status_readable": "prevented (blocked)", "alert_category": "Malware", "alert_description": "Suspicious executable detected", "alert_description_raw": "Suspicious executable detected", "alert_is_fp": False, "alert_name": "Local Analysis Malware", "alert_source": "TRAPS", "alert_type": "Unclassified", "asmdevcheck": False, "association_strength": [50], "attempt_counter": 0, "case_id": 74, "causality_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "closeReason": "", "closed": "0001-01-01T00:00:00Z", "closingUserId": "", "contains_featured_host": ["NO"], "contains_featured_ip": ["NO"], "contains_featured_user": ["NO"], "dbotMirrorDirection": "", "dbotMirrorId": "", "dbotMirrorInstance": "", "dbotMirrorLastSync": "0001-01-01T00:00:00Z", "digitalguardianattachmentfilename": "dnsapi.dll", "digitalguardianfilename": "dnsapi.dll", "droppedCount": 0, "dst_agent_os_type": ["NO_HOST"], "dueDate": "0001-01-01T00:00:00Z", "event_timestamp": [1674659141991], "event_type": [1], "events": [], "external_id": "e08916bd582b401d862ddb2dcb704def", "family_tags": ["DS:PANW/XDR Agent"], "feedBased": False, "feedbased": False, "filenames": "dnsapi.dll", "filepaths": ["C:\\\\Windows\\\\system32\\\\dnsapi.dll"], "followup": False, "gibleakedfilename": "dnsapi.dll", "internal_id": "14864", "investigationId": "14864", "isDebug": False, "is_deleted": False, "is_identity": False, "is_pcap": False, "is_rule_triggering": False, "is_whitelisted": False, "is_xsoar_alert": False, "lastJobRunTime": "0001-01-01T00:00:00Z", "lastOpen": "0001-01-01T00:00:00Z", "last_modified_ts": 1678193813541, "linkedCount": 0, "local_insert_ts": 1674659148751, "mac": "00:50:56:9f:f5:5f", "matching_status": "UNMATCHABLE", "module_id": ["Local Analysis"], "module_name": ["COMPONENT_LOCAL_ANALYSIS"], "notifyTime": "2023-03-07T12:56:50.991890521Z", "occurred": "0001-01-01T00:00:00Z", "openDuration": 0, "original_severity": "SEV_030_MEDIUM", "os_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "passwordresetsuccessfully": False, "pcapfilename": "dnsapi.dll", "playbookId": "5a05f427-1416-426a-89d8-df7c89992486", "reason": "", "reminder": "0001-01-01T00:00:00Z", "resolution_status": "STATUS_020_UNDER_INVESTIGATION", "resolution_status_modified_ts": 1674659179219, "runStatus": "error", "severity": "SEV_030_MEDIUM", "sha256": "7A31418E4ABC333EC28E11A05ED794A6EE930D6B2CDE84DA4F7B959B49335FE4", "sla": 0, "sourceInstance": "", "source_insert_ts": 1674659141991, "starred": False, "tags": ["DS:PANW/XDR Agent"], "values_changed": True, "zipcode": None, }, "incident_fields": None, }, { "alert_fields": { "action_country": ["UNKNOWN"], "action_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "activated": "0001-01-01T00:00:00Z", "actor_effective_username": ["env4.local\\Administrator"], "actor_process_command_line": ['"C:\\Users\\administrator.ENV4\\Downloads\\8872230438\\wanmgr.exe" '], "actor_process_image_md5": ["7265719c94c5ffbcdbb5c23428d8ca68"], "actor_process_image_name": ["wanmgr.exe"], "actor_process_image_path": ["C:\\Users\\administrator.ENV4\\Downloads\\8872230438\\wanmgr.exe"], "actor_process_image_sha256": ["000001e7a228b2a7abdf7f7e3313324332b725e86907dde32176bddbbbb27"], "actor_process_instance_id": ["Adkwy9zWJhIAAA1sAAAAAA=="], "actor_process_os_pid": [3436], "actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "agent_data_collection_status": False, "agent_device_domain": "env4.local", "agent_fqdn": "DC1ENV4APC01.env4.local", "agent_hostname": "DC1ENV4APC01", "agent_id": "ac848acbd7504115b6624c9b1d755000", "agent_install_type": "STANDARD", "agent_ip_addresses": ["172.16.4.122"], "agent_os_sub_type": "10.0.19044", "agent_os_type": "AGENT_OS_WINDOWS", "agent_version": "7.9.0.20664", "alert_action_status": "BLOCKED", "alert_action_status_readable": "prevented (blocked)", "alert_category": "Malware", "alert_description": "Suspicious executable detected", "alert_description_raw": "Suspicious executable detected", "alert_is_fp": False, "alert_name": "WildFire Malware", "alert_source": "TRAPS", "alert_type": "Unclassified", "asmdevcheck": False, "association_strength": [50], "attempt_counter": 0, "case_id": 73, "causality_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "closed": "0001-01-01T00:00:00Z", "contains_featured_host": ["NO"], "contains_featured_ip": ["NO"], "contains_featured_user": ["NO"], "dbotMirrorLastSync": "0001-01-01T00:00:00Z", "droppedCount": 0, "dst_agent_os_type": ["NO_HOST"], "dueDate": "0001-01-01T00:00:00Z", "dynamic_fields": { "action_country": ["UNKNOWN"], "action_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "activated": "0001-01-01T00:00:00Z", "activatingingUserId": "", "actor_effective_username": ["env4.local\\Administrator"], "actor_process_command_line": ['"C:\\Users\\administrator.ENV4\\Downloads\\8872230438\\wanmgr.exe" '], "actor_process_image_md5": ["7265719c94c5ffbcdbb5c23428d8ca68"], "actor_process_image_name": ["wanmgr.exe"], "actor_process_image_path": ["C:\\Users\\administrator.ENV4\\Downloads\\8872230438\\wanmgr.exe"], "actor_process_image_sha256": ["000001e7a228b2a7abdf7f7e3313324332b725e86907dde32176bddbbbb27"], "actor_process_os_pid": [3436], "actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "agent_device_domain": "env4.local", "agent_fqdn": "DC1ENV4APC01.env4.local", "agent_hostname": "DC1ENV4APC01", "agent_id": "ac848acbd7504115b6624c9b1d755000", "agent_ip_addresses": ["172.16.4.122"], "agent_os_sub_type": "10.0.19044", "agent_os_type": "AGENT_OS_WINDOWS", "alert_action_status": "BLOCKED", "alert_category": "Malware", "alert_description": "Suspicious executable detected", "alert_name": "WildFire Malware", "alert_source": "TRAPS", "alert_type": "Unclassified", "category": "", "causality_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "closeReason": "", "closed": "0001-01-01T00:00:00Z", "closingUserId": "", "contains_featured_host": ["NO"], "contains_featured_ip": ["NO"], "contains_featured_user": ["NO"], "dbotMirrorDirection": "", "dbotMirrorId": "", "dbotMirrorInstance": "", "dbotMirrorLastSync": "0001-01-01T00:00:00Z", "droppedCount": 0, "dueDate": "0001-01-01T00:00:00Z", "event_type": [1], "feedBased": False, "internal_id": 14863, "investigationId": "14863", "isDebug": False, "is_whitelisted": False, "lastJobRunTime": "0001-01-01T00:00:00Z", "lastOpen": "0001-01-01T00:00:00Z", "linkedCount": 0, "mac": "00:50:56:9f:f5:5f", "module_id": ["WildFire"], "notifyTime": "0001-01-01T00:00:00Z", "occurred": "0001-01-01T00:00:00Z", "openDuration": 0, "os_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "phase": "", "playbookId": "f1fa9cef-75be-429e-8d16-e29350af29a9", "reason": "", "reminder": "0001-01-01T00:00:00Z", "resolution_comment": "", "resolution_status": "STATUS_020_UNDER_INVESTIGATION", "runStatus": "pending", "severity": "SEV_030_MEDIUM", "sla": 0, "sourceInstance": "", "source_insert_ts": 1674658129127, "starred": False, }, "event_timestamp": [1674658095784], "event_type": [1], "events": [], "external_id": "57e81344f4a340538b540c770f36d7aa", "family_tags": ["DS:PANW/XDR Agent"], "feedBased": False, "feedbased": False, "followup": False, "internal_id": "14863", "investigationId": "14863", "isDebug": False, "is_pcap": False, "is_rule_triggering": False, "is_whitelisted": False, "is_xsoar_alert": False, "lastJobRunTime": "0001-01-01T00:00:00Z", "lastOpen": "0001-01-01T00:00:00Z", "linkedCount": 0, "local_insert_ts": 1674658099828, "mac": "00:50:56:9f:f5:5f", "matching_status": "UNMATCHABLE", "module_id": ["WildFire"], "module_name": ["COMPONENT_WILDFIRE"], "notifyTime": "0001-01-01T00:00:00Z", "occurred": "0001-01-01T00:00:00Z", "openDuration": 0, "original_severity": "SEV_030_MEDIUM", "os_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "passwordresetsuccessfully": False, "playbookId": "f1fa9cef-75be-429e-8d16-e29350af29a9", "reminder": "0001-01-01T00:00:00Z", "resolution_comment": "", "resolution_status": "STATUS_020_UNDER_INVESTIGATION", "resolution_status_modified_ts": 1674658129232, "runStatus": "pending", "severity": "SEV_030_MEDIUM", "sla": 0, "source_insert_ts": 1674658095784, "starred": False, "tags": ["DS:PANW/XDR Agent"], "zipcode": None, }, "incident_fields": None, }, { "alert_fields": { "action_country": ["UNKNOWN"], "action_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "activated": "0001-01-01T00:00:00Z", "actor_effective_username": ["env4.local\\Administrator"], "actor_process_command_line": [ '"C:\\Users\\administrator.ENV4\\Downloads\\8872362056\\' '000001e7a228b2a7abdfa4b3c8522df32b725e86907dde32176bccbbbb27.exe" ' ], "actor_process_image_md5": ["e9aaa45159dacbc598aadfb6311eae54"], "actor_process_image_name": ["000001e7a228b2a7abdf7f7e40313324332b725e86907dde32176bccbbbb27.exe"], "actor_process_image_path": [ "C:\\Users\\administrator.ENV4\\Downloads\\8872362056\\" "000001e7a228b2a7abdf7f7e40313324332b725e86907dde32176bccbbbb27.exe" ], "actor_process_image_sha256": ["000001e7a228b2a7abdf7f7e40313324332b725e86907dde32176bccbbbb27"], "actor_process_instance_id": ["AdkwxLhiKM4AABJsAAAAAA=="], "actor_process_os_pid": [4716], "actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "agent_data_collection_status": False, "agent_device_domain": "env4.local", "agent_fqdn": "DC1ENV4APC01.env4.local", "agent_hostname": "DC1ENV4APC01", "agent_id": "ac848acbd7504115b6624c9b1d755000", "agent_install_type": "STANDARD", "agent_ip_addresses": ["172.16.4.122"], "agent_os_sub_type": "10.0.19044", "agent_os_type": "AGENT_OS_WINDOWS", "agent_version": "7.9.0.20664", "alert_action_status": "BLOCKED", "alert_action_status_readable": "prevented (blocked)", "alert_category": "Malware", "alert_description": "Suspicious executable detected", "alert_description_raw": "Suspicious executable detected", "alert_is_fp": False, "alert_name": "WildFire Malware", "alert_source": "TRAPS", "alert_type": "Unclassified", "asmdevcheck": False, "association_strength": [50], "attempt_counter": 0, "case_id": 72, "causality_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "closed": "0001-01-01T00:00:00Z", "contains_featured_host": ["NO"], "contains_featured_ip": ["NO"], "contains_featured_user": ["NO"], "dbotMirrorLastSync": "0001-01-01T00:00:00Z", "droppedCount": 0, "dst_agent_os_type": ["NO_HOST"], "dueDate": "0001-01-01T00:00:00Z", "dynamic_fields": { "action_country": ["UNKNOWN"], "action_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "activated": "0001-01-01T00:00:00Z", "activatingingUserId": "", "actor_effective_username": ["env4.local\\Administrator"], "actor_process_command_line": [ '"C:\\Users\\administrator.ENV4\\Downloads\\8872362056\\000001e7a228b2a7abdf7f7e40313324332b' '725e86907dde32176bccbbbb27.exe" ' ], "actor_process_image_md5": ["e9aaa45159dacbc598aadfb6311eae54"], "actor_process_image_name": ["000001e7a228b2a7abdf7f7e40313324332b725e86907dde32176bccbbbb27.exe"], "actor_process_image_path": [ "C:\\Users\\administrator.ENV4\\Downloads\\8872362056\\000001e7a228b2a7abdf7f7e40313324332b725e86907dde32176bccbbbb27.exe" # noqa: E501 ], "actor_process_image_sha256": ["000001e7a228b2a7abdf7f7e40313324332b725e86907dde32176bccbbbb27"], "actor_process_os_pid": [4716], "actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "agent_device_domain": "env4.local", "agent_fqdn": "DC1ENV4APC01.env4.local", "agent_hostname": "DC1ENV4APC01", "agent_id": "ac848acbd7504115b6624c9b1d755000", "agent_ip_addresses": ["172.16.4.122"], "agent_os_sub_type": "10.0.19044", "agent_os_type": "AGENT_OS_WINDOWS", "alert_action_status": "BLOCKED", "alert_category": "Malware", "alert_description": "Suspicious executable detected", "alert_name": "WildFire Malware", "alert_source": "TRAPS", "alert_type": "Unclassified", "category": "", "causality_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "closeReason": "", "closed": "0001-01-01T00:00:00Z", "closingUserId": "", "contains_featured_host": ["NO"], "contains_featured_ip": ["NO"], "contains_featured_user": ["NO"], "dbotMirrorDirection": "", "dbotMirrorId": "", "dbotMirrorInstance": "", "dbotMirrorLastSync": "0001-01-01T00:00:00Z", "droppedCount": 0, "dueDate": "0001-01-01T00:00:00Z", "event_type": [1], "feedBased": False, "internal_id": 14862, "investigationId": "14862", "isDebug": False, "is_whitelisted": False, "lastJobRunTime": "0001-01-01T00:00:00Z", "lastOpen": "0001-01-01T00:00:00Z", "linkedCount": 0, "mac": "00:50:56:9f:f5:5f", "module_id": ["WildFire"], "notifyTime": "0001-01-01T00:00:00Z", "occurred": "0001-01-01T00:00:00Z", "openDuration": 0, "os_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "phase": "", "playbookId": "f1fa9cef-75be-429e-8d16-e29350af29a9", "reason": "", "reminder": "0001-01-01T00:00:00Z", "resolution_comment": "", "resolution_status": "STATUS_020_UNDER_INVESTIGATION", "runStatus": "pending", "severity": "SEV_030_MEDIUM", "sla": 0, "sourceInstance": "", "source_insert_ts": 1674655039367, "starred": False, }, "event_timestamp": [1674655027190], "event_type": [1], "events": [], "external_id": "4ee579e1cbe4495280e536bd6d6ca866", "family_tags": ["DS:PANW/XDR Agent"], "feedBased": False, "feedbased": False, "followup": False, "internal_id": "14862", "investigationId": "14862", "isDebug": False, "is_pcap": False, "is_rule_triggering": False, "is_whitelisted": False, "is_xsoar_alert": False, "lastJobRunTime": "0001-01-01T00:00:00Z", "lastOpen": "0001-01-01T00:00:00Z", "linkedCount": 0, "local_insert_ts": 1674655034860, "mac": "00:50:56:9f:f5:5f", "matching_status": "UNMATCHABLE", "module_id": ["WildFire"], "module_name": ["COMPONENT_WILDFIRE"], "notifyTime": "0001-01-01T00:00:00Z", "occurred": "0001-01-01T00:00:00Z", "openDuration": 0, "original_severity": "SEV_030_MEDIUM", "os_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "passwordresetsuccessfully": False, "playbookId": "f1fa9cef-75be-429e-8d16-e29350af29a9", "reminder": "0001-01-01T00:00:00Z", "resolution_comment": "", "resolution_status": "STATUS_020_UNDER_INVESTIGATION", "resolution_status_modified_ts": 1674655039472, "runStatus": "pending", "severity": "SEV_030_MEDIUM", "sla": 0, "source_insert_ts": 1674655027190, "starred": False, "tags": ["DS:PANW/XDR Agent"], "zipcode": None, }, "incident_fields": None, }, { "alert_fields": { "action_country": ["UNKNOWN"], "action_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "activated": "0001-01-01T00:00:00Z", "actor_effective_username": ["env4.local\\Administrator"], "actor_process_command_line": ['"C:\\Users\\administrator.ENV4\\Downloads\\8872230438\\wanmgr.exe" '], "actor_process_image_md5": ["7265719c94c5ffbcdbb5c23428d8ca68"], "actor_process_image_name": ["wanmgr.exe"], "actor_process_image_path": ["C:\\Users\\administrator.ENV4\\Downloads\\8872230438\\wanmgr.exe"], "actor_process_image_sha256": ["000001e7a228b2a7abdf7f7e3313324332b725e86907dde32176bddbbbb27"], "actor_process_instance_id": ["AdkwsQxs4pMAAB9YAAAAAA=="], "actor_process_os_pid": [8024], "actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "agent_data_collection_status": False, "agent_device_domain": "env4.local", "agent_fqdn": "DC1ENV4APC01.env4.local", "agent_hostname": "DC1ENV4APC01", "agent_id": "ac848acbd7504115b6624c9b1d755000", "agent_install_type": "STANDARD", "agent_ip_addresses": ["172.16.4.122"], "agent_os_sub_type": "10.0.19044", "agent_os_type": "AGENT_OS_WINDOWS", "agent_version": "7.9.0.20664", "alert_action_status": "BLOCKED", "alert_action_status_readable": "prevented (blocked)", "alert_category": "Malware", "alert_description": "Suspicious executable detected", "alert_description_raw": "Suspicious executable detected", "alert_is_fp": False, "alert_name": "WildFire Malware", "alert_source": "TRAPS", "alert_type": "Unclassified", "asmdevcheck": False, "association_strength": [50], "attempt_counter": 0, "case_id": 72, "causality_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "closed": "0001-01-01T00:00:00Z", "contains_featured_host": ["NO"], "contains_featured_ip": ["NO"], "contains_featured_user": ["NO"], "dbotMirrorLastSync": "0001-01-01T00:00:00Z", "droppedCount": 0, "dst_agent_os_type": ["NO_HOST"], "dueDate": "0001-01-01T00:00:00Z", "dynamic_fields": { "action_country": ["UNKNOWN"], "action_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "activated": "0001-01-01T00:00:00Z", "activatingingUserId": "", "actor_effective_username": ["env4.local\\Administrator"], "actor_process_command_line": ['"C:\\Users\\administrator.ENV4\\Downloads\\8872230438\\wanmgr.exe" '], "actor_process_image_md5": ["7265719c94c5ffbcdbb5c23428d8ca68"], "actor_process_image_name": ["wanmgr.exe"], "actor_process_image_path": ["C:\\Users\\administrator.ENV4\\Downloads\\8872230438\\wanmgr.exe"], "actor_process_image_sha256": ["000001e7a228b2a7abdf7f7e3313324332b725e86907dde32176bddbbbb27"], "actor_process_os_pid": [8024], "actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "agent_device_domain": "env4.local", "agent_fqdn": "DC1ENV4APC01.env4.local", "agent_hostname": "DC1ENV4APC01", "agent_id": "ac848acbd7504115b6624c9b1d755000", "agent_ip_addresses": ["172.16.4.122"], "agent_os_sub_type": "10.0.19044", "agent_os_type": "AGENT_OS_WINDOWS", "alert_action_status": "BLOCKED", "alert_category": "Malware", "alert_description": "Suspicious executable detected", "alert_name": "WildFire Malware", "alert_source": "TRAPS", "alert_type": "Unclassified", "category": "", "causality_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "closeReason": "", "closed": "0001-01-01T00:00:00Z", "closingUserId": "", "contains_featured_host": ["NO"], "contains_featured_ip": ["NO"], "contains_featured_user": ["NO"], "dbotMirrorDirection": "", "dbotMirrorId": "", "dbotMirrorInstance": "", "dbotMirrorLastSync": "0001-01-01T00:00:00Z", "droppedCount": 0, "dueDate": "0001-01-01T00:00:00Z", "event_type": [1], "feedBased": False, "internal_id": 14861, "investigationId": "14861", "isDebug": False, "is_whitelisted": False, "lastJobRunTime": "0001-01-01T00:00:00Z", "lastOpen": "0001-01-01T00:00:00Z", "linkedCount": 0, "mac": "00:50:56:9f:f5:5f", "module_id": ["WildFire"], "notifyTime": "0001-01-01T00:00:00Z", "occurred": "0001-01-01T00:00:00Z", "openDuration": 0, "os_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "phase": "", "playbookId": "f1fa9cef-75be-429e-8d16-e29350af29a9", "reason": "", "reminder": "0001-01-01T00:00:00Z", "resolution_comment": "", "resolution_status": "STATUS_020_UNDER_INVESTIGATION", "runStatus": "pending", "severity": "SEV_030_MEDIUM", "sla": 0, "sourceInstance": "", "source_insert_ts": 1674646610961, "starred": False, }, "event_timestamp": [1674646578590], "event_type": [1], "events": [], "external_id": "303a293a9227422da0475cca1f6a8710", "family_tags": ["DS:PANW/XDR Agent"], "feedBased": False, "feedbased": False, "followup": False, "internal_id": "14861", "investigationId": "14861", "isDebug": False, "is_pcap": False, "is_rule_triggering": False, "is_whitelisted": False, "is_xsoar_alert": False, "lastJobRunTime": "0001-01-01T00:00:00Z", "lastOpen": "0001-01-01T00:00:00Z", "linkedCount": 0, "local_insert_ts": 1674646586780, "mac": "00:50:56:9f:f5:5f", "matching_status": "UNMATCHABLE", "module_id": ["WildFire"], "module_name": ["COMPONENT_WILDFIRE"], "notifyTime": "0001-01-01T00:00:00Z", "occurred": "0001-01-01T00:00:00Z", "openDuration": 0, "original_severity": "SEV_030_MEDIUM", "os_actor_process_signature_status": ["SIGNATURE_UNAVAILABLE"], "passwordresetsuccessfully": False, "playbookId": "f1fa9cef-75be-429e-8d16-e29350af29a9", "reminder": "0001-01-01T00:00:00Z", "resolution_comment": "", "resolution_status": "STATUS_020_UNDER_INVESTIGATION", "resolution_status_modified_ts": 1674646611059, "runStatus": "pending", "severity": "SEV_030_MEDIUM", "sla": 0, "source_insert_ts": 1674646578590, "starred": False, "tags": ["DS:PANW/XDR Agent"], "zipcode": None, }, "incident_fields": None, }, ], "result_count": 4, } context = [] for alert in raw_response.get("alerts", []): # type:ignore[attr-defined] alert = alert.get("alert_fields") if "alert_action_status" in alert: # convert the status, if failed take the original status action_status = alert.get("alert_action_status") alert["alert_action_status_readable"] = ALERT_STATUS_TYPES.get(action_status, action_status) context.append(alert) human_readable = [ { "Alert ID": alert.get("internal_id"), "Detection Timestamp": timestamp_to_datestring(alert.get("source_insert_ts")), "Name": alert.get("alert_name"), "Severity": alert.get("severity"), "Category": alert.get("alert_category"), "Action": alert.get("alert_action_status_readable"), "Description": alert.get("alert_description"), "Host IP": alert.get("agent_ip_addresses"), "Host Name": alert.get("agent_hostname"), } for alert in context ] return CommandResults( outputs_prefix=f"{prefix}.Alert", outputs_key_field="internal_id", outputs=context, readable_output=tableToMarkdown("Alerts", human_readable), raw_response=raw_response, ) def get_contributing_event_command(client: Client, args: Dict) -> CommandResults: if alert_ids := argToList(args.get("alert_ids")): alerts = [] for alert_id in alert_ids: if alert := client.get_contributing_event_by_alert_id(int(alert_id)): page_number = max(int(args.get("page_number", 1)), 1) - 1 # Min & default zero (First page) page_size = max(int(args.get("page_size", 50)), 0) # Min zero & default 50 offset = page_number * page_size limit = max(int(args.get("limit", 0)), 0) or offset + page_size alert_with_events = { "alertID": str(alert_id), "events": alert.get("events", [])[offset:limit], } alerts.append(alert_with_events) readable_output = tableToMarkdown( "Contributing events", alerts, headerTransform=pascalToSpace, removeNull=True, is_auto_json_transform=True ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.ContributingEvent", outputs_key_field="alertID", outputs=alerts, raw_response=alerts, ) else: return CommandResults(readable_output="The alert_ids argument cannot be empty.") def replace_featured_field_command(client: Client, args: Dict) -> CommandResults: field_type = args.get("field_type", "") values = argToList(args.get("values")) len_values = len(values) comments = argToList(args.get("comments"))[:len_values] ad_type = argToList(args.get("ad_type", "group"))[:len_values] if field_type == "ad_groups": fields = [ {"value": field[0], "comment": field[1], "type": field[2]} for field in zip_longest(values, comments, ad_type, fillvalue="") ] else: fields = [{"value": field[0], "comment": field[1]} for field in zip_longest(values, comments, fillvalue="")] client.replace_featured_field(field_type, fields) result = {"fieldType": field_type, "fields": fields} readable_output = tableToMarkdown( f'Replaced featured: {result.get("fieldType")}', result.get("fields"), headerTransform=pascalToSpace ) return CommandResults( readable_output=readable_output, outputs_prefix=f"{INTEGRATION_CONTEXT_BRAND}.FeaturedField", outputs_key_field="fieldType", outputs=result, raw_response=result, ) def main(): # pragma: no cover """ Executes an integration command """ command = demisto.command() params = demisto.params() LOG(f"Command being called is {command}") # using two different credentials object as they both fields need to be encrypted # api_key = params.get('apikey') or params.get('apikey_creds').get('password', '') # api_key_id = params.get('apikey_id') or params.get('apikey_id_creds').get('password', '') first_fetch_time = params.get("fetch_time", "3 days") # base_url = urljoin(params.get('url'), '/public_api/v1') params.get("proxy") not params.get("insecure", False) statuses = params.get("status") starred = True if params.get("starred") else None starred_incidents_fetch_window = params.get("starred_incidents_fetch_window", "3 days") try: int(params.get("timeout", 120)) except ValueError as e: demisto.debug(f"Failed casting timeout parameter to int, falling back to 120 - {e}") try: max_fetch = int(params.get("max_fetch", 10)) except ValueError as e: demisto.debug(f"Failed casting max fetch parameter to int, falling back to 10 - {e}") max_fetch = 10 "".join([secrets.choice(string.ascii_letters + string.digits) for _ in range(64)]) str(int(datetime.now(timezone.utc).timestamp()) * 1000) # auth_key = "%s%s%s" % (api_key, nonce, timestamp) # auth_key = auth_key.encode("utf-8") # api_key_hash = hashlib.sha256(auth_key).hexdigest() # if argToBoolean(params.get("prevent_only", False)): # api_key_hash = api_key # headers = { # "x-xdr-timestamp": timestamp, # "x-xdr-nonce": nonce, # "x-xdr-auth-id": str(api_key_id), # "Authorization": api_key_hash # } # client = Client( # base_url=base_url, # proxy=proxy, # verify=verify_cert, # headers=headers, # timeout=timeout # ) client = None args = demisto.args() args["integration_context_brand"] = INTEGRATION_CONTEXT_BRAND args["integration_name"] = INTEGRATION_NAME try: if command == "test-module": # client.test_module(first_fetch_time) demisto.results("ok") elif command == "fetch-incidents": integration_instance = demisto.integrationInstance() next_run, incidents = fetch_incidents( client, first_fetch_time, integration_instance, demisto.getLastRun().get("next_run"), max_fetch, statuses, starred, starred_incidents_fetch_window, ) last_run_obj = demisto.getLastRun() last_run_obj["next_run"] = next_run demisto.setLastRun(last_run_obj) demisto.incidents(incidents) elif command == "xdr-get-incident-extra-data-ctf": return_outputs(*get_incident_extra_data_command(client, args)) elif command == "xdr-update-incident": # return_outputs(*update_incident_command(client, args)) # type:ignore[name-defined] return_outputs(None) elif command == "xdr-get-endpoints": return_results(get_endpoints_command(client, args)) elif command == "xdr-endpoint-alias-change": return_results(endpoint_alias_change_command(client, **args)) # type:ignore[arg-type] elif command == "xdr-insert-parsed-alert": return_outputs(*insert_parsed_alert_command(client, args)) elif command == "xdr-insert-cef-alerts": return_outputs(*insert_cef_alerts_command(client, args)) elif command == "xdr-isolate-endpoint": return_results(isolate_endpoint_command(client, args)) # type:ignore[arg-type] elif command == "xdr-endpoint-isolate-ctf": """ This command not in use. """ polling_args = {**args, "endpoint_id_list": args.get("endpoint_id")} return_results( run_polling_command( client=client, # type:ignore[arg-type] args=polling_args, cmd="xdr-endpoint-isolate", command_function=isolate_endpoint_command, command_decision_field="action_id", results_function=get_endpoints_command, polling_field="is_isolated", polling_value=["AGENT_ISOLATED"], stop_polling=True, ) ) elif command == "xdr-unisolate-endpoint": return_results(unisolate_endpoint_command(client, args)) elif command == "xdr-endpoint-unisolate": polling_args = {**args, "endpoint_id_list": args.get("endpoint_id")} return_results( run_polling_command( client=client, # type:ignore[arg-type] args=polling_args, cmd="xdr-endpoint-unisolate", command_function=unisolate_endpoint_command, command_decision_field="action_id", results_function=get_endpoints_command, polling_field="is_isolated", polling_value=[ "AGENT_UNISOLATED", "CANCELLED", "ֿPENDING_ABORT", "ABORTED", "EXPIRED", "COMPLETED_PARTIAL", "COMPLETED_SUCCESSFULLY", "FAILED", "TIMEOUT", ], stop_polling=True, ) ) elif command == "xdr-get-distribution-url": return_outputs(*get_distribution_url_command(client, args)) elif command == "xdr-get-create-distribution-status": return_outputs(*get_distribution_status_command(client, args)) elif command == "xdr-get-distribution-versions": return_outputs(*get_distribution_versions_command(client, args)) elif command == "xdr-create-distribution": return_outputs(*create_distribution_command(client, args)) elif command == "xdr-get-audit-management-logs": return_outputs(*get_audit_management_logs_command(client, args)) elif command == "xdr-get-audit-agent-reports": return_outputs(*get_audit_agent_reports_command(client, args)) elif command == "xdr-quarantine-files": return_results(quarantine_files_command(client, args)) elif command == "xdr-file-quarantine": return_results( run_polling_command( client=client, # type:ignore[arg-type] args=args, cmd="xdr-file-quarantine", command_function=quarantine_files_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "core-quarantine-files": polling_args = {**args, "endpoint_id": argToList(args.get("endpoint_id_list"))[0]} return_results( run_polling_command( client=client, # type:ignore[arg-type] args=polling_args, cmd="core-quarantine-files", command_function=quarantine_files_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-get-quarantine-status": return_results(get_quarantine_status_command(client, args)) elif command == "xdr-restore-file": return_results(restore_file_command(client, args)) elif command == "xdr-file-restore": return_results( run_polling_command( client=client, # type:ignore[arg-type] args=args, cmd="xdr-file-restore", command_function=restore_file_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-endpoint-scan": return_results(endpoint_scan_command(client, args)) # type:ignore[arg-type] elif command == "xdr-endpoint-scan-execute": return_results( run_polling_command( client=client, # type:ignore[arg-type] args=args, cmd="xdr-endpoint-scan-execute", command_function=endpoint_scan_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-endpoint-scan-abort": return_results(endpoint_scan_abort_command(client, args)) elif command == "get-mapping-fields": return_results(get_mapping_fields_command()) elif command == "get-remote-data": return_results(get_remote_data_command(client, args)) elif command == "update-remote-system": # return_results(update_remote_system_command(client, args)) # type:ignore[name-defined] return_results(None) elif command == "xdr-delete-endpoints": return_outputs(*delete_endpoints_command(client, args)) # type:ignore[arg-type] elif command == "xdr-get-policy": return_outputs(*get_policy_command(client, args)) # type:ignore[arg-type] elif command == "xdr-get-endpoint-device-control-violations": return_outputs(*get_endpoint_device_control_violations_command(client, args)) # type:ignore[arg-type] elif command == "xdr-retrieve-files": return_results(retrieve_files_command(client, args)) # type:ignore[arg-type] elif command == "xdr-file-retrieve-ctf": """ Command not in use """ return_error("This command is missing, try something else.") elif command == "xdr-retrieve-file-details": file_details_results(client, args, False) # type:ignore[arg-type] elif command == "xdr-get-scripts": return_outputs(*get_scripts_command(client, args)) # type:ignore[arg-type] elif command == "xdr-get-script-metadata": return_outputs(*get_script_metadata_command(client, args)) # type:ignore[arg-type] elif command == "xdr-get-script-code": return_outputs(*get_script_code_command(client, args)) # type:ignore[arg-type] elif command == "xdr-action-status-get": return_results(action_status_get_command(client, args)) # type:ignore[arg-type] elif command == "get-modified-remote-data": return_results(get_modified_remote_data_command(client, demisto.args())) elif command == "xdr-script-run": # used with polling = true always return_results(script_run_polling_command(args, client)) elif command == "xdr-run-script": return_results(run_script_command(client, args)) # type:ignore[arg-type] elif command == "xdr-run-snippet-code-script": return_results(run_snippet_code_script_command(client, args)) # type:ignore[arg-type] elif command == "xdr-snippet-code-script-execute": return_results( run_polling_command( client=client, # type:ignore[arg-type] args=args, cmd="xdr-snippet-code-script-execute", command_function=run_snippet_code_script_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-get-script-execution-status": return_results(get_script_execution_status_command(client, args)) # type:ignore[arg-type] elif command == "xdr-get-script-execution-results": return_results(get_script_execution_results_command(client, args)) # type:ignore[arg-type] elif command == "xdr-get-script-execution-result-files": return_results(get_script_execution_result_files_command(client, args)) # type:ignore[arg-type] elif command == "xdr-get-cloud-original-alerts": return_results(get_original_alerts_command(client, args)) # type:ignore[arg-type] elif command == "xdr-get-alerts-ctf": return_results(get_alerts_by_filter_command_ctf(client, args)) # type:ignore[arg-type] elif command == "xdr-run-script-execute-commands": return_results(run_script_execute_commands_command(client, args)) # type:ignore[arg-type] elif command == "xdr-script-commands-execute": return_results( run_polling_command( client=client, # type:ignore[arg-type] args=args, cmd="xdr-script-commands-execute", command_function=run_script_execute_commands_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-run-script-delete-file": return_results(run_script_delete_file_command(client, args)) # type:ignore[arg-type] elif command == "xdr-file-delete-script-execute": return_results( run_polling_command( client=client, # type:ignore[arg-type] args=args, cmd="xdr-file-delete-script-execute", command_function=run_script_delete_file_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-run-script-file-exists": return_results(run_script_file_exists_command(client, args)) # type:ignore[arg-type] elif command == "xdr-file-exist-script-execute": return_results( run_polling_command( client=client, # type:ignore[arg-type] args=args, cmd="xdr-file-exist-script-execute", command_function=run_script_file_exists_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "xdr-run-script-kill-process": return_results((client, args)) elif command == "xdr-kill-process-script-execute": return_results( run_polling_command( client=client, # type:ignore[arg-type] args=args, cmd="xdr-kill-process-script-execute", command_function=run_script_kill_process_command, command_decision_field="action_id", results_function=action_status_get_command, polling_field="status", polling_value=["PENDING", "IN_PROGRESS", "PENDING_ABORT"], ) ) elif command == "endpoint": return_results(endpoint_command(client, args)) elif command == "xdr-get-endpoints-by-status": return_results(get_endpoints_by_status_command(client, args)) # type:ignore[arg-type] elif command == "xdr-blocklist-files": return_results(blocklist_files_command(client, args)) elif command == "xdr-blacklist-files": args["prefix"] = "blacklist" return_results(blocklist_files_command(client, args)) elif command == "xdr-allowlist-files": return_results(allowlist_files_command(client, args)) elif command == "xdr-whitelist-files": args["prefix"] = "whitelist" return_results(allowlist_files_command(client, args)) elif command == "xdr-remove-blocklist-files": return_results(remove_blocklist_files_command(client, args)) # type:ignore[arg-type] elif command == "xdr-remove-allowlist-files": return_results(remove_allowlist_files_command(client, args)) elif command == "xdr-get-contributing-event": return_results(get_contributing_event_command(client, args)) # type:ignore[arg-type] elif command == "xdr-replace-featured-field": return_results(replace_featured_field_command(client, args)) # type:ignore[arg-type] elif command == "xdr-endpoint-tag-add": return_results(add_tag_to_endpoints_command(client, args)) # type:ignore[arg-type] elif command == "xdr-endpoint-tag-remove": return_results(remove_tag_from_endpoints_command(client, args)) # type:ignore[arg-type] elif command == "xdr-get-tenant-info": return_results(get_tenant_info_command(client)) # type:ignore[arg-type] except Exception as err: return_error(str(err)) if __name__ in ("__main__", "__builtin__", "builtins"): main()