IllusiveNetworks
The Illusive Attack Management API allows customers to retrieve detected incidents with a forensics timeline, attack surface insights, collect forensics on-demand, and manage a variety of operations with regard to deceptive entities, deception policies, and more.
Deception & Breach Simulation · Illusive Networks
Details
| ID | IllusiveNetworks |
|---|---|
| Provider | Proofpoint Inc |
| Category | Deception & Breach Simulation |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
Overview
The Illusive Attack Management API allows customers to retrieve detected incidents with a forensics timeline, attack surface insights, collect forensics on-demand, and manage a variety of operations with regard to deceptive entities, deception policies, and more.
This integration was integrated and tested with version 130 of IllusiveNetworks
Configure IllusiveNetworks on Cortex XSOAR
Use Cases
- Automatically collect data and forensics from new incidents detected by Illusive
- Enrich SOC data by retrieving a rich set of incident and forensics information, including: 1) host details and forensics from a potentially compromised host, 2) a forensics timeline, 3) forensics analysis, 4) additional data
- Auto-analyze collected data and calculate incident severity to speed up SOC response times
- Collect forensics from any compromised host and retrieve a forensics timeline
- Retrieve detailed lists of approved and suggested deceptive servers and users
- Approve, delete, and query deceptive entities
- Manage deception policy assignments per host
- Retrieve attack surface insights for Crown Jewels and specific hosts
Configure IllusiveNetworks on Cortex XSOAR
Illusive Console
- Open the Illusive Management console, navigate to Settings > General, and locate the API KEYS section. Generate a new API key with all permissions and copy the token at the end of the process.
Cortex XSOAR Console
- Navigate to Settings > Integrations > Servers & Services.
- Search for IllusiveNetworks.
- Click Add instance to create and configure a new integration instance.
| Parameter | Description | Required |
|---|---|---|
| url | Server URL (e.g. https://example.net) | True |
| api_token | API Token | True |
| isFetch | Fetch incidents | False |
| incidentType | Incident type | False |
| insecure | Trust any certificate (not secure) | False |
| proxy | Use system proxy settings | False |
| fetch_time | The initial time to fetch from | False |
| has_forensics | Fetch only incidents with forensics | True |
- Click Test to validate the URLs, token, and connection.
Fetched Incidents Data
{
“sourceIp”: “10.90.10.25”,
“sourceOperatingSystem”: null,
“policyName”: null,
“incidentTypes”: [“DECEPTION”],
“riskInsights”: {“stepsToDomainAdmin”: null, “stepsToCrownJewel”: null},
“deceptionFamilies”: [“FAMILY_TYPE_BROWSERS”],
“lastSeenUser”: null,
“closed”: false,
“unread”: true,
“flagged”: false,
“hasForensics”: false,
“incidentId”: 32,
“incidentTimeUTC”: “2020-05-04T11:37:10.231Z”,
“sourceHostname”: null,
“userNotes”: null
}
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.
- illusive-get-forensics-timeline
- illusive-get-asm-host-insight
- illusive-get-asm-cj-insight
- illusive-get-deceptive-users
- illusive-get-deceptive-servers
- illusive-is-deceptive-user
- illusive-is-deceptive-server
- illusive-add-deceptive-users
- illusive-add-deceptive-servers
- illusive-delete-deceptive-users
- illusive-delete-deceptive-servers
- illusive-assign-host-to-policy
- illusive-remove-host-from-policy
- illusive-run-forensics-on-demand
- illusive-get-incidents
- illusive-get-event-incident-id
- illusive-get-incident-events
- illusive-get-forensics-analyzers
- illusive-get-forensics-triggering-process-info
- illusive-get-forensics-artifacts
illusive-get-forensics-timeline
Retrieve forensics timeline for a specific incident
Base Command
illusive-get-forensics-timeline
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The desired incident ID | Required |
| start_date | The starting date of the forensics timeline. | Optional |
| end_date | The last date of the forensics timeline. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.Forensics.Evidence.details | String | The forensics evidence details |
| Illusive.Forensics.Evidence.eventId | String | The event ID |
| Illusive.Forensics.Evidence.id | String | The forensics evidence ID |
| Illusive.Forensics.Evidence.source | String | The Evidence source |
| Illusive.Forensics.Evidence.starred | Boolean | Whether the forensics evidence has been starred |
| Illusive.Forensics.Evidence.time | Date | Date and time of the forensics evidence |
| Illusive.Forensics.Evidence.title | String | The forensics evidence description |
| Illusive.Forensics.IncidentId | String | The Incident Id |
| Illusive.Forensics.Status | String | The process progress ( Done, InProgress) |
| Illusive.Forensics.Evidence.date | Date | The forensics evidence date |
Command Example
illusive-get-forensics-timeline incident_id=80 start_date=”10 days” end_date=”3 hours”
Human Readable Output
| date | details | eventId | id | source | starred | time | title | type |
|---|---|---|---|---|---|---|---|---|
| 2020-06-29 09:16:17.480 | id: 4 date: 2020-06-29 09:16:17.480 type: LOGIN sourceIP: 172.27.102.12 trap: hr injectedUserName: dgffg injectedPassword: **** destinationIpAddress: 172.27.102.6 serviceType: WEB data: Is Successful Login: false, Accept-language: en-US,en;q=0.9, Web Protocol: HTTP, Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9, Web Host: 172.27.102.6, Web Url: /, Authorization: Digest username=”dgffg”, realm=”Domain Name”, nonce=”1593422172658:ad3f7cc0c86b52747fba1d68583c3827”, uri=”/”, response=”9f5d4174395c7d09460fc88e454713aa”, opaque=”9AC5ADA4A6317F9FB4F2B1211D8A7EFE”, qop=auth, nc=00000002, cnonce=”b000143183c56904”, Web Body: , Web Method: GET, Upgrade-insecure-requests: 1, Web User Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36, Connection: keep-alive, Cache-control: max-age=0, Accept-encoding: gzip, deflate hasForensics: No title: WEB login attempt with the username dgffg to the deceptive URL 172.27.102.6/ |
4 | d59f0b0a-4a66-40d0-9565-563adc7534f1 | MANAGEMENT | false | 1593422177480 | WEB login attempt with the username dgffg to the deceptive URL 172.27.102.6/ | EVENT |
illusive-get-asm-host-insight
Retrieve the specified host insights from Attack Surface Manager
Base Command
illusive-get-asm-host-insight
Input
| Argument Name | Description | Required |
|---|---|---|
| hostnameOrIp | The hostname or IP address of the desired host | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.AttackSurfaceInsightsHost.DomainName | String | The host domain |
| Illusive.AttackSurfaceInsightsHost.HostName | String | The host hostname |
| Illusive.AttackSurfaceInsightsHost.HostType | String | The host type (Server, Workstation, Other) |
| Illusive.AttackSurfaceInsightsHost.IpAddresses | String | The host IP address |
| Illusive.AttackSurfaceInsightsHost.OperatingSystemName | String | The host operating system name |
| Illusive.AttackSurfaceInsightsHost.OperatingSystemVersion | String | The host operating system version |
| Illusive.AttackSurfaceInsightsHost.OrganizationalUnit | String | The host Active Directory Organizational Unit |
| Illusive.AttackSurfaceInsightsHost.SourceConnectivityExposure | Number | The host Source Connectivity Exposure to crown jewels and domain user credentials |
Command Example
illusive-get-asm-host-insight hostnameOrIp=172.27.139.12
Human Readable Output
Illusive ASM Host Insights
| domainName | hostName | hostType | ipAddresses | operatingSystemName | operatingSystemVersion | organizationalUnit | sourceConnectivityExposure |
|---|---|---|---|---|---|---|---|
| illusive.com | win5.illusive.com | Workstation | 172.27.139.12,::1,fe80::ffff:ffff:fffe,fe80::2d2d:5763:8c1a:7b9 | Windows 10 | clients | 0.0 |
illusive-get-asm-cj-insight
Retrieve Crown-Jewels insights from Attack Surface Manager
Base Command
illusive-get-asm-cj-insight
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.AttackSurfaceInsightsCrownJewel.data | Unknown | The number of connections to this Crown Jewel per service type |
| Illusive.AttackSurfaceInsightsCrownJewel.hostname | String | The crown jewel hostname |
| Illusive.AttackSurfaceInsightsCrownJewel.machineTagAndSubTags.tag | String | The List of a crown jewel category and subcategory couplings |
| Illusive.AttackSurfaceInsightsCrownJewel.MachineTagAndSubTags.subTag | String | The List of a crown jewel category and subcategory couplings |
| Illusive.AttackSurfaceInsightsCrownJewel.targetExposureRank | Number | The crown jewel target exposure |
Command Example
illusive-get-asm-cj-insight
Human Readable Output
Illusive ASM Crown Jewels Insights
| data | hostname | machineTagAndSubTags | targetExposureRank |
|---|---|---|---|
| {‘key’: ‘RDP’, ‘value’: 1} | 172.27.139.12 | {‘tag’: ‘Mainframe’, ‘subTag’: ‘MAINFRAME’} | 0.0 |
illusive-get-deceptive-users
Retrieve a list of all deceptive users
Base Command
illusive-get-deceptive-users
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The status of the desired deceptive users (APPROVED, SUGGESTED, ALL) | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.DeceptiveUser.userName | String | The deceptive user name |
| Illusive.DeceptiveUser.domainName | String | The deceptive user domain |
| Illusive.DeceptiveUser.policyNames | Unknown | The deception policies the deceptive user is assigned to |
| Illusive.DeceptiveUser.password | String | The deceptive user password |
| Illusive.DeceptiveUser.deceptiveState | String | The deceptive user state (APPROVED, SUGGESTED, ALL) |
| Illusive.DeceptiveUser.adUser | Boolean | Whether the deceptive user is a genuine user in Active Directory |
| Illusive.DeceptiveUser.activeUser | Boolean | In case the deceptive user is a real AD user, indicates whether he is active |
Command Example
!illusive-get-deceptive-users type=APPROVED
Human Readable Output
Illusive Deceptive Users
| activeUser | adUser | deceptiveState | domainName | password | policyNames | username |
|---|---|---|---|---|---|---|
| false | false | APPROVED | illusive.com | Password | Full Protection | user1 |
| false | false | APPROVED | illusive.com | Password | Full Protection | user2 |
illusive-get-deceptive-servers
Retrieve a list of all deceptive servers
Base Command
illusive-get-deceptive-servers
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The status of the desired deceptive servers (APPROVED, SUGGESTED, ALL) | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.DeceptiveServer.host | String | The deceptive server hostname |
| Illusive.DeceptiveServer.policyNames | String | The deception policies the deceptive server is assigned to |
| Illusive.DeceptiveServer.adHost | Boolean | Whether the deceptive server is a genuine machine in Active Directory |
| Illusive.DeceptiveServer.deceptiveState | String | The deceptive server state (APPROVED, SUGGESTED, ALL) |
| Illusive.DeceptiveServer.serviceTypes | String | The deception services the deceptive server is assigned to |
Command Example
!illusive-get-deceptive-servers type=APPROVED
Human Readable Output
Illusive Deceptive Servers
| adHost | deceptiveState | host | policyNames | serviceTypes |
|---|---|---|---|---|
| false | APPROVED | server1.illusive.com | adiPo, Full Protection |
SHARE, DB |
| false | APPROVED | server2.illusive.com | Full Protection | WEB, DB |
| false | APPROVED | server3.illusive.com | adiPo, Full Protection |
FTP, SHARE, DB |
illusive-is-deceptive-user
Retrieve whether a specified user is deceptive
Base Command
illusive-is-deceptive-user
Input
| Argument Name | Description | Required |
|---|---|---|
| username | The username to be verified | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.IsDeceptive.Username | String | The checked username |
| Illusive.IsDeceptive.IsDeceptiveUser | Boolean | Is the specified user conducted as a deceptive user |
Command Example
!illusive-is-deceptive-user username=user1
Human Readable Output
Illusive Is Deceptive
| IsDeceptiveUser | Username |
|---|---|
| true | user1 |
illusive-is-deceptive-server
Retrieve whether a specified server is deceptive
Base Command
illusive-is-deceptive-server
Input
| Argument Name | Description | Required |
|---|---|---|
| hostname | The server hostname to be verified | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.IsDeceptive.IsDeceptiveServer | Boolean | Is the specified server conducted as a deceptive server |
| Illusive.IsDeceptive.Hostname | String | The checked server hostname |
Command Example
!illusive-is-deceptive-server hostname=server5.illusive.com
Human Readable Output
Illusive Is Deceptive
| Hostname | IsDeceptiveServer |
|---|---|
| server5.illusive.com | false |
illusive-add-deceptive-users
Add or approve deceptive users
Base Command
illusive-add-deceptive-users
Input
| Argument Name | Description | Required |
|---|---|---|
| domain_name | The deceptive user domain | Required |
| password | The deceptive user password | Required |
| policy_names | The deception policies to be assigned to the new deceptive user | Optional |
| username | The deceptive user name | Required |
Context Output
There is no context output for this command.
Command Example
!illusive-add-deceptive-users domain_name=illusive.com password=pass username=user3
Human Readable Output
Illusive Add Deceptive User Succeeded
| domainName | password | policyNames | userName |
|---|---|---|---|
| illusive.com | pass | All Policies | user3 |
illusive-add-deceptive-servers
Add or approve deceptive servers
Base Command
illusive-add-deceptive-servers
Input
| Argument Name | Description | Required |
|---|---|---|
| host | The deceptive server hostname | Required |
| policy_names | The deception policies to be assigned to the new deceptive server | Optional |
| service_types | The deception services to be assigned to the new deceptive server | Required |
Context Output
There is no context output for this command.
Command Example
!Set key=”serviceTypes” value=”FTP”
!Set key=”serviceTypes” value=”SSH” append=true
!illusive-add-deceptive-servers host=server4.illusive.com service_types=${serviceTypes}
Human Readable Output
Illusive Add Deceptive Server Succeeded
| host | policyNames | serviceTypes |
|---|---|---|
| server4.illusive.com | All Policies | FTP, SSH |
illusive-delete-deceptive-users
Delete deceptive users
Base Command
illusive-delete-deceptive-users
Input
| Argument Name | Description | Required |
|---|---|---|
| deceptive_users | The list of deceptive users to delete | Required |
Context Output
There is no context output for this command.
Command Example
!illusive-delete-deceptive-users deceptive_users=user3
Human Readable Output
Deceptive User [‘user3’] was successfully Deleted
illusive-delete-deceptive-servers
Delete deceptive servers
Base Command
illusive-delete-deceptive-servers
Input
| Argument Name | Description | Required |
|---|---|---|
| deceptive_hosts | The list of deceptive servers to delete | Required |
Context Output
There is no context output for this command.
Command Example
!Set key=”servers” value=”server5.illusive.com”
!Set key=”servers” value=”server1.illusive.com” append=true
!illusive-delete-deceptive-servers deceptive_hosts=${servers}
Human Readable Output
Deceptive Servers [‘server5.illusive.com’, ‘server1.illusive.com’] were successfully Deleted
illusive-assign-host-to-policy
Assign a deception policy to domain hosts
Base Command
illusive-assign-host-to-policy
Input
| Argument Name | Description | Required |
|---|---|---|
| policy_name | Policy name to assign | Required |
| hosts | List of hosts to assign, in the following format: machine@domain. Maximum number of hosts is 1000. |
Required |
Context Output
There is no context output for this command.
Command Example
!illusive-assign-host-to-policy hosts=WIN7@illusive.com policy_name=”Full Protection”
Human Readable Output
Illusive Assign Machines to Policy Succeeded
| hosts | isAssigned | policy_name |
|---|---|---|
| WIN7@illusive.com | true | Full Protection |
illusive-remove-host-from-policy
Remove deception policy assignment from domain hosts
Base Command
illusive-remove-host-from-policy
Input
| Argument Name | Description | Required |
|---|---|---|
| hosts | List of hosts to remove policy assignment from, in the following format: machine@domain. Maximum number of hosts is 1000 |
Required |
Context Output
There is no context output for this command.
Command Example
!illusive-remove-host-from-policy hosts=WIN7@illusive.com
Human Readable Output
Illusive Remove Machines from All Policies Succeeded
| hosts | isAssigned | policy_name |
|---|---|---|
| WIN7@illusive.com | false |
illusive-run-forensics-on-demand
Collect forensics on a specified host and retrieve the forensics timeline
Base Command
illusive-run-forensics-on-demand
Input
| Argument Name | Description | Required |
|---|---|---|
| fqdn_or_ip | The host fqdn or IP address on which to collect forensics | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.Event.eventId | Number | The created event ID of the operation |
Command Example
!illusive-run-forensics-on-demand fqdn_or_ip=172.27.139.12
Human Readable Output
Illusive Run Forensics On Demand
| eventId |
|---|
| 123 |
illusive-get-incidents
Retrieve incidents
Base Command
illusive-get-incidents
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The desired incident ID to retrieve. If specified - other arguments are ignored and only a single incident can be retrieved |
Optional |
| hostnames | The list of hostnames to retrieve incidents | Optional |
| has_forensics | Whether to retrieve incidents with forensics only | Optional |
| limit | Use offset and limit for pagination. The maximum limit is 100. |
Optional |
| offset | Use offset and limit for pagination. | Optional |
| start_date | start date | Optional |
Context Output
| Path | Type | Description |
| — | — | — |
| Illusive.Incident.closed | Boolean | Whether the incident has been closed |
| Illusive.Incident.deceptionFamilies | String | The deception families of the
deceptions used to trigger
the incident |
| Illusive.Incident.flagged | Boolean | Whether the incident has been flagged |
| Illusive.Incident.hasForensics | Boolean | Whether incident has forensics |
| Illusive.Incident.incidentId | Number | The Incident ID |
| Illusive.Incident.incidentTimeUTC | Date | Date and time of the incident |
| Illusive.Incident.incidentTypes | Unknown | Type of events detected |
| Illusive.Incident.lastSeenUser | String | The user who last reviewed the incident |
| Illusive.Incident.policyName | String | The compromised host’s policy |
| Illusive.Incident.riskInsights.stepsToCrownJewel | Number | The compromised host’s lateral distance from Crown Jewels |
| Illusive.Incident.riskInsights.stepsToDomainAdmin | Number | The compromised host’s lateral distance from domain admin accounts |
| Illusive.Incident.sourceHostname | String | The compromised host’s name |
| Illusive.Incident.sourceIp | String | The compromised host’s IP address |
| Illusive.Incident.sourceOperatingSystem | String | The compromised host’s operating system |
| Illusive.Incident.unread | Boolean | Whether the incident has been read |
| Illusive.Incident.userNotes | String | The analyst’s comments |
Command Example
!illusive-get-incidents incident_id=28
Human Readable Output
Illusive Incidents
| closed | deceptionFamilies | flagged | hasForensics | incidentId | incidentTimeUTC | incidentTypes | lastSeenUser | policyName | riskInsights | sourceHostname | sourceIp | sourceOperatingSystem | unread | userNotes |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| false | FAMILY_TYPE_BROWSERS | false | false | 28 | 2020-04-20T06:44:33.207Z | DECEPTION | stepsToDomainAdmin: null stepsToCrownJewel: null |
172.27.139.14 | false |
illusive-get-event-incident-id
Retrieve the incident ID of an event
Base Command
illusive-get-event-incident-id
Input
| Argument Name | Description | Required |
|---|---|---|
| event_id | The Event id | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.Event.incidentId | Number | The Incident ID |
| Illusive.Event.eventId | Number | The given event ID |
| Illusive.Event.status | String | The status command ( Done, InProgress) |
Command Example
!illusive-get-event-incident-id event_id=80
Human Readable Output
Illusive Get Incident
| eventId | incidentId | status |
|---|---|---|
| 80 | 72 | Done |
illusive-get-incident-events
Retrieve all the events that are associated with an incident
Base Command
illusive-get-incident-events
Input
| Argument Name | Description | Required |
|---|---|---|
| incident_id | The incident ID on which to retrieve the associated events | Required |
| limit | The maximum number of events to retrieve | Optional |
| offset | Use offset and limit for pagination | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.Incident.incidentId | Number | The corresponding incident ID |
| Illusive.Incident.eventsNumber | Number | The number of associated events |
| Illusive.Incident.Event.eventId | Number | The event ID |
| Illusive.Incident.Event.eventTimeUTC | Date | The event time |
| Illusive.Incident.Event.hasForensics | Boolean | Whether the event has forensics |
Command Example
!illusive-get-incident-events incident_id=2
Human Readable Output
Illusive get incident’s events
| eventId | eventTimeUTC | hasForensics |
|---|---|---|
| 4 | 2020-06-29T09:16:17.480Z | false |
| 3 | 2020-06-29T09:16:17.464Z | false |
| 2 | 2020-06-29T09:16:12.673Z | false |
illusive-get-forensics-analyzers
Retrieve Illusive’s forensics analyzers on a certain event
Base Command
illusive-get-forensics-analyzers
Input
| Argument Name | Description | Required |
|---|---|---|
| event_id | The event ID to retrieve the forensics analyzers from | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.Event.incidentId | Number | The corresponding incident ID |
| Illusive.Event.eventId | Number | The corresponding event ID |
| Illusive.Event.ForensicsAnalyzers.analyzerName | String | The forensics analyzer name |
| Illusive.Event.ForensicsAnalyzers.analyzerValue | String | The forensics analyzer description |
Command Example
!illusive-get-forensics-analyzers event_id=2
Human Readable Output
Illusive Forensics Analyzers
| analyzerName | analyzerValue |
|---|---|
| Summary | An attempt to browse to the deceptive URL hr (172.27.102.6) was detected from 172.27.102.12 |
| Event Source And Destination | Event ID: 2 Event time: 2020-06-29T09:16:12.673Z Event originated from 172.27.102.12 Event targeted hr (172.27.102.6) |
| Web | A GET request was made to the url http://172.27.102.6/ |
| Forensics Failure Reason | No resolving for host 172.27.102.12 |
illusive-get-forensics-triggering-process-info
Retrieve the triggering process information from Illusive’s forensics
Base Command
illusive-get-forensics-triggering-process-info
Input
| Argument Name | Description | Required |
|---|---|---|
| event_id | The event ID to retrieve the triggering process information from | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Illusive.Event.incidentId | Number | The corresponding incident ID |
| Illusive.Event.eventId | Number | The corresponding event ID |
| Illusive.Event.ForensicsTriggeringProcess.commandLine | String | The triggering process command line |
| Illusive.Event.ForensicsTriggeringProcess.connectionsNum | Number | The triggering process active connections |
| Illusive.Event.ForensicsTriggeringProcess.md5 | String | The triggering process md5 |
| Illusive.Event.ForensicsTriggeringProcess.sha256 | String | The triggering process sha256 |
| Illusive.Event.ForensicsTriggeringProcess.name | String | The triggering process name |
| Illusive.Event.ForensicsTriggeringProcess.parent | String | The parent process of the triggering process |
| Illusive.Event.ForensicsTriggeringProcess.path | String | The triggering process path |
| Illusive.Event.ForensicsTriggeringProcess.startTime | Date | The triggering process start time |
Command Example
!illusive-get-forensics-triggering-process-info event_id=5
Human Readable Output
Illusive Triggering Processes Info
| commandLine | connectionsNum | md5 | name | parent | path | sha256 | startTime |
|---|---|---|---|---|---|---|---|
| “C:\Program Files (x86)\Google\Chrome\Application\chrome.exe” –type=utility –field-trial-handle=1472,8764100348922490764,5250110531070070503,131072 –lang=en-US –service-sandbox-type=network –enable-audio-service-sandbox –mojo-platform-channel-handle=1900 /prefetch:8 | 15 | 9E46D108805A743D2D88D04019370A05 | chrome.exe | chrome.exe(7848) | C:\Program Files (x86)\Google\Chrome\Application\chrome.exe | D7771E5F5090EF37BE554D5DD9E1C24C8CD83EBF284C48CC5D1EF45D02C0E77F | 2020-06-29T09:16:47.245+00:00 |
illusive-get-forensics-artifacts
Retrieve forensics artifacts from Illusive’s forensics
Base Command
illusive-get-forensics-artifacts
Input
| Argument Name | Description | Required |
|---|---|---|
| event_id | The event ID to retrieve the forensics artifacts from | Required |
| artifact_type | The type of forensics artifact to retrieve | Required |
Context Output
There is no context output for this command.
Command Example
!illusive-get-forensics-artifacts event_id=2
Human Readable Output
event id 2 has no artifacts
Configuration parameters
url— Server URL (e.g. https://example.net) (required)api_token— API Token (required)isFetch— Fetch incidentsincidentType— Incident typeincidentFetchInterval— Incidents Fetch Intervalinsecure— Trust any certificate (not secure)proxy— Use system proxy settingsfetch_time— The initial time to fetch fromhas_forensics— Fetch only incidents with forensics
Commands (20)
-
illusive-add-deceptive-serversAdd or approve deceptive servers.
-
illusive-add-deceptive-usersAdd or approve deceptive users.
-
illusive-assign-host-to-policyAssign a deception policy to domain hosts.
-
illusive-delete-deceptive-serversDelete deceptive servers.
-
illusive-delete-deceptive-usersDelete deceptive users.
-
illusive-get-asm-cj-insightRetrieve Crown-Jewels insights from Attack Surface Manager.
-
illusive-get-asm-host-insightRetrieve the specified host insights from Attack Surface Manager.
-
illusive-get-deceptive-serversRetrieve a list of all deceptive servers.
-
illusive-get-deceptive-usersRetrieve a list of all deceptive users.
-
illusive-get-event-incident-idRetrieve the incident ID of an event.
-
illusive-get-forensics-analyzersRetrieve Illusive's forensics analyzers on a certain event.
-
illusive-get-forensics-artifactsRetrieve forensics artifacts from Illusive's forensics.
-
illusive-get-forensics-timelineRetrieve forensics timeline for a specific incident.
-
illusive-get-forensics-triggering-process-infoRetrieve the triggering process information from Illusive's forensics.
-
illusive-get-incident-eventsRetrieve all the events that are associated with an incident.
-
illusive-get-incidentsRetrieve incidents.
-
illusive-is-deceptive-serverRetrieve whether a specified server is deceptive.
-
illusive-is-deceptive-userRetrieve whether a specified user is deceptive.
-
illusive-remove-host-from-policyRemove deception policy assignment from domain hosts.
-
illusive-run-forensics-on-demandCollect forensics on a specified host and retrieve the forensics timeline.
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 import urllib3 from CommonServerUserPython import * # noqa: E402 lgtm [py/polluting-import] # IMPORTS from typing import Any import json import dateparser import zipfile import io # Disable insecure warnings urllib3.disable_warnings() # CONSTANTS DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.000Z" DEFAULT_HEADERS_POST_REQUEST = {"accept": "application/json;charset=UTF-8", "Content-Type": "application/json;charset=UTF-8"} class Client(BaseClient): """ Client will implement the service API, and should not contain any Demisto logic. Should only do requests and return data. """ def get_deceptive_users(self, user_type): url_suffix = f"/api/v1/deceptive-entities/users?deceptive_user_type={user_type}" return self._http_request("GET", url_suffix=url_suffix) def get_deceptive_serves(self, server_type): url_suffix = f"/api/v1/deceptive-entities/servers?deceptive_server_type={server_type}" return self._http_request("GET", url_suffix=url_suffix) def add_deceptive_users(self, body): url_suffix = "/api/v1/deceptive-entities/users" return self._http_request("POST", url_suffix=url_suffix, data=json.dumps(body), ok_codes=(200,)) def add_deceptive_servers(self, body): url_suffix = "/api/v1/deceptive-entities/servers" return self._http_request("POST", url_suffix=url_suffix, data=json.dumps(body), ok_codes=(200,)) def assign_host_to_policy(self, policy_name, body): url_suffix = f"/api/v1/policy/domain_hosts/assign?policy_name={policy_name}" return self._http_request("POST", url_suffix=url_suffix, data=json.dumps(body), ok_codes=(200,)) def remove_host_from_policy(self, body): url_suffix = "/api/v1/policy/domain_hosts/remove_assignment" return self._http_request("POST", url_suffix=url_suffix, data=json.dumps(body), ok_codes=(200,)) def get_forensics_timeline(self, incident_id, start_date, end_date): url_suffix = f"/api/v1/forensics/timeline?incident_id={incident_id}" if end_date: url_suffix += f"&end_date={end_date}" if start_date: url_suffix += f"&start_date={start_date}" return self._http_request("GET", url_suffix=url_suffix, ok_codes=(200,)) def get_asm_host_insight(self, hostname_or_ip): url_suffix = f"/api/v1/attack-surface/machine-insights?hostNameOrIp={hostname_or_ip}" return self._http_request("GET", url_suffix=url_suffix) def get_asm_cj_insight(self): url_suffix = "/api/v1/crownjewels/insights" return self._http_request("GET", url_suffix=url_suffix) def run_forensics_on_demand(self, hostname_or_ip): url_suffix = f"/api/v1/event/create-external-event?hostNameOrIp={hostname_or_ip}" return self._http_request("POST", url_suffix=url_suffix) def is_deceptive_user(self, username): url_suffix = f"/api/v1/deceptive-entities/user?userName={username}" return self._http_request("GET", url_suffix=url_suffix, resp_type="text") def is_deceptive_server(self, hostname): url_suffix = f"/api/v1/deceptive-entities/server?hostName={hostname}" return self._http_request("GET", url_suffix=url_suffix, resp_type="text") def delete_deceptive_users(self, deceptive_users): url_suffix = "/api/v1/deceptive-entities/users" url_suffix += "?deceptive_users=" + "&deceptive_users=".join(deceptive_users) return self._http_request("DELETE", url_suffix=url_suffix, resp_type="text") def delete_deceptive_servers(self, deceptive_servers): url_suffix = "/api/v1/deceptive-entities/servers" url_suffix += "?deceptive_hosts=" + "&deceptive_hosts=".join(deceptive_servers) return self._http_request("DELETE", url_suffix=url_suffix, resp_type="text") def get_incident(self, incident_id): url_suffix = f"/api/v2/incidents/incident?incident_id={incident_id}" return self._http_request("GET", url_suffix=url_suffix) def get_event_incident_id(self, event_id): url_suffix = f"/api/v1/incidents/id?event_id={event_id}" return self._http_request("GET", url_suffix=url_suffix, ok_codes=(200,)) def list_all_incidents(self, has_forensics, host_names, limit, offset, start_date): url_suffix = f"/api/v1/incidents?limit={limit}&offset={offset}" if has_forensics is not None: url_suffix += f"&has_forensics={has_forensics}" if start_date: url_suffix += f"&start_date={start_date}" if host_names: url_suffix += "&host_names=" + "&host_names=".join(host_names) return self._http_request("GET", url_suffix=url_suffix) def test_configuration(self): url_suffix = "/api/v1/incidents?limit=10&offset=0" return self._http_request("GET", url_suffix=url_suffix, ok_codes=(200,)) def get_incident_events(self, incident_id, limit, offset): url_suffix = f"/api/v1/incidents/events?incident_id={incident_id}&limit={limit}&offset={offset}" return self._http_request("GET", url_suffix=url_suffix) def get_forensics_artifacts(self, event_id, artifact_type): url_suffix = f"/api/v1/forensics/artifacts?event_id={event_id}&artifacts_type={artifact_type}" return self._http_request("GET", url_suffix=url_suffix, resp_type="content") def get_forensics_analyzers(self, event_id): url_suffix = f"/api/v1/forensics/analyzers?event_id={event_id}" return self._http_request("GET", url_suffix=url_suffix) def get_forensics_triggering_process_info(self, event_id): url_suffix = f"/api/v1/forensics/triggering_process_info?event_id={event_id}" return self._http_request("GET", url_suffix=url_suffix, ok_codes=(200,)) def test_module(client): """ Returning 'ok' indicates that the integration works like it is supposed to. Connection to the service is successful. Args: client: Illusive Networks client Returns: 'ok' if test passed, anything else will fail the test. """ try: client.test_configuration() return "ok" except DemistoException as e: if "401" in e.args[0]: return f"Test failed, potential reasons might be that the API KEY parameter is incorrect: {e.args[0]}" else: return f"Test failed: {e.args[0]}" def fetch_incidents(client, last_run, first_fetch_time, has_forensics): """ This function will execute each interval (default is 1 minute). """ # Get the last fetch time, if exists last_fetch = last_run.get("last_run") # Handle first time fetch if last_fetch is None: last_fetch, _ = parse_date_range(first_fetch_time, date_format=DATE_FORMAT, utc=True) latest_created_time = last_fetch incidents = [] items = client.list_all_incidents(has_forensics, None, limit=10, offset=0, start_date=latest_created_time) for item in items: incident_created_time = item["incidentTimeUTC"] incident_type = "None" if len(item["incidentTypes"]) > 0: incident_type = str(item["incidentTypes"][0]) incident_create_time_date = dateparser.parse(incident_created_time) assert incident_create_time_date is not None incident = { "name": "Illusive Attack Management detected an incident of type " + incident_type, "occurred": incident_create_time_date.strftime("%Y-%m-%dT%H:%M:%SZ"), "rawJSON": json.dumps(item), } incidents.append(incident) # Update last run and add incident if the incident is newer than last fetch if incident_created_time > latest_created_time: latest_created_time = incident_created_time next_run = {"last_run": latest_created_time} return next_run, incidents def get_deceptive_users_command(client: Client, args: dict) -> tuple: user_type = args.get("type", "ALL") try: result = client.get_deceptive_users(user_type) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") readable_output = tableToMarkdown("Illusive Deceptive Users", result) outputs = {"Illusive.DeceptiveUser(val.userName == obj.userName)": result} return ( readable_output, outputs, result, # raw response - the original response ) def get_deceptive_servers_command(client: Client, args: dict) -> tuple: server_type = args.get("type", "ALL") try: result = client.get_deceptive_serves(server_type) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") readable_output = tableToMarkdown("Illusive Deceptive Servers", result) outputs = {"Illusive.DeceptiveServer(val.host == obj.host)": result} return ( readable_output, outputs, result, # raw response - the original response ) def add_deceptive_users_command(client: Client, args: dict) -> tuple: user_name = args.get("username", None) domain_name = args.get("domain_name", None) password = args.get("password", None) policy_names = argToList(args.get("policy_names")) request_body = [{"domainName": domain_name, "password": password, "policyNames": policy_names, "username": user_name}] try: client.add_deceptive_users(request_body) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") result = { "userName": user_name, "domainName": domain_name, "policyNames": "All Policies" if policy_names == [] else policy_names, "password": password, } readable_output = tableToMarkdown("Illusive Add Deceptive User Succeeded", result) outputs = {"Illusive.DeceptiveUser(val.userName == obj.userName)": result} return ( readable_output, outputs, result, # raw response - the original response ) def add_deceptive_servers_command(client: Client, args: dict) -> tuple: host_name = args.get("host", "") # must be <host>.<domain> service_types = argToList(args.get("service_types")) policy_names = argToList(args.get("policy_names"), "All Policies") if len(host_name.split(".")) < 2: raise DemistoException("host name must have the following pattern: <host>.<domain>") request_body = [{"host": host_name, "serviceTypes": service_types, "policyNames": policy_names}] try: client.add_deceptive_servers(request_body) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") result = { "host": host_name, "serviceTypes": service_types, "policyNames": "All Policies" if policy_names == [] else policy_names, } readable_output = tableToMarkdown("Illusive Add Deceptive Server Succeeded", result) outputs = {"Illusive.DeceptiveServer(val.host == obj.host)": result} return ( readable_output, outputs, result, # raw response - the original response ) def assign_host_to_policy_command(client: Client, args: dict) -> tuple: policy_name = args.get("policy_name", None) host_names = argToList(args.get("hosts")) host_names = host_names[:1000] request_body = [] for host_name in host_names: host_name_split = host_name.split("@") if len(host_name_split) != 2: raise Exception(f"bad hostname format: {host_name}. Should be <machineName>@<domainName> ") request_body.append({"machineName": host_name_split[0], "domainName": host_name_split[1]}) try: client.assign_host_to_policy(policy_name, request_body) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") result = [] for host in host_names: result.append({"isAssigned": True, "hosts": host, "policy_name": policy_name}) readable_output = tableToMarkdown("Illusive Assign Machines to Policy Succeeded", result) outputs = {"Illusive.DeceptionPolicy.isAssigned(val.hosts == obj.hosts)": result} return ( readable_output, outputs, result, # raw response - the original response ) def remove_host_from_policy_command(client: Client, args: dict) -> tuple: host_names = argToList(args.get("hosts")) host_names = host_names[:1000] request_body = [] for host_name in host_names: host_name_split = host_name.split("@") if len(host_name_split) != 2: raise Exception(f"bad hostname format: {host_name}. Should be <machineName>@<domainName> ") request_body.append({"machineName": host_name_split[0], "domainName": host_name_split[1]}) try: client.remove_host_from_policy(request_body) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") result = [] for host in host_names: result.append({"isAssigned": False, "hosts": host, "policy_name": ""}) readable_output = tableToMarkdown("Illusive Remove Machines from All Policies Succeeded", result) outputs = {"Illusive.DeceptionPolicy.isAssigned(val.hosts == obj.hosts)": result} return ( readable_output, outputs, result, # raw response - the original response ) def get_forensics_timeline_command(client: Client, args: dict) -> tuple: incident_id = args.get("incident_id") start_date = args.get("start_date", None) end_date = args.get("end_date", None) if start_date: start_date, _ = parse_date_range(start_date, date_format=DATE_FORMAT, utc=True) if end_date: end_date, _ = parse_date_range(end_date, date_format=DATE_FORMAT, utc=True) try: result = client.get_forensics_timeline(incident_id, start_date, end_date) for evidence in result: evidence["date"] = evidence.get("details").get("date") readable_output = tableToMarkdown("Illusive Forensics Timeline", result) outputs = { "Illusive.Forensics(val.IncidentId == obj.IncidentId)": { "IncidentId": incident_id, "Status": "Done", "Evidence": result, } } except DemistoException as e: if "404" in e.args[0]: raise DemistoException(f"Incident id {incident_id} doesn't not exist") elif "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) elif "202" in e.args[0]: readable_output = f"Incident id {incident_id} hasn't been closed yet" outputs = { "Illusive.Forensics(val.IncidentId == obj.IncidentId)": { "IncidentId": incident_id, "Status": "InProgress", "Evidence": [], } } result = [] else: raise DemistoException(f"{e.args[0]}") return ( readable_output, outputs, result, # raw response - the original response ) def get_asm_host_insight_command(client: Client, args: dict) -> tuple: hostname_or_ip = args.get("hostnameOrIp", None) try: result = client.get_asm_host_insight(hostname_or_ip) except DemistoException as e: if "404" in e.args[0]: result = [] elif "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") readable_output = tableToMarkdown("Illusive ASM Host Insights", result) outputs = {"Illusive.AttackSurfaceInsightsHost(val.ipAddresses == obj.ipAddresses)": result} return ( readable_output, outputs, result, # raw response - the original response ) def get_asm_cj_insight_command(client: Client, args: dict) -> tuple: try: result = client.get_asm_cj_insight() except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") readable_output = tableToMarkdown("Illusive ASM Crown Jewels Insights", result) outputs = {"Illusive.AttackSurfaceInsightsCrownJewel(val.hostname == obj.hostname)": result} return ( readable_output, outputs, result, # raw response - the original response ) def run_forensics_on_demand_command(client: Client, args: dict) -> tuple: fqdn_or_ip = args.get("fqdn_or_ip", None) try: result = client.run_forensics_on_demand(fqdn_or_ip) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") readable_output = tableToMarkdown("Illusive Run Forensics On Demand", result) outputs = {"Illusive.Event(val.eventId == obj.eventId)": result} return ( readable_output, outputs, result, # raw response - the original response ) def is_deceptive_user_command(client: Client, args: dict) -> tuple: username = args.get("username", None) is_deceptive_user = False is_deceptive_user = True if client.is_deceptive_user(username) else is_deceptive_user result = {"Username": username, "IsDeceptiveUser": is_deceptive_user} readable_output = tableToMarkdown("Illusive Is Deceptive", result) outputs = {"Illusive.IsDeceptive(val.Username == obj.Username)": result} return ( readable_output, outputs, None, # raw response - the original response ) def is_deceptive_server_command(client: Client, args: dict) -> tuple: hostname = args.get("hostname", None) is_deceptive_server = False is_deceptive_server = True if client.is_deceptive_server(hostname) else is_deceptive_server result = {"Hostname": hostname, "IsDeceptiveServer": is_deceptive_server} readable_output = tableToMarkdown("Illusive Is Deceptive", result) outputs = {"Illusive.IsDeceptive(val.Hostname == obj.Hostname)": result} return ( readable_output, outputs, None, # raw response - the original response ) def delete_deceptive_users_command(client: Client, args: dict) -> tuple: deceptive_users = argToList(args.get("deceptive_users")) try: client.delete_deceptive_users(deceptive_users) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") if len(deceptive_users) > 1: a, b = "s", "were" else: a, b = "", "was" result = f' {f"Deceptive User{a} {deceptive_users} {b} successfully Deleted"}' readable_output = f"## {result}" outputs: dict[str, Any] = {} return ( readable_output, outputs, None, # raw response - the original response ) def delete_deceptive_servers_command(client: Client, args: dict) -> tuple: deceptive_servers = argToList(args.get("deceptive_hosts")) try: client.delete_deceptive_servers(deceptive_servers) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") if len(deceptive_servers) > 1: a, b = "s", "were" else: a, b = "", "was" result = f' {f"Deceptive Server{a} {deceptive_servers} {b} successfully Deleted"}' readable_output = f"## {result}" outputs: dict[str, Any] = {} return ( readable_output, outputs, None, # raw response - the original response ) def get_incidents_command(client: Client, args: dict) -> tuple: incident_id = args.get("incident_id") has_forensics = args.get("has_forensics", None) host_names = argToList(args.get("hostnames")) limit = args.get("limit", 10) offset = args.get("offset", 0) start_date = args.get("start_date", None) if start_date: start_date, _ = parse_date_range(start_date, date_format=DATE_FORMAT, utc=True) try: if incident_id: incident = client.get_incident(incident_id) else: limit = "100" if int(limit) > 100 else limit incident = client.list_all_incidents(has_forensics, host_names, limit, offset, start_date) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") readable_output = tableToMarkdown("Illusive Incidents", incident) outputs = {"Illusive.Incident(val.incidentId == obj.incidentId)": incident} return ( readable_output, outputs, incident, # raw response - the original response ) def get_event_incident_id_command(client: Client, args: dict) -> tuple: event_id = int(args.get("event_id", None)) status = "Done" try: incident = client.get_event_incident_id(event_id) except DemistoException as e: if "404" in e.args[0]: raise DemistoException(f"Event id {event_id} doesn't not exist") elif "202" in e.args[0]: incident = "-" status = "InProgress" elif "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") result = [{"eventId": event_id, "incidentId": incident, "status": status}] outputs = {"Illusive.Event(val.eventId == obj.eventId)": result} readable_output = tableToMarkdown("Illusive Get Incident", result) return ( readable_output, outputs, None, # raw response - the original response ) def get_incident_events_command(client: Client, args: dict) -> tuple: incident_id = args.get("incident_id", 0) limit = args.get("limit", 100) limit = "1000" if int(limit) > 1000 else limit offset = args.get("offset", 0) try: events = client.get_incident_events(incident_id, limit, offset) except DemistoException as e: if "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") readable_output = tableToMarkdown("Illusive get incident's events", events, metadata=f"Number of events {len(events)}") outputs = { "Illusive.Incident(val.incidentId == obj.incidentId)": { "eventsNumber": len(events), "incidentId": int(incident_id), "Event": events, } } return ( readable_output, outputs, events, # raw response - the original response ) def get_forensics_analyzers_command(client: Client, args: dict) -> tuple: event_id = args.get("event_id", 0) try: analyzers = client.get_forensics_analyzers(event_id) incident = client.get_event_incident_id(event_id) except DemistoException as e: if "404" in e.args[0]: raise DemistoException(f"Event id {event_id} doesn't not exist") elif "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") outputs = { "Illusive.Event(val.eventId == obj.eventId)": { "eventId": int(event_id), "incidentId": int(incident), "ForensicsAnalyzers": analyzers, } } readable_output = tableToMarkdown("Illusive Forensics Analyzers", analyzers) return ( readable_output, outputs, incident, # raw response - the original response ) def get_forensics_triggering_process_info_command(client: Client, args: dict) -> tuple: event_id = args.get("event_id") try: processes = client.get_forensics_triggering_process_info(event_id) except DemistoException as e: if "404" in e.args[0]: raise DemistoException(f"failed to get forensics for Event id {event_id}") elif "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") readable_output = tableToMarkdown("Illusive Triggering Processes Info", processes.get("processes")) outputs = { "Illusive.Event(val.eventId == obj.eventId)": { "eventId": event_id, "ForensicsTriggeringProcess": processes.get("processes"), } } return ( readable_output, outputs, readable_output, # raw response - the original response ) def get_forensics_artifacts_command(client: Client, args: dict) -> tuple: event_id = args.get("event_id") artifact_type = args.get("artifact_type", "DESKTOP_SCREENSHOT") try: client.get_event_incident_id(event_id) # this request is for checking the event exists artifact = client.get_forensics_artifacts(event_id, artifact_type) except DemistoException as e: if "404" in e.args[0]: raise DemistoException(f"failed to get forensics for Event id {event_id}") elif "429" in e.args[0]: raise DemistoException( "The allowed amount of API calls per minute in Illusive Attack Management has exceeded. In case this" " message repeats, please contact Illusive Networks support" ) else: raise DemistoException(f"{e.args[0]}") if len(artifact) == 0: return [], [] zip_file = zipfile.ZipFile(io.BytesIO(artifact)) file_results = [] file_names = [] i = 0 for info in zip_file.infolist(): i = i + 1 file_results.append( fileResult( filename=f"eventId_{event_id}_{artifact_type}_{i}.jpg", data=zip_file.read(info.filename), file_type=entryTypes["image"], ) ) file_names.append(f"eventId_{event_id}_{artifact_type}_{i}.jpg") return file_results, file_names def link_forensics_artifacts_name_command(file_names, client: Client, args: dict) -> CommandResults: event_id = args.get("event_id", 0) if len(file_names) > 0: outputs = {"eventId": int(event_id), "Artifacts": file_names} return CommandResults(outputs_prefix="Illusive.Event", outputs_key_field="eventId", outputs=outputs) else: readable_output = f"### event id {event_id} has no artifacts" return CommandResults( readable_output=readable_output, outputs_prefix="Illusive.Event", outputs_key_field="eventId", outputs={"eventId": int(event_id)}, ) def main(): """ PARSE AND VALIDATE INTEGRATION PARAMS """ # get the service API token api_token = demisto.params().get("api_token") has_forensics = demisto.params().get("has_forensics") has_forensics = None if has_forensics == "ALL" else has_forensics # get the service API url base_url = demisto.params()["url"] verify_certificate = not demisto.params().get("insecure", False) # How much time before the first fetch to retrieve incidents first_fetch_time = demisto.params().get("fetch_time", "7 days").strip().lower() proxy = demisto.params().get("proxy", False) LOG(f"Command being called is {demisto.command()}") try: headers = DEFAULT_HEADERS_POST_REQUEST headers["Authorization"] = api_token client = Client(base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy) if demisto.command() == "test-module": # This is the call made when pressing the integration Test button. result = test_module(client) demisto.results(result) elif demisto.command() == "fetch-incidents": # Set and define the fetch incidents command to run after activated via integration settings. next_run, incidents = fetch_incidents( client=client, last_run=demisto.getLastRun(), first_fetch_time=first_fetch_time, has_forensics=has_forensics ) demisto.setLastRun(next_run) demisto.incidents(incidents) elif demisto.command() == "illusive-get-forensics-timeline": return_outputs(*get_forensics_timeline_command(client, demisto.args())) elif demisto.command() == "illusive-get-asm-host-insight": return_outputs(*get_asm_host_insight_command(client, demisto.args())) elif demisto.command() == "illusive-get-asm-cj-insight": return_outputs(*get_asm_cj_insight_command(client, demisto.args())) elif demisto.command() == "illusive-get-deceptive-users": return_outputs(*get_deceptive_users_command(client, demisto.args())) elif demisto.command() == "illusive-get-deceptive-servers": return_outputs(*get_deceptive_servers_command(client, demisto.args())) elif demisto.command() == "illusive-is-deceptive-user": return_outputs(*is_deceptive_user_command(client, demisto.args())) elif demisto.command() == "illusive-is-deceptive-server": return_outputs(*is_deceptive_server_command(client, demisto.args())) elif demisto.command() == "illusive-get-incidents": return_outputs(*get_incidents_command(client, demisto.args())) elif demisto.command() == "illusive-get-event-incident-id": return_outputs(*get_event_incident_id_command(client, demisto.args())) elif demisto.command() == "illusive-add-deceptive-users": return_outputs(*add_deceptive_users_command(client, demisto.args())) elif demisto.command() == "illusive-add-deceptive-servers": return_outputs(*add_deceptive_servers_command(client, demisto.args())) elif demisto.command() == "illusive-delete-deceptive-users": return_outputs(*delete_deceptive_users_command(client, demisto.args())) elif demisto.command() == "illusive-delete-deceptive-servers": return_outputs(*delete_deceptive_servers_command(client, demisto.args())) elif demisto.command() == "illusive-assign-host-to-policy": return_outputs(*assign_host_to_policy_command(client, demisto.args())) elif demisto.command() == "illusive-remove-host-from-policy": return_outputs(*remove_host_from_policy_command(client, demisto.args())) elif demisto.command() == "illusive-run-forensics-on-demand": return_outputs(*run_forensics_on_demand_command(client, demisto.args())) elif demisto.command() == "illusive-get-forensics-artifacts": try: file_results, file_names = get_forensics_artifacts_command(client, demisto.args()) return_results(file_results) return_results(link_forensics_artifacts_name_command(file_names, client, demisto.args())) except ValueError: return_results(link_forensics_artifacts_name_command([], client, demisto.args())) elif demisto.command() == "illusive-get-forensics-triggering-process-info": return_outputs(*get_forensics_triggering_process_info_command(client, demisto.args())) elif demisto.command() == "illusive-get-forensics-analyzers": return_outputs(*get_forensics_analyzers_command(client, demisto.args())) elif demisto.command() == "illusive-get-incident-events": return_outputs(*get_incident_events_command(client, demisto.args())) # Log exceptions except Exception as e: return_error(f"Failed to execute {demisto.command()} command. Error: {str(e)}") if __name__ in ("__main__", "__builtin__", "builtins"): main()