FireEyeNX
FireEye Network Security is an effective cyber threat protection solution that helps organizations minimize the risk of costly breaches by accurately detecting and immediately stopping advanced, targeted, and other evasive attacks hiding in internet traffic.
Network Security · FireEye Network Security (NX)
Details
| ID | FireEyeNX |
|---|---|
| Provider | Trellix |
| Category | Network Security |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
FireEye Network Security is an effective cyber threat protection solution that helps organizations minimize the risk of costly breaches by accurately detecting and immediately stopping advanced, targeted, and other evasive attacks hiding in internet traffic.
This integration was integrated and tested with version 2.0.0 of FireEyeNX APIs.
Configure FireEyeNX in Cortex
| Parameter | Description | Required |
|---|---|---|
| url | URL | True |
| credentials | Username | True |
| request_timeout | HTTP(S) Request Timeout (in seconds) | False |
| isFetch | Fetch incidents | False |
| incidentType | Incident type | False |
| first_fetch | First fetch time interval | False |
| max_fetch | Fetch Limit | False |
| fetch_type | Fetch Types | False |
| fetch_mvx_correlated_events | Fetches MVX-correlated events only. | False |
| malware_type | Alert Malware Type | False |
| replace_alert_url | Use instance URL for all the fetched alerts URL. | False |
| fetch_artifacts | Fetch artifacts for each alert. | False |
| insecure | Trust any certificate (not secure) | False |
| proxy | Use system proxy settings | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
fireeye-nx-get-alerts
Search and retrieve FireEye alerts based on several filters.
Base Command
fireeye-nx-get-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | The ID number of the alert to retrieve. To retrieve the alert ID, execute the fireeye-nx-get-alerts command without specifying the alert_id. | Optional |
| src_ip | The source IPv4 address related to the malware alert to retrieve. | Optional |
| dst_ip | The destination IPv4 address related to the malware alert to retrieve. | Optional |
| duration | The time interval to search. This filter is used with either the start_time or end_time filter. If duration, start time, and end time are not specified, the system defaults to duration=12_hours, end_time=current_time. If only the duration is specified, the end_time defaults to the current_time. Possible values are: “1_hour”, “2_hours”, “6_hours”, “12_hours”, “24_hours”, and “48_hours”. | Optional |
| start_time | The start time of the search. This filter is used with the duration filter. If the start_time is specified but not the duration, the system defaults to duration=12_hours, starting at the specified start_time. Formats: YYYY-MM-dd YYYY-MM-ddTHH:mm:ss N days N hours Example: 2020-05-01 2020-05-01T00:00:00 2 days 5 hours |
Optional |
| end_time | The end time of the search. This filter is used with the duration filter. If the end_time is specified but not the duration, the system defaults to duration=12_hours, ending at the specified end_time. Formats: YYYY-MM-dd YYYY-MM-ddTHH:mm:ss N days N hours Example: 2020-05-01 2020-05-01T00:00:00 2 days 5 hours |
Optional |
| file_name | The name of the malware file to retrieve. | Optional |
| file_type | The malware file type to retrieve. | Optional |
| info_level | The level of information to retrieve. Possible values are: “concise”, “normal”, and “extended”. | Optional |
| malware_name | The name of the malware object to retrieve. | Optional |
| malware_type | The type of the malware object to retrieve. Possible values are: “domain_match”, “malware_callback”, “malware_object”, “web_infection”, and “infection_match”. | Optional |
| md5 | The MD5 hash of the alert to retrieve. This filter is not time dependent; it does not default to duration=12_hours. | Optional |
| url | A specific alert URL to retrieve. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Md5Sum | String | The md5sum of malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Sha256 | String | The SHA256 hash of malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Application | String | The application of the malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.HttpHeader | String | The HTTP header of the malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Original | String | The filename of the malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Name | String | The name of the malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Sid | String | The SID of the malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Type | String | The file type of the malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Stype | String | The STYPE of the malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Url | String | The URL of the malware associated with the alert. |
| FireEyeNX.Alert.Explanation.MalwareDetected.Malware.Content | String | The content of the malware associated with the alert. |
| FireEyeNX.Alert.Explanation.CncServices.CncService.Address | String | The CNC service IP address associated with the alert. |
| FireEyeNX.Alert.Explanation.CncServices.CncService.Channel | String | The CNC service channel associated with the alert. |
| FireEyeNX.Alert.Explanation.CncServices.CncService.Port | Number | The CNC service port address associated with the alert. |
| FireEyeNX.Alert.Explanation.CncServices.CncService.Protocol | String | The CNC service protocol associated with the alert. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Totalmemory | Number | The total memory of heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Lastbytesreceived | Number | The last byte received in heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Processinfo.Imagepath | String | The image path of the process in heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Processinfo.Md5sum | String | The md5sum of the process in heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Processinfo.Pid | Number | The PID of the process in heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.IncrementCount | Number | The increment count in heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Name | String | The name of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Bytesreceived | Number | The bytes received in heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Lasttotalmemory | Number | The last total memory in heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Type | String | The type of heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Timestamp | Number | The timestamp of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.RCount | Number | The RCount of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.TotalSize | String | The total size of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.RUnit | String | The RUnit of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Mode | String | The mode of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Pattern | String | The pattern of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.BytesList.Entry.Percentage | Number | The entry percentage of the bytes list in the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.BytesList.Entry.Byte | String | The entry byte of the bytes list in the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.BytesList.Entry.Count | Number | The entry count of the bytes list in the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.BytesList.Entry.FirstOffset | String | The entry offset of the bytes list in the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.BytesList.Entry.IsNOP | String | If entry NOP appears in the bytes list in the heap spraying then yes, otherwise no. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.BytesList.Distinct | Number | The distinct number of the byte list in the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.BytesList.Count | Number | The number of the byte list in the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Javascript | String | If heap spraying has javascript then yes, otherwise no. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.DNA | Number | The DNA of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.TotalRCount | Number | The total row count of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.ProcessedRCount | Number | The processed row count of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Heapspraying.Processed | String | The processed memory of the heap spraying. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Fid.Ads | String | The FID ads of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Fid.Content | Number | The FID content of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.ParentUserAccount.UserSid | String | The parent user account SID of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.ParentUserAccount.SessionId | Number | The parent user account session ID of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.ParentUserAccount.UserAccountName | String | The parent user account name of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.ParentUserAccount.AuthenticationId | String | The parent user account authentication ID of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.ParentUserAccount.SuperPrivilegesPresent | Number | If super privileges are present in this process then 1, otherwise 0. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Parentname | String | The path of the parent process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Sha256sum | String | The sha256sum of the parent process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Pid | Number | The PID of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Filesize | Number | File size of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Ppid | Number | The PPID of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Mode | String | The mode of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Cmdline | String | The path of the command associated with the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Sha1sum | String | The sha1sum of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Md5sum | String | The md5sum of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.SrcThread | String | The source thread name of the process. |
| FireEyeNX.Alert.Explanation.osChanges.Process.Value | String | The value of the path in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.UserAccount.UserSid | String | The SID of the user account for the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.UserAccount.SessionId | Number | The session ID of the user account for the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.UserAccount.UserAccountName | String | The name of the user account for the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.UserAccount.AuthenticationId | String | The authentication ID of the user account for the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.UserAccount.SuperPrivilegesPresent | Number | If super privileges are present in this user account then 1, otherwise 0. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.Timestamp | Number | The timestamp of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.MemoryData | String | The memory data of the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.TelemetryData.LocalThreadCount | Number | The local thread count of the telemetry data in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.TelemetryData.FileOpenCount | Number | The file open count of the telemetry data in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.TelemetryData.FileModifyCount | Number | The file modify count of the telemetry data in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.TelemetryData.FileCreateCount | Number | The file created count of the telemetry data in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.TelemetryData.ChildProcessCount | Number | The file process count of the telemetry data in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.TelemetryData.FileFailedCount | Number | The file failed count of the telemetry data in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.TelemetryData.HttpReqCount | Number | The HTTP request count of the telemetry data in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.TelemetryData.RemoteThreadCount | Number | The remote thread count of the telemetry data in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Process.TelemetryData.MutexCreateCount | Number | The mutex-created count of the telemetry data in the process. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Mode | String | The mode of the registry key. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Processinfo.Imagepath | String | The image path of the process in the registry key. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Processinfo.Md5sum | String | The md5sum of the process in the registry key. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Processinfo.Pid | Number | The PID of the process in the registry key. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Ntstatus | String | The NTSTATUS of the registry key. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Suppressed | Boolean | If the registry key was suppressed then true, otherwise false. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Value | String | The value of the registry key. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Timestamp | Number | The timestamp of the registry key. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.SrcThread | String | The source thread name of the registry key. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Randomized | Boolean | If the registry key was randomized then true, otherwise false. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.Buffered | Boolean | If the registry key was buffered then true, otherwise false. |
| FireEyeNX.Alert.Explanation.OsChanges.Regkey.NoExtend | Boolean | If the registry key has no_extend then true, otherwise false. |
| FireEyeNX.Alert.Explanation.OsChanges.Os.Name | String | The name of the operating system. |
| FireEyeNX.Alert.Explanation.OsChanges.Os.Arch | String | The architecture of the operating system. |
| FireEyeNX.Alert.Explanation.OsChanges.Os.Version | String | The version of the operating system. |
| FireEyeNX.Alert.Explanation.OsChanges.Os.Sp | Number | The service pack version of the operating system. |
| FireEyeNX.Alert.Explanation.OsChanges.OsMonitor.Date | String | The monitored date of the operating system. |
| FireEyeNX.Alert.Explanation.OsChanges.OsMonitor.Build | Number | The monitored build of the operating system. |
| FireEyeNX.Alert.Explanation.OsChanges.OsMonitor.Time | String | The monitored time of the operating system. |
| FireEyeNX.Alert.Explanation.OsChanges.OsMonitor.Version | String | The monitored version of the operating system. |
| FireEyeNX.Alert.Explanation.OsChanges.Analysis.Mode | String | The mode of the analysis. |
| FireEyeNX.Alert.Explanation.OsChanges.Analysis.Product | String | The product name of the analysis. |
| FireEyeNX.Alert.Explanation.OsChanges.Analysis.Ftype | String | The file type of the analysis. |
| FireEyeNX.Alert.Explanation.OsChanges.Analysis.Version | String | The version of the analysis. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.Mode | String | The mode of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.ProtocolType | String | The protocol type of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.Ipaddress | String | The IP address of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.DestinationPort | Number | The destination port address of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.Processinfo.Imagepath | String | The image path of the process in the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.Processinfo.Tainted | Boolean | If the process state is tainted then true, otherwise false for the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.Processinfo.Md5sum | String | The md5sum of the process in the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.Processinfo.Pid | Number | The PID of the process in the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.HttpRequest | String | The HTTP request of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.Timestamp | Number | The timestamp of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.Hostname | String | The hostname of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.Qtype | String | The QTYPE of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.AnswerNumber | Number | The answer number of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.Network.DnsResponseCode | Number | The DNS response code of the network. |
| FireEyeNX.Alert.Explanation.OsChanges.ActionFopen.Mode | String | The mode of opening the file. |
| FireEyeNX.Alert.Explanation.OsChanges.ActionFopen.Ext | String | The extension of opening the file. |
| FireEyeNX.Alert.Explanation.OsChanges.ActionFopen.Buffered | Boolean | If the opened file was buffered then true, otherwise false. |
| FireEyeNX.Alert.Explanation.OsChanges.ActionFopen.NoExtend | Boolean | If the opened file has no_extend then true, otherwise false. |
| FireEyeNX.Alert.Explanation.OsChanges.ActionFopen.Name | String | The name of the action for opening the file. |
| FireEyeNX.Alert.Explanation.OsChanges.ActionFopen.Timestamp | Number | The timestamp of opening the file. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Dllname | String | The DLL file name of the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Apiname | String | The API name of the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Address | String | The address of the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Processinfo.Imagepath | String | The image path of the process in the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Processinfo.Md5sum | String | The md5sum of the process in the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Processinfo.Pid | Number | The PID of the process in the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.SrcThread | String | The source thread name of the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Protection | String | The protection number of the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Callstack.CallstackEntry.SymbolName | String | The symbol name of the call stack entry in the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Callstack.CallstackEntry.FrameNumber | Number | The frame number of the call stack entries in the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Callstack.CallstackEntry.ModuleName | String | The module name of the call stack entry in the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Callstack.CallstackEntry.InstructionAddress | String | The instruction address of the call stack entry in the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Callstack.CallstackEntry.SymbolDisplacement | String | The symbol displacement of the call stack entry in the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Params.Param.Id | Number | The ID parameter of the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Params.Param.Content | String | The path parameter of the exploit code. |
| FireEyeNX.Alert.Explanation.OsChanges.Exploitcode.Timestamp | Number | The timestamp of the exploit codes. |
| FireEyeNX.Alert.Explanation.OsChanges.Folder.Mode | String | The mode of the folder. |
| FireEyeNX.Alert.Explanation.OsChanges.Folder.Processinfo.Imagepath | String | The image path of the process in the folder. |
| FireEyeNX.Alert.Explanation.OsChanges.Folder.Processinfo.Md5sum | String | The md5sum of the process in the folder. |
| FireEyeNX.Alert.Explanation.OsChanges.Folder.Processinfo.Pid | Number | The PID of the process in the folder. |
| FireEyeNX.Alert.Explanation.OsChanges.Folder.SrcThread | String | The source thread name of the folder. |
| FireEyeNX.Alert.Explanation.OsChanges.Folder.Value | String | The path of the folder. |
| FireEyeNX.Alert.Explanation.OsChanges.Folder.Timestamp | Number | The timestamp of the folder. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Mode | String | The mode of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Fid.Ads | String | The Alternate Data Stream (ADS) of the FID for the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Fid.Content | Number | The content of the FID in the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Processinfo.Imagepath | String | The image path of the process for the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Processinfo.Md5sum | String | The md5sum of the process for the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Processinfo.Pid | Number | The PID of the process for the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Processinfo.Tainted | Boolean | If the process state is tainted then true, otherwise false for the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.SrcThread | String | The source thread name of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Ntstatus | String | The NTSTATUS of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Filesize | Number | The size of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Value | String | The value of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.CreateOptions | String | The created option of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Timestamp | Number | The timestamp of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Type | String | The type of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Sha256sum | String | The sha256sum of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Sha1sum | String | The sha1sum of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.InspectionType | String | The inspection type of the portable executable file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.TimeDateStamp | String | The time date stamp of the portable executable file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.Characteristics.Names.Name | Unknown | The list of characteristic names in the portable executable file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.Characteristics.Value | String | The characteristic value in the portable executable file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.DllCharacteristics.Names | String | The characteristic name in the DLL portable executable file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.DllCharacteristics.Value | String | The characteristic value in the DLL portable executable file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.Dll | String | If the portable file is a DLL file then yes, otherwise no file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.Magic | String | The magic hex value of the portable executable file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.Subsystem | String | The subsystem of the portable executable file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.PE.Machine | String | The hexadecimal address of the machine in the file. |
| FireEyeNX.Alert.Explanation.OsChanges.File.Md5sum | String | The md5sum of the file. |
| FireEyeNX.Alert.Explanation.OsChanges.Application.AppName | String | The app name of the application. |
| FireEyeNX.Alert.Explanation.OsChanges.QuerySystemTime.Processinfo.Imagepath | String | The image path of the queried system process. |
| FireEyeNX.Alert.Explanation.OsChanges.QuerySystemTime.Processinfo.Md5sum | String | The system time process info of the md5sum that is queried. |
| FireEyeNX.Alert.Explanation.OsChanges.QuerySystemTime.Processinfo.Pid | Number | The system time process info of the PID (process ID) that is queried |
| FireEyeNX.Alert.Explanation.OsChanges.QuerySystemTime.Ntstatus | String | The NTSTATUS of the system time that is queried. |
| FireEyeNX.Alert.Explanation.OsChanges.QuerySystemTime.Timestamp | Number | The timestamp of the system that is queried. |
| FireEyeNX.Alert.Explanation.OsChanges.QuerySystemTime.SystemTime.Value | String | The time value of the system that is queried. |
| FireEyeNX.Alert.Explanation.OsChanges.QuerySystemTime.SystemTime.Time | String | The time of the system that is queried. |
| FireEyeNX.Alert.Explanation.OsChanges.EndOfReport | String | The end of the report. |
| FireEyeNX.Alert.Explanation.OsChanges.MaliciousAlert.Classtype | String | The class type of the malicious alert. |
| FireEyeNX.Alert.Explanation.OsChanges.MaliciousAlert.DisplayMsg | String | The display message of the malicious alert. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDetected.Hwnd | String | The hexadecimal address of the dialog detected. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDetected.Processinfo.Imagepath | String | The image path of the process for the dialog detected. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDetected.Processinfo.Pid | Number | The PID of the process for the dialog detected. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDetected.Buffered | Boolean | A flag indicating whether the dialog detected is buffered. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDetected.NoExtend | Boolean | A flag indicating whether NoExtend is true in the dialog detected. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDetected.Timestamp | Number | The timestamp of the dialog detected. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDetected.DlgId | String | The dialog ID of the dialog detected. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDismissed.Note | String | A note in the dismissed dialog. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDismissed.Hwnd | String | The hexadecimal address of the dismissed dialog. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDismissed.Processinfo.Imagepath | String | The image path of the process for the dismissed dialog. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDismissed.Processinfo.Pid | Number | The PID of the process for the dismissed dialog. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDismissed.Buffered | Boolean | A flag indicating whether the dismissed dialog is buffered. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDismissed.NoExtend | Boolean | A flag indicating whether NoExtend is true in the dismissed dialog. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDismissed.Timestamp | Number | The timestamp of the dismissed dialog. |
| FireEyeNX.Alert.Explanation.OsChanges.DialogDismissed.DlgId | String | The dialog ID of the dismissed dialog. |
| FireEyeNX.Alert.Explanation.OsChanges.Wmiquery.Processinfo.Imagepath | String | The image path of the process for the Windows Management Instrumentation (WMI) query. |
| FireEyeNX.Alert.Explanation.OsChanges.Wmiquery.Processinfo.Md5sum | String | The md5sum of the process for the WMI query. |
| FireEyeNX.Alert.Explanation.OsChanges.Wmiquery.Processinfo.Pid | Number | The PID of the process for the WMI query. |
| FireEyeNX.Alert.Explanation.OsChanges.Wmiquery.Wmicontents.Wmiconent.Query | String | The query for the WMI content for WMI query. |
| FireEyeNX.Alert.Explanation.OsChanges.Wmiquery.Wmicontents.Wmicontent.Lang | String | Language of the WMI content for the WMI query. |
| FireEyeNX.Alert.Explanation.OsChanges.Wmiquery.Timestamp | Number | The timestamp of the WMI query. |
| FireEyeNX.Alert.Explanation.OsChanges.Wmiquery.Buffered | Boolean | A flag indicating whether the WMI query is buffered. |
| FireEyeNX.Alert.Explanation.OsChanges.Wmiquery.NoExtend | Boolean | A flag indicating whether NoExtend is true in the WMI query. |
| FireEyeNX.Alert.Explanation.OsChanges.Uac.Mode | String | The mode of the User Account Control (UAC). |
| FireEyeNX.Alert.Explanation.OsChanges.Uac.Value | String | The value of the User Account Control. |
| FireEyeNX.Alert.Explanation.OsChanges.Uac.Timestamp | Number | The timestamp of the User Account Control. |
| FireEyeNX.Alert.Explanation.OsChanges.Uac.Status | String | The status of the User Account Control. |
| FireEyeNX.Alert.Explanation.StaticAnalysis.Static.Value | String | The value of the static analysis. |
| FireEyeNX.Alert.Explanation.StolenData.Info.Field | Unknown | The information field of the stolen data. |
| FireEyeNX.Alert.Explanation.StolenData.Info.Type | String | The information type of the stolen data. |
| FireEyeNX.Alert.Explanation.StolenData.EventId | Number | The event ID of the stolen data. |
| FireEyeNX.Alert.Src.Ip | String | The source IP address of the alert. |
| FireEyeNX.Alert.Src.Mac | String | The source MAC address of the alert. |
| FireEyeNX.Alert.Src.Port | Number | The source port address of the alert. |
| FireEyeNX.Alert.Src.Host | String | The source host of the alert. |
| FireEyeNX.Alert.AlertUrl | String | The alert URL. |
| FireEyeNX.Alert.Action | String | The action of the alert. |
| FireEyeNX.Alert.Occurred | String | The time when the alert occurred. |
| FireEyeNX.Alert.AttackTime | String | The time when an attack occurred. |
| FireEyeNX.Alert.Dst.Mac | String | The destination MAC address of the alert. |
| FireEyeNX.Alert.Dst.Port | Number | The destination port address of the alert. |
| FireEyeNX.Alert.Dst.Ip | String | The destination IP address of the alert. |
| FireEyeNX.Alert.ApplianceId | String | The appliance ID of the alert. |
| FireEyeNX.Alert.Id | Number | The ID of the alert. |
| FireEyeNX.Alert.Name | String | The type of the alert. |
| FireEyeNX.Alert.Severity | String | The severity of the alert. |
| FireEyeNX.Alert.Uuid | String | The universally unique identifier (UUID) of the alert. |
| FireEyeNX.Alert.Ack | String | A flag indicating whether an acknowledgment is received. |
| FireEyeNX.Alert.Product | String | The product name of the alert. |
| FireEyeNX.Alert.Vlan | Number | The virtual LAN (VLAN) of the alert. |
| FireEyeNX.Alert.Malicious | String | A flag indicating whether the alert is malicious. |
| FireEyeNX.Alert.ScVersion | String | The SC version of the alert. |
Command Example
#### Context Example
{
“FireEyeNX”: {
“Alert”: [
{
“Ack”: “no”,
“Action”: “notified”,
“AlertUrl”: “https://fireeye-941918/event_stream/events_for_bot?ev_id=11364”,
“ApplianceId”: “866ED7558A08”,
“AttackTime”: “2020-09-29 18:30:01 +0000”,
“Dst”: {
“Mac”: “xx:xx:xx:xx:xx:xx”,
“Ip”: “1.1.1.1”,
“Port”: 0
},
“Explanation”: {
“MalwareDetected”: {
“Malware”: [
{
“Name”: “dummy malware name 1”
}
]
}
},
“Id”: 1,
“Malicious”: “yes”,
“Name”: “dummy name 1”,
“Occurred”: “0000-00-00 02:12:53 +0000”,
“Product”: “WEB_MPS”,
“ScVersion”: “1.000”,
“Severity”: “MINR”,
“Src”: {
“Ip”: “1.1.1.1”,
“Port”: 0,
“Mac”: “xx:xx:xx:xx:xx:xx”
},
“Uuid”: “0b0b0b0b0-0b0b0b-0b0b-0b0b-0b0b0b0b0b”,
“Vlan”: 0
},
{
“Ack”: “no”,
“Action”: “notified”,
“AlertUrl”: “https://fireeye-941918/event_stream/events_for_bot?ev_id=11365”,
“ApplianceId”: “866ED7558A08”,
“AttackTime”: “2020-09-29 19:00:01 +0000”,
“Dst”: {
“Mac”: “xx:xx:xx:xx:xx:xx”,
“Ip”: “1.1.1.1”,
“Port”: 0
},
“Explanation”: {
“MalwareDetected”: {
“Malware”: [
{
“Name”: “dummy malware name 2”
}
]
}
},
“Id”: 2,
“Malicious”: “yes”,
“Name”: “dummy name 2”,
“Occurred”: “0000-00-00 02:12:53 +0000”,
“Product”: “WEB_MPS”,
“ScVersion”: “1.000”,
“Severity”: “MINR”,
“Src”: {
“Ip”: “1.1.1.1”,
“Port”: 0,
“Mac”: “xx:xx:xx:xx:xx:xx”
},
“Uuid”: “0a0a0a0a0-0a0a0a-0a0a-0a0a-0a0a0a0a0a”,
“Vlan”: 0
}
]
}
}
#### Human Readable Output
>### Alert(s) Information
>
>|ID|Distinguisher(UUID)|Malware Name|Alert Type|Victim IP|Time (UTC)|Severity|Malicious|SC Version|Victim Port|Victim MAC Address|Target IP|Target Port|Target MAC Address|
>|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
>| 1 | 0b0b0b0b0-0b0b0b-0b0b-0b0b-0b0b0b0b0b | dummy malware name 1 | dummy name 1 | 1.1.1.1 | 0000-00-00 02:12:53 +0000 | MINR | yes | 1.000 | 0 | xx:xx:xx:xx:xx:xx | 1.1.1.1 | 0 | xx:xx:xx:xx:xx:xx |
>| 2 | 0a0a0a0a0-0a0a0a-0a0a-0a0a-0a0a0a0a0a | dummy malware name 2 | dummy name 2 | 1.1.1.1 | 0000-00-00 02:12:53 +0000 | MINR | yes | 1.000 | 0 | xx:xx:xx:xx:xx:xx | 1.1.1.1 | 0 | xx:xx:xx:xx:xx:xx |
### fireeye-nx-get-artifacts-metadata-by-alert
***
Gets malware artifacts metadata for the specified UUID.
#### Base Command
`fireeye-nx-get-artifacts-metadata-by-alert`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| uuid | Universally unique ID (UUID) of the alert. To retrieve the UUID, execute the fireeye-nx-get-alerts command. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| FireEyeNX.Alert.Uuid | String | Universally unique ID \(UUID\) of the alert. |
| FireEyeNX.Alert.ArtifactsMetadata.ArtifactType | String | The artifact type. |
| FireEyeNX.Alert.ArtifactsMetadata.ArtifactName | String | The artifact name. |
| FireEyeNX.Alert.ArtifactsMetadata.ArtifactSize | String | The artifact size. |
#### Command Example
```!fireeye-nx-get-artifacts-metadata-by-alert uuid=0b0b0b0b-0b0b-0b0b-0b0b-0b0b0b0b0b0b```
#### Context Example
{
“FireEyeNX”: {
“Alert”: {
“ArtifactsMetadata”: [
{
“ArtifactType”: “artifact type test 1”,
“ArtifactName”: “artifact name test 1”,
“ArtifactSize”: “1010”
},
{
“ArtifactType”: “artifact type test 2”,
“ArtifactName”: “artifact name test 2”,
“ArtifactSize”: “1010”
}
],
“Uuid”: “0b0b0b0b-0b0b-0b0b-0b0b-0b0b0b0b0b0b”
}
}
}
#### Human Readable Output
>### Artifacts Metadata
>
>|Artifact Type|Artifact Name|Artifact Size (Bytes)|
>|---|---|---|
>| artifact type test 1 | artifact name test 1 | 1010 |
>| artifact type test 2 | artifact name test 2 | 1010 |
### fireeye-nx-get-artifacts-by-alert
***
Downloads malware artifacts data for the specified UUID as a zip file.
#### Base Command
`fireeye-nx-get-artifacts-by-alert`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| uuid | The universally unique ID (UUID) of the alert. To get the UUID, execute the fireeye-nx-get-alerts command. | Required |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| File.Size | Number | The size of the file. |
| File.SHA1 | String | The SHA1 hash of the file. |
| File.SHA256 | String | The SHA256 hash of the file. |
| File.Name | String | The name of the file. |
| File.SSDeep | String | The SSDeep hash of the file. |
| File.EntryID | String | The entry ID of the file. |
| File.Info | String | The file information. |
| File.Type | String | The file type. |
| File.MD5 | String | The MD5 hash of the file. |
| File.Extension | String | The file extension. |
#### Command Example
```!fireeye-nx-get-artifacts-by-alert uuid=0b0b0b0b-0b0b-0b0b-0b0b-0b0b0b0b0b0b```
#### Context Example
{
“File”: {
“Size”: 17277,
“SHA1”: “574352bb238d3379429063d71990c0000000000”,
“SHA256”: “1f8ac8eaba9abaf9d12b9b82180a110eab15b14aeec14715f48b4dedaaaaaaaaa”,
“Name”: “0b0b0b0b-0b0b-0b0b-0b0b-0b0b0b0b0b0b.zip”,
“SSDeep”: “000:aaaaaa/aAaAaAaA+AaAaAaAaA:aa0/aAaAaAaAaAaAaA”,
“EntryID”: “150@1”,
“Info”: “zip”,
“Type”: “Zip archive data, at least v1.0 to extract”,
“MD5”: “1aA1aA1aA1aA1aA1aA1aA1aA”,
“Extension”: “zip”
}
}
### fireeye-nx-get-reports
***
Returns reports on selected alerts by specifying a time_frame value or a start_time and end_time of the search range.
#### Base Command
`fireeye-nx-get-reports`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| report_type | The type of report to be queried. | Required |
| type | The output format of the report. Possible values are: "csv" and "pdf", or both depending upon the report type. | Optional |
| start_time | The start time of the search. The search occurs between the start and end times. When specifying a start_time value, you must specify both a start_time and an end_ time value.<br/> Formats:<br/>YYYY-MM-dd<br/>YYYY-MM-ddTHH:mm:ss<br/>N days <br/>N hours<br/>Example:<br/> 2020-05-01 <br/> 2020-05-01T00:00:00 <br/> 2 days <br/> 5 hours. | Optional |
| end_time | The end time of the search. The search occurs between the start and end times. When specifying an end_time value, you must specify both a start_time and an end_time value.<br/> Formats:<br/>YYYY-MM-dd<br/>YYYY-MM-ddTHH:mm:ss<br/>N days <br/>N hours<br/>Example:<br/> 2020-05-01 <br/> 2020-05-01T00:00:00 <br/> 2 days <br/> 5 hours. | Optional |
| time_frame | The time frame in which reports are searched. | Optional |
| limit | The maximum number (N) of items covered by each IPS Top N report. This argument is required only for IPS Top N reports. Possible values are: "25", "50", "75", and "100". | Optional |
| interface | The internet interface. Possible values are: "A", "B", "C", "D", "AB", and "All". This option is required only for IPS reports. | Optional |
| infection_id | The alert ID. To retrieve the alert ID, execute the fireeye-nx-get-alerts command. Use the combination of infection_id and infection_type arguments to specify a unique alert to describe in the Alert Details Report. If one option is used alone and does not specify a unique alert, an error message is produced. | Optional |
| infection_type | The type of the infection. Use the combination of infection_id and infection_type arguments to specify a unique alert to describe in the Alert Details Report. If one option is used alone and does not specify a unique alert, an error message is produced. Possible values are: "malware-object", "malware-callback", "infection-match", "domain-match", and "web-infection". | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| InfoFile.Name | String | The file name. |
| InfoFile.EntryID | String | The ID for locating the file in the War Room. |
| InfoFile.Size | Number | The size of the file \(in bytes\). |
| InfoFile.Type | String | The file type, as determined by libmagic \(same as displayed in the file entries\). |
| InfoFile.Extension | String | The file extension. |
| InfoFile.Info | String | Basic information about the file. |
#### Command Example
```!fireeye-nx-get-reports report_type="IPS Executive Summary Report" type=csv time_frame=between start_time=2020-01-29T23:59:59 end_time=2020-08-29T23:59:59```
#### Context Example
{
“InfoFile”: {
“EntryID”: “1052@8db8b36d-df26-4a3a-8f8a-40e45629ff54”,
“Extension”: “csv”,
“Info”: “csv”,
“Name”: “ips_executive_summary_report_fireeye_20200709_151727878642.csv”,
“Size”: 606,
“Type”: “ASCII text”
}
}
### fireeye-nx-get-events
***
Search and retrieve FireEye events based on several filters.
#### Base Command
`fireeye-nx-get-events`
#### Input
| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| duration | The time interval to search. This filter is used with the end_time filter. If the duration is not specified, the system defaults to duration=12_hours, end_time=current_time. | Optional |
| start_time | The start time of the search. This filter is used with the duration filter. If the start_time is specified but not the duration, the system defaults to duration=12_hours, starting at the specified start_time.<br/>Formats:<br/>YYYY-MM-dd<br/>YYYY-MM-ddTHH:mm:ss<br/>N days <br/>N hours<br/>Example:<br/> 2020-05-01 <br/> 2020-05-01T00:00:00 <br/> 2 days <br/> 5 hours | Optional |
| end_time | The end time of the search. This filter is used with the duration filter. If the end_time is specified but not the duration, the system defaults to duration=12_hours, ending at the specified end_time. <br/>Formats:<br/>YYYY-MM-dd<br/>YYYY-MM-ddTHH:mm:ss<br/>N days <br/>N hours<br/>Example:<br/> 2020-05-01 <br/> 2020-05-01T00:00:00 <br/> 2 days <br/> 5 hours | Optional |
| mvx_correlated_only | Whether to include all IPS events or MVX-correlated events only. Default: false | Optional |
#### Context Output
| **Path** | **Type** | **Description** |
| --- | --- | --- |
| FireEyeNX.Event.EventId | Number | The ID of the event. |
| FireEyeNX.Event.Occurred | String | The date and time when the event occurred. |
| FireEyeNX.Event.SrcIp | String | The IP address of the victim. |
| FireEyeNX.Event.SrcPort | Number | The port number of the victim. |
| FireEyeNX.Event.DstIp | String | The IP address of the attacker. |
| FireEyeNX.Event.DstPort | Number | The port number of the attacker. |
| FireEyeNX.Event.Severity | Number | The severity level of the event. |
| FireEyeNX.Event.SignatureRev | Number | The signature revision number of the event. |
| FireEyeNX.Event.SignatureIden | Number | The signature identity number of the event. |
| FireEyeNX.Event.SignatureMatchCnt | Number | The signature match count number of the event. |
| FireEyeNX.Event.Vlan | Number | The virtual LAN \(VLAN\) of the event. |
| FireEyeNX.Event.VmVerified | Boolean | Whether the event VM was verified. |
| FireEyeNX.Event.SrcMac | String | The MAC address of the source machine. |
| FireEyeNX.Event.DstMac | String | The MAC address of the destination machine. |
| FireEyeNX.Event.RuleName | String | The rule name for the event. |
| FireEyeNX.Event.SensorId | String | The sensor ID of the FireEye machine. |
| FireEyeNX.Event.CveId | String | The CVE ID found in the event. |
| FireEyeNX.Event.ActionTaken | Number | The IPS blocking action taken on the event. |
| FireEyeNX.Event.AttackMode | String | The attack mode mentioned in the event. |
| FireEyeNX.Event.InterfaceId | Number | The interface ID of the event. |
| FireEyeNX.Event.Protocol | Number | The protocol used in the event. |
| FireEyeNX.Event.IncidentId | Number | The incident ID of the event on FireEye. |
#### Command Example
```!fireeye-nx-get-events duration=48_hours end_time=2020-08-10T06:31:00```
#### Context Example
{
“FireEyeNX”: {
“Event”: [
{
“EventId”:1,
“Occurred”:”2020-08-10T06:31:00Z”,
“SrcIp”:”1.1.1.1”,
“SrcPort”:1,
“DstIp”:”1.1.1.1”,
“DstPort”:1,
“Vlan”:0,
“SignatureMatchCnt”:1,
“SignatureIden”:1,
“SignatureRev”:1,
“Severity”:1,
“VmVerified”:true,
“SrcMac”:”dummy”,
“DstMac”:”dummy”,
“RuleName”:”dummy”,
“SensorId”:”dummy”,
“CveId”:”CVE-123”,
“ActionTaken”:1,
“AttackMode”:”dummy”,
“InterfaceId”:1,
“Protocol”:1,
“IncidentId”:1
}
]
}
}
```
Human Readable Output
IPS Events
Event ID Time (UTC) Victim IP Attacker IP CVE ID Severity Rule Protocol 1 2020-08-10T06:31:00Z 1.1.1.1 1.1.1.1 CVE-123 1 dummy 1
Configuration parameters
url— URL (required)credentials— Username (required)request_timeout— HTTP(S) Request Timeout (in seconds)isFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalfirst_fetch— First fetch time intervalmax_fetch— Fetch Limitfetch_type— Fetch Typesfetch_mvx_correlated_events— Fetches MVX-correlated events onlymalware_type— Alert Malware Typereplace_alert_url— Use instance URL for all the fetched alerts URL.fetch_artifacts— Fetch artifacts for each alertinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (5)
-
fireeye-nx-get-alertsSearch and retrieve FireEye alerts based on several filters.
-
fireeye-nx-get-artifacts-by-alertDownloads malware artifacts data for the specified UUID as a zip file.
-
fireeye-nx-get-artifacts-metadata-by-alertGets malware artifacts metadata for the specified UUID.
-
fireeye-nx-get-eventsSearch and retrieve FireEye events based on several filters.
-
fireeye-nx-get-reportsReturns reports on selected alerts by specifying a time_frame value or a start_time and end_time of the search range.
from CommonServerPython import * """ IMPORTS """ from typing import Any import dateparser import urllib3 from requests import Response from requests.exceptions import ( InvalidSchema, InvalidURL, MissingSchema, SSLError, ) # Disable insecure warnings urllib3.disable_warnings() """ CONSTANTS """ DEFAULT_REQUEST_TIMEOUT = 120 REQUEST_TIMEOUT_MAX_VALUE = 9223372036 API_VERSION = "v2.0.0" DEFAULT_SESSION_TIMEOUT = 15 * 60 # In Seconds DEFAULT_FETCH_LIMIT = "50" FORTY_EIGHT_HOURS_IN_SECOND = 172000.0 # Due to API limitations we can retrieve events only from the last 48 hours. CONTENT_TYPE_JSON = "application/json" CONTENT_TYPE_ZIP = "application/zip" DATE_FORMAT_OF_YEAR_MONTH_DAY = "%Y-%m-%d" DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ" DATE_FORMAT_WITH_MICROSECOND = "%Y-%m-%dT%H:%M:%S.%fZ" API_SUPPORT_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.000-00:00" ALERT_DETAILS_REPORT = "Alert Details Report" VICTIM_IP = "Victim IP" TIME_UTC = "Time (UTC)" DEFAULT_FIRST_FETCH = "12 hours" ALERT_INCIDENT_TYPE = "FireEye NX Alert" IPS_EVENT_INCIDENT_TYPE = "FireEye NX IPS Event" MESSAGES: dict[str, str] = { "BAD_REQUEST_ERROR": "An error occurred while fetching the data.", "AUTHENTICATION_ERROR": "Unauthenticated. Check the configured Username and Password.", "PROXY_ERROR": "Proxy Error - cannot connect to proxy. Either try clearing the 'Use system proxy' check-box or " "check the host, authentication details and connection details for the proxy.", "BLANK_PROXY_ERROR": "https proxy value is empty. Check XSOAR server configuration ", "SSL_CERT_ERROR": "SSL Certificate Verification Failed - try selecting 'Trust any certificate' checkbox in the " "integration configuration.", "INTERNAL_SERVER_ERROR": "The server encountered an internal error for FireEye NX and was unable to complete " "your request.", "MISSING_SCHEMA_ERROR": "Invalid API URL. No schema supplied: http(s).", "INVALID_SCHEMA_ERROR": "Invalid API URL. Supplied schema is invalid, supports http(s).", "INVALID_API_URL": "Invalid API URL.", "CONNECTION_ERROR": "Connectivity failed. Check your internet connection or the API URL.", "INVALID_ALERT_DETAILS": 'For fetching Alert Details Report, "infection_id" and "infection_type" arguments are required.', "INVALID_REPORT_TYPE": "The given value for report_type is invalid.", "INVALID_REPORT_OUTPUT_TYPE": "The given value for the argument type (report's format) is invalid. Valid value(s): {}.", "NO_RECORDS_FOUND": "No {} were found for the given argument(s).", "INVALID_INT_VALUE": "The given value for {} is invalid. Expected integer value.", "FETCH_LIMIT_VALIDATION": "Value of Fetch Limit should be an integer and between range 1 to 200.", "INVALID_BOOLEAN_VALUE_ERROR": "The given value for {0} argument is invalid. Valid values: true, false.", "REQUEST_TIMEOUT_VALIDATION": "HTTP(S) Request timeout parameter must be a positive integer.", "REQUEST_TIMEOUT_EXCEED_ERROR": "Value is too large for HTTP(S) Request Timeout.", "REQUEST_TIMEOUT": "Request timed out. Check the configured HTTP(S) Request Timeout (in seconds) value.", "FIRST_FETCH_ARG_VALIDATION": "The First fetch time interval should be up to 48 hour as per API limitation.", "INVALID_TIME_VALIDATION": "The given value for {0} argument is invalid.", "INVALID_FETCH_TYPE": "The given value for Fetch Types is invalid. Expected Alerts or/and IPS Events ", } URL_SUFFIX: dict[str, str] = { "GET_TOKEN": "/auth/login", "GET_ARTIFACTS_METADATA": "/artifacts/{}/meta", "GET_ARTIFACTS": "/artifacts/{}", "GET_REPORTS": "/reports/report", "GET_ALERTS": "/alerts", "GET_EVENTS": "/events", } REPORT_TYPE_LABEL_NAME = { "Website Callback Server Report": "mpsCallBackServer", "Website Executive Summary": "mpsExecutiveSummary", "Website Infected Host Trends": "mpsInfectedHostsTrend", "Website Malware Activity": "mpsMalwareActivity", "Website Antivirus Report": "mpsWebAVReport", "IPS Executive Summary Report": "ipsExecutiveSummary", "IPS Top N Attacks Report": "ipsTopNAttack", "IPS Top N Attackers Report": "ipsTopNAttacker", "IPS Top N Victims Report": "ipsTopNVictim", "IPS Top N MVX-Correlated Report": "ipsTopNMvxVerified", ALERT_DETAILS_REPORT: "alertDetailsReport", } REPORT_TYPE_ALLOWED_FORMAT = { "Website Callback Server Report": ["csv"], "Website Executive Summary": ["pdf"], "Website Infected Host Trends": ["csv"], "Website Malware Activity": ["pdf", "csv"], "Website Antivirus Report": ["csv"], "IPS Executive Summary Report": ["pdf", "csv"], "IPS Top N Attacks Report": ["pdf", "csv"], "IPS Top N Attackers Report": ["pdf", "csv"], "IPS Top N Victims Report": ["pdf", "csv"], "IPS Top N MVX-Correlated Report": ["pdf", "csv"], ALERT_DETAILS_REPORT: ["pdf"], } PLATFORM_SEVERITY_TO_SEVERITY_MAP = { "10": 4, "9": 4, "8": 3, "7": 3, "6": 2, "5": 2, "4": 2, "3": 1, "2": 1, "1": 1, "0": 0, } def strip_blank(args: dict) -> dict: nargs = {} for key, value in args.items(): if isinstance(value, str): value = value.strip() nargs[key] = value return nargs class Client(BaseClient): """ Client to use in integration with powerful http_request. It extends the base client and uses the http_request method for the API request. Handle some exceptions externally. """ def __init__( self, base_url: str, verify: bool, proxy: bool, auth: tuple[str, str], request_timeout: int, ): super().__init__(base_url=base_url, verify=verify, proxy=proxy, auth=auth) self.request_timeout = request_timeout def http_request( self, method: str, url_suffix: str, json_data=None, params=None, headers=None, ok_codes=None, ): """ Override http_request method from BaseClient class. This method will print an error based on status code and exceptions. :type method: ``str`` :param method: The HTTP method, for example: GET, POST, and so on. :type url_suffix: ``str`` :param url_suffix: The API endpoint. :type json_data: ``dict`` :param json_data: The dictionary to send in a 'POST' request. :type params: ``dict`` :param params: URL parameters to specify the query. :type headers: ``dict`` :param headers: Headers to send in the request. If None, will use self._headers. :type ok_codes: ``tuple`` :param ok_codes: The tuple of acceptable status codes. Default is None. :return: Depends on the resp_type parameter :rtype: ``dict`` or ``str`` or ``requests.Response`` """ resp = Response() try: resp = super()._http_request( method=method, url_suffix=url_suffix, json_data=json_data, params=params, headers=headers, resp_type="response", timeout=self.request_timeout, ok_codes=ok_codes or (200, 201), error_handler=self.handle_error_response, ) except MissingSchema: raise ValueError(MESSAGES["MISSING_SCHEMA_ERROR"]) except InvalidSchema: raise ValueError(MESSAGES["INVALID_SCHEMA_ERROR"]) except InvalidURL: raise ValueError(MESSAGES["INVALID_API_URL"]) except DemistoException as e: self.handle_demisto_exception(e) if resp.ok: content_type = resp.headers.get("Content-Type", "") if content_type == CONTENT_TYPE_JSON: # Handle empty response if resp.text == "": return resp else: return resp.json() elif self.is_supported_context_type(content_type): return resp return None return None @staticmethod def is_supported_context_type(content_type: str): """ Check whether content type is supported or not. :param content_type: content type of header. :return: boolean flag, whether content type is supported or not. """ return ( content_type == "application/pdf" or content_type == "text/csv" or content_type == CONTENT_TYPE_ZIP or content_type == "application/octet-stream" ) @staticmethod def handle_demisto_exception(e): """ Handle Demisto exception based on string. :param e: Demisto Exception :return: Error message """ if "Proxy Error" in str(e): raise ConnectionError(MESSAGES["PROXY_ERROR"]) elif "ReadTimeoutError" in str(e): raise ConnectionError(MESSAGES["REQUEST_TIMEOUT"]) elif "ConnectionError" in str(e) or "ConnectTimeoutError" in str(e): raise ConnectionError(MESSAGES["CONNECTION_ERROR"]) elif "SSLError" in str(e): raise SSLError(MESSAGES["SSL_CERT_ERROR"]) else: raise e @staticmethod def handle_error_response(resp): """ Handle error response and display user specific error message based on status code. :param resp: response from API. :return: raise DemistoException based on status code. """ error_message = "" error_message_with_reason = "" try: error_message = resp.json().get("fireeyeapis", {}).get("description", "").strip() error_message = error_message.replace("\n", "") if error_message: error_message_with_reason = f"Reason: {error_message}" except ValueError: # ignoring json parsing errors pass if resp.headers.get("Content-Type", "") == CONTENT_TYPE_ZIP: error_message = error_message_with_reason = resp.text status_code_messages = { 400: f"{MESSAGES['BAD_REQUEST_ERROR']} {error_message_with_reason}", 401: MESSAGES["AUTHENTICATION_ERROR"], 403: error_message, 404: error_message, 406: error_message, 407: MESSAGES["PROXY_ERROR"], 500: MESSAGES["INTERNAL_SERVER_ERROR"], 503: MESSAGES["INTERNAL_SERVER_ERROR"], } if resp.status_code in status_code_messages: demisto.debug(f"Response Code: {resp.status_code}, Reason: {status_code_messages[resp.status_code]}") raise DemistoException(status_code_messages[resp.status_code]) else: raise DemistoException(resp.raise_for_status()) def get_api_token(self): """ Retrieve new api token and set it to integration context. if api token is not not found or expired, making api call to retrieve api token and set it to integration context. :return: api-token """ integration_context = demisto.getIntegrationContext() api_token = integration_context.get("api_token") valid_until = integration_context.get("valid_until") # Return api token from integration context, if found and not expired if api_token and valid_until and time.time() < valid_until: demisto.debug("Retrieved api-token from integration cache.") return api_token headers = {"Accept": CONTENT_TYPE_JSON} demisto.debug("Calling authentication API for retrieve api-token") resp = self.http_request(method="POST", url_suffix=URL_SUFFIX["GET_TOKEN"], headers=headers) integration_context = self.set_integration_context(resp) return integration_context.get("api_token") @staticmethod def set_integration_context(resp): """ set api token and expiry time in integration configuration context. Will raise value error if api-token is not found. :param resp: resp from API. :return: integration context """ integration_context = demisto.getIntegrationContext() api_token = resp.headers.get("X-FeApi-Token") if api_token: integration_context["api_token"] = api_token integration_context["valid_until"] = time.time() + DEFAULT_SESSION_TIMEOUT else: raise ValueError("No api token found. Please try again") demisto.setIntegrationContext(integration_context) return integration_context """ HELPER FUNCTION""" def set_attachment_file(client, incident: dict, uuid: str, headers: dict): """ Set attachment in incident entry. :param client: Client object. :param incident: Incident entry. :param uuid: uuid of alert. :param headers: Header of API which will pass to get artifact API. """ # Call get artifacts data api headers["Accept"] = CONTENT_TYPE_ZIP artifacts_resp = client.http_request( "GET", url_suffix=URL_SUFFIX["GET_ARTIFACTS"].format(uuid), headers=headers, ok_codes=(200, 201, 404), ) if artifacts_resp and int(artifacts_resp.headers.get("Content-Length", "0")) > 0: # Create file from Content file_name = f"{uuid}.zip" attachment_file = fileResult(filename=file_name, data=artifacts_resp.content) incident["attachment"] = [{"path": attachment_file["FileID"], "name": file_name}] def get_incidents_for_alert(**kwargs) -> tuple[list[dict[str, Any]], dict[str, Any]]: """ Return List of incidents for alert. :param kwargs: Contains all required arguments. :return: Incident List for alert. """ incidents: list[dict[str, Any]] = [] last_run = kwargs["last_run"] next_run = last_run.get("alerts", {}) headers = { "X-FeApi-Token": kwargs["client"].get_api_token(), "Accept": CONTENT_TYPE_JSON, } params = { "start_time": time.strftime(API_SUPPORT_DATE_FORMAT, time.localtime(kwargs["start_time"])), "duration": "48_hours", } if kwargs["malware_type"]: params["malware_type"] = kwargs["malware_type"] # http call resp = kwargs["client"].http_request( method="GET", url_suffix=URL_SUFFIX["GET_ALERTS"], params=params, headers=headers, ) total_records = resp.get("alertsCount", 0) if total_records > 0: if kwargs["replace_alert_url"]: replace_alert_url_key_domain_to_instance_url(resp.get("alert", []), kwargs["instance_url"]) count = kwargs["fetch_count"] next_incidents_ids: List[str] = [] alerts = resp.get("alert", []) alerts.sort(key=lambda x: x.get("occurred")) last_alert_start_time = last_run.get("alerts", {}).get("start_time") last_alert_ids = last_run.get("alerts", {}).get("alert_ids", []) next_alert_start_time = alerts[: kwargs["fetch_limit"]][-1].get("occurred", "") for alert in alerts: # skip on duplicate incident if ( last_alert_start_time and last_alert_ids and last_alert_start_time == alert.get("occurred", "") and alert.get("id", "") in last_alert_ids ): continue # set incident context_alert = remove_empty_entities(alert) context_alert["incidentType"] = ALERT_INCIDENT_TYPE if count >= kwargs["fetch_limit"]: break occurred_date = dateparser.parse(context_alert.get("occurred", "")) assert occurred_date is not None if ((alert_occurred_time := alert.get("occurred")) and next_alert_start_time == alert_occurred_time) and ( alert_id := alert.get("id") ): # Save the alert id for the next fetch dedup next_incidents_ids.append(alert_id) incident = { "name": context_alert.get("name", ""), "occurred": occurred_date.strftime(DATE_FORMAT_WITH_MICROSECOND), "rawJSON": json.dumps(context_alert), "dbotMirrorId": str(alert.get("id")), } if not kwargs["is_test"] and alert.get("uuid", "") and kwargs["fetch_artifacts"]: set_attachment_file( client=kwargs["client"], incident=incident, uuid=alert.get("uuid", ""), headers=headers, ) remove_nulls_from_dictionary(incident) incidents.append(incident) count += 1 parsed_incidents_str = [ f"Incident name: {incident.get('name')} Incident date: {incident.get('occurred')}\n" for incident in incidents ] demisto.debug(f"FireeyeNX Alerts: {parsed_incidents_str}") if next_incidents_ids: next_run = {"start_time": next_alert_start_time, "alert_ids": next_incidents_ids} return incidents, next_run def get_incidents_for_event(client: Client, start_time: float, fetch_limit: int, mvx_correlated: bool, last_run: dict): """ Return List of incidents for event. :param client: Client object. :param start_time: It contains the timestamp in milliseconds on when to start fetching incidents. :param fetch_limit: limit for number of fetch incidents per fetch. :param mvx_correlated: The boolean flag that tell us to fetch events which only mvx correlated. :param last_run: The last run object. :return: Incident List for event. """ incidents: list[dict[str, Any]] = [] next_run = last_run.get("events", {}) # Preparing header and parameters headers = { "X-FeApi-Token": client.get_api_token(), "Accept": CONTENT_TYPE_JSON, } params = { "start_time": time.strftime(API_SUPPORT_DATE_FORMAT, time.localtime(start_time)), "duration": "48_hours", "event_type": "Ips Event", } if mvx_correlated: params["mvx_correlated_only"] = "true" # http call resp = client.http_request( method="GET", url_suffix=URL_SUFFIX["GET_EVENTS"], params=params, headers=headers, ) total_records = len(resp.get("events", [])) count = 0 if total_records > 0: next_incidents_ids = [] events = resp.get("events", []) events.sort(key=lambda x: x.get("occurred")) last_event_start_time = last_run.get("events", {}).get("start_time") last_event_ids = last_run.get("events", {}).get("event_ids", []) next_event_start_time = events[:fetch_limit][-1].get("occurred", "") for event in events: # skip on duplicate incident if ( last_event_start_time and last_event_ids and last_event_start_time == event.get("occurred", "") and event.get("eventId", "") in last_event_ids ): continue # set incident context_event = remove_empty_entities(event) context_event["incidentType"] = IPS_EVENT_INCIDENT_TYPE if count >= fetch_limit: break if ((event_occurred_time := event.get("occurred")) and next_event_start_time == event_occurred_time) and ( event_id := event.get("eventId") ): # Save the event id for the next fetch dedup next_incidents_ids.append(event_id) incident = { "name": context_event.get("ruleName", ""), "occurred": context_event.get("occurred", ""), "severity": PLATFORM_SEVERITY_TO_SEVERITY_MAP.get(str(context_event.get("severity", 0)), 0), "rawJSON": json.dumps(context_event), "dbotMirrorId": str(event.get("eventId")), } remove_nulls_from_dictionary(incident) incidents.append(incident) count += 1 parsed_incidents_str = [ f"Incident name: {incident.get('name')} Incident date: {incident.get('occurred')}\n" for incident in incidents ] demisto.debug(f"FireeyeNX IPS Events: {parsed_incidents_str}") if next_incidents_ids: next_run = {"start_time": next_event_start_time, "event_ids": next_incidents_ids} return incidents, count, next_run def validate_fetch_type(fetch_type): """ Validate fetch type. :param fetch_type: A list contain types which user want to fetch. :return: """ if type(fetch_type) is list: if len(fetch_type) == 0: raise ValueError(MESSAGES["INVALID_FETCH_TYPE"]) if "Alerts" not in fetch_type and "IPS Events" not in fetch_type: raise ValueError(MESSAGES["INVALID_FETCH_TYPE"]) def validate_date_range(fetch_time: str): """ Validate date range and it should be up to 2 days as per API limitation. Will raise ValueError() if date is not in range. :param fetch_time: A time in format of (<number> <unit>). eg. 1 hour. """ two_days_before_time = datetime.utcnow() - timedelta(hours=48) start_time, _ = parse_date_range(fetch_time, utc=True) if start_time < two_days_before_time: raise ValueError(MESSAGES["FIRST_FETCH_ARG_VALIDATION"]) def pascal_case(st) -> str: """ Covert string to pascal case. :param st: string :return: pascal case string. """ if st.find("-") != -1 or st.find("_") != -1: st = "".join(a.capitalize() for a in re.split("-|_", st)) return st[:1].upper() + st[1 : len(st)] def remove_dash_and_underscore_from_key(d): # type: ignore """ Recursively traverse dict and change keys into pascal case. :param d: Input dictionary. :return: Dictionary with pascal case key. """ if not isinstance(d, dict | list): return d elif isinstance(d, list): return [remove_dash_and_underscore_from_key(value) for value in d] else: return {pascal_case(key): remove_dash_and_underscore_from_key(value) for key, value in d.items()} def get_request_timeout(request_timeout: str) -> int: """ Validate and return the request timeout parameter. The parameter must be a positive integer. Default value is set to 60 seconds for API request timeout. Will raise ValueError if inappropriate input given. :params req_timeout: Request timeout value. :return: boolean """ try: request_timeout_str = request_timeout if request_timeout else str(DEFAULT_REQUEST_TIMEOUT) request_timeout_int = int(request_timeout_str) except ValueError: raise ValueError(MESSAGES["REQUEST_TIMEOUT_VALIDATION"]) if request_timeout_int <= 0: raise ValueError(MESSAGES["REQUEST_TIMEOUT_VALIDATION"]) elif request_timeout_int > REQUEST_TIMEOUT_MAX_VALUE: raise ValueError(MESSAGES["REQUEST_TIMEOUT_EXCEED_ERROR"]) return request_timeout_int def get_fetch_limit(fetch_limit): """ Retrieve fetch limit from demisto arguments and validate it. Will raise ValueError if inappropriate input given. :param fetch_limit: The maximum number of incident want to fetch. :return: fetch limit """ fetch_limit = fetch_limit if fetch_limit else DEFAULT_FETCH_LIMIT try: fetch_limit_int = int(fetch_limit) if not 1 <= fetch_limit_int <= 200: raise ValueError except ValueError: raise ValueError(MESSAGES["FETCH_LIMIT_VALIDATION"]) return fetch_limit_int def generate_report_file_name(args: dict[str, Any]) -> str: """ Create the filename of the info file of report. :param args: Input arguments :return: The report file name """ return ( f"{args.get('report_type', '').lower().replace(' ', '_')}_fireeye_" f"{datetime.now().strftime('%Y-%m-%d_%H:%M:%S')}." f"{args.get('type', REPORT_TYPE_ALLOWED_FORMAT[args.get('report_type', '')][0])}" ) def validate_alert_report_type_arguments(args: dict[str, Any], params: dict[str, Any]) -> dict[str, Any]: """ Validates the arguments required for alert details report type from input arguments of reports command. Will raise ValueError if inappropriate input given. :param args: Input arguments :param params: Params to be passed in API call :return: Params to be passed in API call """ arg_keys = args.keys() if "infection_id" in arg_keys and "infection_type" in arg_keys: params["infection_id"] = args.get("infection_id", "") params["infection_type"] = args.get("infection_type", "") else: raise ValueError(MESSAGES["INVALID_ALERT_DETAILS"]) return params def validate_ips_report_type_arguments(args: dict[str, Any], params: dict[str, Any]) -> dict[str, Any]: """ Validates the arguments required for IPS report types from input arguments of reports command. Will raise ValueError if inappropriate input given. :param args: Input arguments :param params: Params to be passed in API call :return: Params to be passed in API call """ arg_keys = args.keys() if "limit" in arg_keys: limit = args.get("limit", "") try: params["limit"] = int(limit) except ValueError: raise ValueError(MESSAGES["INVALID_INT_VALUE"].format("limit")) if "interface" in arg_keys: params["interface"] = args.get("interface", "") if args.get("interface", "") != "All" else "all" return params def validate_time_parameters(args: dict[str, Any], params: dict[str, Any]) -> dict[str, Any]: """ Validates the time arguments from input arguments of reports command. :param args: Input arguments :param params: Params to be passed in API call :return: Params to be passed in API call """ arg_keys = args.keys() if "time_frame" in arg_keys: params["time_frame"] = args.get("time_frame", "") if "start_time" in arg_keys: start_time = args.get("start_time", "") date_time = dateparser.parse(start_time) if date_time: params["start_time"] = str(date_time.strftime(API_SUPPORT_DATE_FORMAT)) else: params["start_time"] = start_time if "end_time" in arg_keys: end_time = args.get("end_time", "") date_time = dateparser.parse(end_time) if date_time: params["end_time"] = str(date_time.strftime(API_SUPPORT_DATE_FORMAT)) else: params["end_time"] = end_time return params def get_reports_params(args: dict[str, Any]) -> dict[str, Any]: """ Validates the input arguments of command and returns parameter dictionary. This function validates the report_type, output format(type), time arguments. Will raise ValueError if inappropriate input given. :param args: Input arguments of command :return: Params dict or error message """ params: dict[str, Any] = {} arg_keys = args.keys() report_type = args.get("report_type", "") if report_type not in REPORT_TYPE_LABEL_NAME: raise ValueError(MESSAGES["INVALID_REPORT_TYPE"]) params["report_type"] = REPORT_TYPE_LABEL_NAME[report_type] if "type" in arg_keys: output_type = args.get("type", "") if output_type not in REPORT_TYPE_ALLOWED_FORMAT[report_type]: raise ValueError(MESSAGES["INVALID_REPORT_OUTPUT_TYPE"].format(", ".join(REPORT_TYPE_ALLOWED_FORMAT[report_type]))) params["type"] = output_type params = validate_time_parameters(args, params) params = validate_ips_report_type_arguments(args, params) if report_type == ALERT_DETAILS_REPORT: params = validate_alert_report_type_arguments(args, params) return params def add_time_suffix_into_arguments(args: dict[str, Any]): """ Add time suffix into arguments. :param args: arguments of alerts. :return: Add suffix to date format if full format is not given. """ arg_keys = args.keys() if "start_time" in arg_keys: start_time = args.get("start_time", "") date_time = dateparser.parse(start_time) if date_time: args["start_time"] = str(date_time.strftime(API_SUPPORT_DATE_FORMAT)) else: raise ValueError(MESSAGES["INVALID_TIME_VALIDATION"].format("start_time")) if "end_time" in arg_keys: end_time = args.get("end_time", "") date_time = dateparser.parse(end_time) if date_time: args["end_time"] = str(date_time.strftime(API_SUPPORT_DATE_FORMAT)) else: raise ValueError(MESSAGES["INVALID_TIME_VALIDATION"].format("end_time")) def get_events_params(args: dict[str, Any]) -> dict[str, Any]: """ Validates the input arguments of command and returns parameter dictionary or raises ValueError in case of validation failed. :param args: Input arguments of command :return: Params dict or error message """ params: dict[str, Any] = {"event_type": "Ips Event"} arg_keys = args.keys() if "duration" in arg_keys: params["duration"] = args.get("duration", "") if "start_time" in arg_keys: start_time = args.get("start_time", "") date_time = dateparser.parse(start_time) if date_time: params["start_time"] = str(date_time.strftime(API_SUPPORT_DATE_FORMAT)) else: raise ValueError(MESSAGES["INVALID_TIME_VALIDATION"].format("start_time")) if "end_time" in arg_keys: end_time = args.get("end_time", "") date_time = dateparser.parse(end_time) if date_time: params["end_time"] = str(date_time.strftime(API_SUPPORT_DATE_FORMAT)) else: raise ValueError(MESSAGES["INVALID_TIME_VALIDATION"].format("end_time")) if "mvx_correlated_only" in arg_keys: mvx_correlated_only = args.get("mvx_correlated_only", "").lower() try: mvx_correlated_only = argToBoolean(mvx_correlated_only) params["mvx_correlated_only"] = mvx_correlated_only except ValueError: raise ValueError(MESSAGES["INVALID_BOOLEAN_VALUE_ERROR"].format("mvx_correlated_only")) return params def prepare_hr_for_artifact_metadata(artifacts_info: list[dict[str, Any]]) -> str: """ Prepare Human readable for get artifact metadata. :param artifacts_info: List contain artifact metadata information. :return: Markdown format in string. """ artifacts_info_hr_list = [] for artifact in artifacts_info: artifacts_dict = { "Artifact Type": artifact.get("artifactType", ""), "Artifact Name": artifact.get("artifactName", ""), "Artifact Size (Bytes)": artifact.get("artifactSize", ""), } artifacts_info_hr_list.append(artifacts_dict) return tableToMarkdown( "Artifacts Metadata", artifacts_info_hr_list, headers=["Artifact Type", "Artifact Name", "Artifact Size (Bytes)"], removeNull=True, ) def remove_empty_entities(d): """ Recursively remove empty lists, empty dicts, or None elements from a dictionary. Note. This is extended feature of CommonServerPython.py remove_empty_elements() method as it was not removing empty character x == ''. :param d: Input dictionary. :return: Dictionary with all empty lists, and empty dictionaries removed. """ def empty(x): return x is None or x == {} or x == [] or x == "" if not isinstance(d, dict | list): return d elif isinstance(d, list): return [value for value in (remove_empty_entities(value) for value in d) if not empty(value)] else: return { key: value for key, value in ((key, remove_empty_entities(value)) for key, value in d.items()) if not empty(value) } def prepare_hr_for_alert_response(resp: dict) -> str: """ Prepare human readable for alert response. :param resp: Dictionary of API response :return: Markdown format for human readable. """ alert_hr_list = [] for alert in resp.get("alert", []): artifacts_dict = { "ID": alert.get("id", ""), "Distinguisher(UUID)": alert.get("uuid", ""), "Malware Name": alert.get("explanation", {}).get("malwareDetected", {}).get("malware", [{}])[0].get("name", ""), "Alert Type": alert.get("name", ""), VICTIM_IP: alert.get("src", {}).get("ip", ""), TIME_UTC: alert.get("occurred", ""), "Severity": alert.get("severity", ""), "Malicious": alert.get("malicious", ""), "SC Version": alert.get("scVersion", ""), "Victim Port": alert.get("src", {}).get("port", ""), "Victim MAC Address": alert.get("src", {}).get("mac", ""), "Target IP": alert.get("dst", {}).get("ip", ""), "Target Port": alert.get("dst", {}).get("port", ""), "Target MAC Address": alert.get("dst", {}).get("mac", ""), } alert_hr_list.append(artifacts_dict) headers = [ "ID", "Distinguisher(UUID)", "Malware Name", "Alert Type", VICTIM_IP, TIME_UTC, "Severity", "Malicious", "SC Version", "Victim Port", "Victim MAC Address", "Target IP", "Target Port", "Target MAC Address", ] return tableToMarkdown("Alert(s) Information", alert_hr_list, headers=headers, removeNull=True) def prepare_hr_for_events(events_info) -> str: """ Prepare the Human readable info for events command. :param events_info: The events data. :return: Human readable. """ hr_list = [] for record in events_info: hr_record = { "Event ID": record.get("eventId", None), TIME_UTC: record.get("occurred", ""), VICTIM_IP: record.get("srcIp", ""), "Attacker IP": record.get("dstIp", ""), "CVE ID": record.get("cveId", ""), "Severity": record.get("severity", None), "Rule": record.get("ruleName", ""), "Protocol": record.get("protocol", None), } hr_list.append(hr_record) return tableToMarkdown( "IPS Events", hr_list, [ "Event ID", TIME_UTC, VICTIM_IP, "Attacker IP", "CVE ID", "Severity", "Rule", "Protocol", ], removeNull=True, ) def replace_alert_url_key_domain_to_instance_url(alerts_resp: list, instance_url: str): """ Change domain of 'alertUrl' to the instance URL. :param alerts_resp: List contain dictionary of alerts. :param instance_url: URL to connect to the FireEye NX. """ def replace_url(alert_url: str, prefix_url: str) -> str: """ Replace alert url domain to prefix url. :param alert_url: Actual url that getting from response. :param prefix_url: URL to connect to the FireEye NX. :return: """ if alert_url.startswith("http://"): # NOSONAR alert_url = alert_url.replace("http://", "") # NOSONAR elif alert_url.startswith("https://"): alert_url = alert_url.replace("https://", "") if alert_url.startswith("www."): alert_url = alert_url.replace("www.", "") elif alert_url.startswith("WWW."): alert_url = alert_url.replace("WWW.", "") if not prefix_url.endswith("/"): prefix_url = f"{prefix_url + '/'}" alert_url_split = alert_url.split("/", 1) suffix_url = "".join(alert_url_split[count] for count in range(len(alert_url_split)) if count != 0) return f"{prefix_url + suffix_url}" for alert_index in range(len(alerts_resp)): if alerts_resp[alert_index].get("alertUrl"): alerts_resp[alert_index]["alertUrl"] = replace_url(alerts_resp[alert_index]["alertUrl"], instance_url) def update_start_time(start_time: float) -> float: """Check that the start time is bigger (later) than the current time - ~48 hours (due to API limitations we can fetch events only from the last 48 hours) if not it returns the current time - ~48 hours Args: start_time: The time we use for start fetching. Returns: The return value. The time we use for start fetching. Validated it's not less (earlier) than current time - ~48 hours. """ current_timestamp = date_to_timestamp(datetime.utcnow(), DATE_FORMAT) / 1000.0 if current_timestamp - FORTY_EIGHT_HOURS_IN_SECOND > start_time: updated_start_time = current_timestamp - FORTY_EIGHT_HOURS_IN_SECOND demisto.debug( f"Start time {start_time=} is earlier than [current time {current_timestamp=} - ~ 48 hours], " f"Start time updated to: {updated_start_time=}" ) return updated_start_time return start_time """ REQUESTS FUNCTIONS """ def test_function(**kwargs) -> str: """ Performs test connectivity by valid http response. :param kwargs: Contains all required parameters. :return: raise ValueError if any error occurred during connection """ if kwargs["is_fetch"]: fetch_limit = get_fetch_limit(kwargs["fetch_limit"]) # getting numeric value from string representation start_time, _ = parse_date_range(kwargs["first_fetch_time"], date_format=DATE_FORMAT, utc=True) # validate start_time should be less then 48 hour as per API limitation validate_date_range(kwargs["first_fetch_time"]) validate_fetch_type(kwargs["fetch_type"]) first_fetch = date_to_timestamp(start_time, date_format=DATE_FORMAT) / 1000 fetch_incidents( client=kwargs["client"], last_run=demisto.getLastRun(), first_fetch=first_fetch, fetch_limit=fetch_limit, malware_type=kwargs["malware_type"], is_test=True, fetch_type=kwargs["fetch_type"], mvx_correlated=kwargs["mvx_correlated"], replace_alert_url=kwargs["replace_alert_url"], instance_url=kwargs["instance_url"], fetch_artifacts=kwargs["fetch_artifacts"], ) else: headers = {"Accept": CONTENT_TYPE_JSON} kwargs["client"].http_request(method="POST", url_suffix=URL_SUFFIX["GET_TOKEN"], headers=headers) return "ok" @logger def get_artifacts_metadata_by_alert_command(client: Client, args: dict[str, Any]) -> str | CommandResults: """ Gets malware artifacts metadata for the specified UUID. :param client: The Client object used for request :param args: The command arguments :return: CommandResults """ uuid = args.get("uuid", "") uuid = uuid.lower() # Preparing header headers = { "Accept": CONTENT_TYPE_JSON, "X-FeApi-Token": client.get_api_token(), } # Call get artifacts metadata api resp = client.http_request( "GET", url_suffix=URL_SUFFIX["GET_ARTIFACTS_METADATA"].format(uuid), headers=headers, ) artifacts_info = resp.get("artifactsInfoList", []) if len(artifacts_info) == 0: return MESSAGES["NO_RECORDS_FOUND"].format("artifacts metadata") # Create entry context artifacts_metadata_custom_ec = createContext(artifacts_info, removeNull=True) # Prepare human readable hr = prepare_hr_for_artifact_metadata(artifacts_info) custom_ec_for_artifact_metadata = { "ArtifactsMetadata": artifacts_metadata_custom_ec, "Uuid": uuid, } # Remove dash, underscore from key and make it pascal case. custom_ec = remove_dash_and_underscore_from_key(custom_ec_for_artifact_metadata) return CommandResults( outputs_prefix="FireEyeNX.Alert", outputs_key_field="Uuid", outputs=custom_ec, readable_output=hr, raw_response=resp, ) @logger def get_artifacts_by_alert_command(client: Client, args: dict[str, Any]) -> str | dict[str, Any]: """ Downloads malware artifacts data for the specified UUID as a zip file. :param client: The Client object used for request :param args: The command arguments :return: Dictionary of file info or empty result message """ uuid = args.get("uuid", "") uuid = uuid.lower() # Preparing header headers = { "X-FeApi-Token": client.get_api_token(), } # Call get artifacts data api artifacts_resp = client.http_request( "GET", url_suffix=URL_SUFFIX["GET_ARTIFACTS"].format(uuid), headers=headers, ) # Create file from Content if int(artifacts_resp.headers.get("Content-Length", "0")) > 0: file_name = f"{uuid}.zip" file_entry = fileResult(filename=file_name, data=artifacts_resp.content) return file_entry else: return MESSAGES["NO_RECORDS_FOUND"].format("artifacts data") @logger def get_reports_command(client: Client, args: dict[str, Any]) -> str | dict[str, Any]: """ Returns reports on selected alerts by specifying a time_frame value or a start_time and end_time of the search range. Will raise ValueError if inappropriate input given. :param client: client object which is used to get response from api :param args:The command arguments :return: Dictionary of file info or empty result message """ # Validate arguments params = get_reports_params(args) # Preparing header headers = { "X-FeApi-Token": client.get_api_token(), "Accept": CONTENT_TYPE_JSON, } # API call resp: Response = client.http_request( method="GET", url_suffix=URL_SUFFIX["GET_REPORTS"], params=params, headers=headers, ) # Create file from Content if int(resp.headers.get("Content-Length", "")) > 0: file_entry = fileResult( filename=generate_report_file_name(args), data=resp.content, file_type=EntryType.ENTRY_INFO_FILE, ) return file_entry else: return MESSAGES["NO_RECORDS_FOUND"].format("report contents") @logger def get_alerts_command( client: Client, args: dict[str, Any], replace_alert_url: bool, instance_url: str, ) -> str | CommandResults: """ Retrieve list of alerts based on various argument(s). :param client: Client object :param args: The command arguments provided by user. :param replace_alert_url: Replace the domain of the alert URL key to the Instance URL. :param instance_url: URL to connect to the FireEye NX. :return: Standard command result or no records found message """ add_time_suffix_into_arguments(args) # Preparing header headers = { "X-FeApi-Token": client.get_api_token(), "Accept": CONTENT_TYPE_JSON, } # http call resp = client.http_request( method="GET", url_suffix=URL_SUFFIX["GET_ALERTS"], params=args, headers=headers, ) total_records = resp.get("alertsCount", 0) if total_records <= 0: return MESSAGES["NO_RECORDS_FOUND"].format("alert(s)") alerts_resp = resp.get("alert", []) # Replace the domain of the alertUrl key to Instance URL if it is true. if replace_alert_url: replace_alert_url_key_domain_to_instance_url(alerts_resp, instance_url) # Creating human-readable hr = prepare_hr_for_alert_response(resp) # Creating entry context custom_ec_for_alerts = remove_empty_entities(alerts_resp) # Remove dash, underscore from key and make it pascal case. custom_ec = remove_dash_and_underscore_from_key(custom_ec_for_alerts) return CommandResults( outputs_prefix="FireEyeNX.Alert", outputs_key_field="Uuid", outputs=custom_ec, readable_output=hr, raw_response=resp, ) @logger def fetch_incidents( **kwargs, ) -> tuple[dict[str, Any] | None, list[dict[str, Any]] | None]: """ This function retrieves new incidents every interval. :param kwargs : Dictionary contain all required arguments. :return: Tuple containing two elements. incidents list and timestamp. """ # Retrieving last run time if not none, otherwise first_fetch will be considered. last_run = kwargs["last_run"] start_time = kwargs["first_fetch"] next_run = last_run incidents = [] fetch_count = 0 if "IPS Events" in (kwargs["fetch_type"] or []): if (events_start_time := last_run.get("events", {}).get("start_time")) and ( parsed_start_time := dateparser.parse(events_start_time) ): start_time = parsed_start_time.timestamp() start_time = update_start_time(start_time) demisto.debug(f"FireeyeNX IPS Events Start Time: {start_time}") incidents, fetch_count, next_run_events = get_incidents_for_event( kwargs["client"], start_time, kwargs["fetch_limit"], kwargs["mvx_correlated"], last_run, ) next_run["events"] = next_run_events # reset start time before next fetch type start_time = kwargs["first_fetch"] if "Alerts" in (kwargs["fetch_type"] or []) and (fetch_count < kwargs["fetch_limit"]): if (alerts_start_time := last_run.get("alerts", {}).get("start_time")) and ( parsed_start_time := dateparser.parse(alerts_start_time) ): start_time = parsed_start_time.timestamp() start_time = update_start_time(start_time) demisto.debug(f"FireeyeNX Alerts Start Time: {start_time}") alert_incidents, next_run_alerts = get_incidents_for_alert( client=kwargs["client"], malware_type=kwargs["malware_type"], start_time=start_time, fetch_limit=kwargs["fetch_limit"], replace_alert_url=kwargs["replace_alert_url"], instance_url=kwargs["instance_url"], is_test=kwargs["is_test"], fetch_artifacts=kwargs["fetch_artifacts"], fetch_count=fetch_count, last_run=last_run, ) incidents.extend(alert_incidents) next_run["alerts"] = next_run_alerts if kwargs["is_test"]: return None, None return next_run, incidents @logger def get_events_command(client: Client, args: dict[str, Any]) -> str | CommandResults: """ Retrieve list of events based on various argument(s). Will raise an exception if validation fails. :param client: Client object :param args: The command arguments provided by user. :return: Standard command result or no records found message """ # Validate arguments params = get_events_params(args) # Preparing header headers = { "X-FeApi-Token": client.get_api_token(), "Accept": CONTENT_TYPE_JSON, } # http call resp = client.http_request( method="GET", url_suffix=URL_SUFFIX["GET_EVENTS"], params=params, headers=headers, ) total_records = resp.get("events", []) if not total_records: return MESSAGES["NO_RECORDS_FOUND"].format("event(s)") # Creating entry context custom_ec_for_event = createContext(total_records, removeNull=True) custom_ec = remove_dash_and_underscore_from_key(custom_ec_for_event) # Creating human-readable hr = prepare_hr_for_events(total_records) return CommandResults( outputs_prefix="FireEyeNX.Event", outputs_key_field="EventId", outputs=custom_ec, readable_output=hr, raw_response=resp, ) def main() -> None: """ PARSE AND VALIDATE INTEGRATION PARAMS """ # Commands dict commands = { "fireeye-nx-get-artifacts-metadata-by-alert": get_artifacts_metadata_by_alert_command, "fireeye-nx-get-reports": get_reports_command, "fireeye-nx-get-artifacts-by-alert": get_artifacts_by_alert_command, "fireeye-nx-get-events": get_events_command, } commands_with_params = {"fireeye-nx-get-alerts": get_alerts_command} command = demisto.command() demisto.info(f"Command being called is {command}") try: url = demisto.params().get("url") username = demisto.params().get("credentials", {}).get("identifier") password = demisto.params().get("credentials", {}).get("password") if password: password = password.encode("utf-8") verify_certificate = not demisto.params().get("insecure", False) proxy = demisto.params().get("proxy", False) request_timeout = demisto.params().get("request_timeout") request_timeout = get_request_timeout(request_timeout) base_url = f"{url}/wsapis/{API_VERSION}" # prepare client class object client = Client( base_url=base_url, verify=verify_certificate, proxy=proxy, auth=(username, password), request_timeout=request_timeout, ) # Trim the arguments args = strip_blank(demisto.args()) # This is the call made when pressing the integration Test button. if demisto.command() == "test-module": is_fetch = demisto.params().get("isFetch") first_fetch_time = demisto.params().get("first_fetch") # Set first fetch time as default if user leave empty first_fetch_time = first_fetch_time if first_fetch_time else DEFAULT_FIRST_FETCH malware_type = demisto.params().get("malware_type") fetch_limit = demisto.params().get("max_fetch") fetch_type = demisto.params().get("fetch_type") mvx_correlated = demisto.params().get("fetch_mvx_correlated_events", False) replace_alert_url = demisto.params().get("replace_alert_url", False) fetch_artifacts = demisto.params().get("fetch_artifacts", False) result = test_function( client=client, first_fetch_time=first_fetch_time, fetch_limit=fetch_limit, malware_type=malware_type, is_fetch=is_fetch, fetch_type=fetch_type, mvx_correlated=mvx_correlated, replace_alert_url=replace_alert_url, instance_url=url, fetch_artifacts=fetch_artifacts, ) demisto.results(result) elif demisto.command() == "fetch-incidents": malware_type = demisto.params().get("malware_type", "") first_fetch_time = demisto.params().get("first_fetch") # Set first fetch time as default if user leave empty first_fetch_time = first_fetch_time if first_fetch_time else DEFAULT_FIRST_FETCH fetch_limit = demisto.params().get("max_fetch") fetch_limit = get_fetch_limit(fetch_limit) demisto.debug(f"Fetch Limit {fetch_limit}") fetch_type = demisto.params().get("fetch_type") mvx_correlated = demisto.params().get("fetch_mvx_correlated_events", False) # Getting numeric value from string representation start_time, _ = parse_date_range(first_fetch_time, date_format=DATE_FORMAT, utc=True) # Validate start_time should be less then 48 hour as per API limitation validate_date_range(first_fetch_time) validate_fetch_type(fetch_type) # Flag indicate to replace the 'alertUrl' domain to Integration URL or not. replace_alert_url = demisto.params().get("replace_alert_url", False) fetch_artifacts = demisto.params().get("fetch_artifacts", False) next_run, incidents = fetch_incidents( client=client, malware_type=malware_type, last_run=demisto.getLastRun(), fetch_limit=fetch_limit, first_fetch=date_to_timestamp(start_time, date_format=DATE_FORMAT) / 1000, fetch_type=fetch_type, mvx_correlated=mvx_correlated, replace_alert_url=replace_alert_url, instance_url=url, fetch_artifacts=fetch_artifacts, is_test=False, ) # saves next_run for the time fetch-incidents is invoked. demisto.debug(f"FireEyeNX setting next run to: {next_run}") demisto.setLastRun(next_run) demisto.incidents(incidents) elif command in commands: return_results(commands[command](client, args)) elif command in commands_with_params: # Flag indicate to replace alertUrl domain to Integration URL or not. replace_alert_url = demisto.params().get("replace_alert_url", False) return_results(commands_with_params[command](client, args, replace_alert_url, url)) # Log exceptions except Exception as e: return_error(f"Error: {e!s}") if __name__ in ("__main__", "__builtin__", "builtins"): main()