Cymulate

Multi-Vector Cyber Attack, Breach and Attack Simulation.

Deception & Breach Simulation · Cymulate

Details

IDCymulate
ProviderCymulate
CategoryDeception & Breach Simulation
From Version5.0.0
Docker Imagedemisto/python3:3.12.8.3296088
Supported ModulesAgentix XSIAM

README

Configure Cymulate on Cortex XSOAR


  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for Cymulate.
  3. Click Add instance to create and configure a new integration instance.
    • Name: a textual name for the integration instance.
    • X-token
    • Fetch incidents
    • Incident type
    • Show only ‘penatrated’ incidents
  4. Click Test to validate the URLs, token, and connection.

Fetched Incidents Data


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.

  1. cymulate_get_incident_info

1. cymulate_get_incident_info


This commands return full cymulate’s incidents information

Base Command

cymulate_get_incident_info

Input
Argument Name Description Required
attack_id The attack unique identifier Required
incident_id The incident unique identifier Required
module_type The Cymulate module_type Required
Context Output
Path Type Description
Cymulate.Incident.Payload String The Cymulatepayload that generated this incident
Cymulate.Incident.Name String The name of the incident
Cymulate.Incident.Status String The attack status
Cymulate.Incident.Attack_Type String The incident Attack_Type
Cymulate.Incident.Attack_Vector String The incident ID
Cymulate.Incident.Timestamp String The incident ID
Cymulate.Incident.Attack_Payload String The incident ID
Cymulate.Incident.Md5 String The incident ID
Cymulate.Incident.Mitigation String The incident ID
Cymulate.Incident.Module String The incident ID
Cymulate.Incident.Penetration_Vector String The incident ID
Cymulate.Incident.Sha1 String The incident ID
Cymulate.Incident.Sha256 String The incident ID
Command Example

!cymulate_get_incident_info attack_id="5e71e8cc7df91d6b4d460943" incident_id="9bc6591182ca40f3a3bfb3b46e3be025" module_type="IMMEDIATE_THREATS"

Context Example
{
    "data": [
        {
            "Attack_Type": "Antivirus",
            "Status": "Penetrated",
            "Sha1": "18e4feb988cb95d71d81e1964aa6280e22361b9f",
            "Description": "New malware created by Chinese-backed Winnti Group has been discovered by researchers at ESET while being used to gain persistence on Microsoft SQL Server (MSSQL) systems.\r\n\r\nThe new malicious tool dubbed skip-2.0 can be used by the attackers to backdoor MSSQL Server 11 and 12 servers, enabling them to connect to any account on the server using a so-called \"magic password\" and hide their activity from the security logs.\r\n\r\nThis backdoor allows the attacker not only to gain persistence in the victim's MSSQL Server through the use of a special password, but also to remain undetected thanks to the multiple log and event publishing mechanisms that are disabled when that password is used.\r\n\r\nThe Winnti Group is an umbrella term used as the name of a collective of Chinese state-backed hacking groups (tracked as Blackfly and Suckfly by Symantec, Wicked Panda by CrowdStrike, BARIUM by Microsoft, APT41 by FireEye) sharing the same malicious tools that have been in use since around 2011.\r\n\r\nThat is when Kaspersky found the hackers' Winnti Trojan on a large number of compromised gaming systems after it got delivered via a game's official update server.\r\n\r\nThe new backdoor, skip-2.0 shares some traits with other Winnti Group malware, in particular, with the PortReuse and ShadowPad backdoors.\r\n\r\nPortReuse, a modular Windows backdoor, was used by the Winnti hackers in an attack targeting the servers of a high-profile Asian mobile software and hardware manufacturer.\r\n\r\nAlso, PortReuse is a network implant that injects itself into a process that is already listening on a network port and waits for an incoming magic packet to trigger the malicious code.\r\n\r\nShadowPad is another Winnti backdoor used by the group as part of a supply chain attack from 2017 that impacted NetSarang, a Soth Korean maker of network connectivity solutions, when the hacking group successfully infected the company's server management software with the backdoor.\r\n\r\nAll three backdoors use the same VMProtected launcher and the group's custom malware packer and, to top it all off, also share multiple other similarities with several other tools associated with the threat group's past operations.\r\n\r\nOnce dropped on an already compromised MSSQL server, the skip-2.0 backdoor proceeds to inject its malicious code within the sqlserv.exe process via the sqllang.dll, hooking multiple functions used for logging an authentication.\r\n\r\nThis allows the malware to bypass the server's built-in authentication mechanism and thus allow its operators to log in even though the account password they entered does not match.\r\n\r\nThis function's hook checks whether the password provided by the user matches the magic password, in that case, the original function will not be called and the hook will return 0, allowing the connection even though the correct password was not provided.\r\n\r\nSkip-2.0 was tested against multiple MSSQL Server versions and found that log in successfully using the special password only with MSSQL Server 11 and 12 was possible.\r\n\r\nWhile MSSQL Server 11 and 12 are not the most recently released versions - they were released in 2012 and 2014 - and they are the most common ones.\r\n\r\nThe skip-2.0 backdoor is an interesting addition to the Winnti Group's arsenal, sharing a great deal of similarities with the group's already known toolset, and allowing the attacker to achieve persistence on an MSSQL Server.\r\n\r\nConsidering that administrative privileges are required for installing the hooks, skip-2.0 must be used on already compromised MSSQL Servers to achieve persistence and stealthiness.",
            "Penetration_Vector": "Dll",
            "Timestamp": "25/12/2019 15:03:15",
            "Related_URLS": "N/A",
            "Attack_Payload": "Skip1Dll.dll",
            "Module": "Immediate Threats Intelligence",
            "Attack_Vector": "Endpoint Security",
            "Mitigation": "Verify that your AV, EPP, EDR, Email Gateway, Web Gateway are up to date.\r\nSearch for malicious traffic using your SIEM based on the IOC's provided.\r\nWhere applicable, block the relevant hashes.",
            "Related_Email_Addresses": "N/A",
            "Name": "Chinese Hackers Use New Malware to Backdoor Microsoft SQL Servers",
            "Sha256": "095785392b61011a861d1106d7e9bb9f34b86877c0fb075d05cca224132238cb",
            "ID": "cd61447e5fc76ebd2a35de651f211ff9",
            "Md5": "30d9ac12711d52a34f87cfa5cea0c85a"
        },
        {
            "Attack_Type": "Antivirus",
            "Status": "Penetrated",
            "Sha1": "4af89296a15c1ea9068a279e05cc4a41b967c956",
            "Description": "New malware created by Chinese-backed Winnti Group has been discovered by researchers at ESET while being used to gain persistence on Microsoft SQL Server (MSSQL) systems.\r\n\r\nThe new malicious tool dubbed skip-2.0 can be used by the attackers to backdoor MSSQL Server 11 and 12 servers, enabling them to connect to any account on the server using a so-called \"magic password\" and hide their activity from the security logs.\r\n\r\nThis backdoor allows the attacker not only to gain persistence in the victim's MSSQL Server through the use of a special password, but also to remain undetected thanks to the multiple log and event publishing mechanisms that are disabled when that password is used.\r\n\r\nThe Winnti Group is an umbrella term used as the name of a collective of Chinese state-backed hacking groups (tracked as Blackfly and Suckfly by Symantec, Wicked Panda by CrowdStrike, BARIUM by Microsoft, APT41 by FireEye) sharing the same malicious tools that have been in use since around 2011.\r\n\r\nThat is when Kaspersky found the hackers' Winnti Trojan on a large number of compromised gaming systems after it got delivered via a game's official update server.\r\n\r\nThe new backdoor, skip-2.0 shares some traits with other Winnti Group malware, in particular, with the PortReuse and ShadowPad backdoors.\r\n\r\nPortReuse, a modular Windows backdoor, was used by the Winnti hackers in an attack targeting the servers of a high-profile Asian mobile software and hardware manufacturer.\r\n\r\nAlso, PortReuse is a network implant that injects itself into a process that is already listening on a network port and waits for an incoming magic packet to trigger the malicious code.\r\n\r\nShadowPad is another Winnti backdoor used by the group as part of a supply chain attack from 2017 that impacted NetSarang, a Soth Korean maker of network connectivity solutions, when the hacking group successfully infected the company's server management software with the backdoor.\r\n\r\nAll three backdoors use the same VMProtected launcher and the group's custom malware packer and, to top it all off, also share multiple other similarities with several other tools associated with the threat group's past operations.\r\n\r\nOnce dropped on an already compromised MSSQL server, the skip-2.0 backdoor proceeds to inject its malicious code within the sqlserv.exe process via the sqllang.dll, hooking multiple functions used for logging an authentication.\r\n\r\nThis allows the malware to bypass the server's built-in authentication mechanism and thus allow its operators to log in even though the account password they entered does not match.\r\n\r\nThis function's hook checks whether the password provided by the user matches the magic password, in that case, the original function will not be called and the hook will return 0, allowing the connection even though the correct password was not provided.\r\n\r\nSkip-2.0 was tested against multiple MSSQL Server versions and found that log in successfully using the special password only with MSSQL Server 11 and 12 was possible.\r\n\r\nWhile MSSQL Server 11 and 12 are not the most recently released versions - they were released in 2012 and 2014 - and they are the most common ones.\r\n\r\nThe skip-2.0 backdoor is an interesting addition to the Winnti Group's arsenal, sharing a great deal of similarities with the group's already known toolset, and allowing the attacker to achieve persistence on an MSSQL Server.\r\n\r\nConsidering that administrative privileges are required for installing the hooks, skip-2.0 must be used on already compromised MSSQL Servers to achieve persistence and stealthiness.",
            "Penetration_Vector": "Dll",
            "Timestamp": "25/12/2019 15:03:14",
            "Related_URLS": "N/A",
            "Attack_Payload": "Skip2Dll.dll",
            "Module": "Immediate Threats Intelligence",
            "Attack_Vector": "Endpoint Security",
            "Mitigation": "Verify that your AV, EPP, EDR, Email Gateway, Web Gateway are up to date.\r\nSearch for malicious traffic using your SIEM based on the IOC's provided.\r\nWhere applicable, block the relevant hashes.",
            "Related_Email_Addresses": "N/A",
            "Name": "Chinese Hackers Use New Malware to Backdoor Microsoft SQL Servers",
            "Sha256": "2518457b6a4812af5084f1f8a3025df5ce3ca3b7721c08c628cab1af415b0c99",
            "ID": "1595f452a74e5743fae63c8063eed9e6",
            "Md5": "64bba3f138d4956cfed166835ed8168f"
        },
        {
            "Attack_Type": "Files",
            "Status": "Penetrated",
            "Sha1": "18e4feb988cb95d71d81e1964aa6280e22361b9f",
            "Description": "New malware created by Chinese-backed Winnti Group has been discovered by researchers at ESET while being used to gain persistence on Microsoft SQL Server (MSSQL) systems.\r\n\r\nThe new malicious tool dubbed skip-2.0 can be used by the attackers to backdoor MSSQL Server 11 and 12 servers, enabling them to connect to any account on the server using a so-called \"magic password\" and hide their activity from the security logs.\r\n\r\nThis backdoor allows the attacker not only to gain persistence in the victim's MSSQL Server through the use of a special password, but also to remain undetected thanks to the multiple log and event publishing mechanisms that are disabled when that password is used.\r\n\r\nThe Winnti Group is an umbrella term used as the name of a collective of Chinese state-backed hacking groups (tracked as Blackfly and Suckfly by Symantec, Wicked Panda by CrowdStrike, BARIUM by Microsoft, APT41 by FireEye) sharing the same malicious tools that have been in use since around 2011.\r\n\r\nThat is when Kaspersky found the hackers' Winnti Trojan on a large number of compromised gaming systems after it got delivered via a game's official update server.\r\n\r\nThe new backdoor, skip-2.0 shares some traits with other Winnti Group malware, in particular, with the PortReuse and ShadowPad backdoors.\r\n\r\nPortReuse, a modular Windows backdoor, was used by the Winnti hackers in an attack targeting the servers of a high-profile Asian mobile software and hardware manufacturer.\r\n\r\nAlso, PortReuse is a network implant that injects itself into a process that is already listening on a network port and waits for an incoming magic packet to trigger the malicious code.\r\n\r\nShadowPad is another Winnti backdoor used by the group as part of a supply chain attack from 2017 that impacted NetSarang, a Soth Korean maker of network connectivity solutions, when the hacking group successfully infected the company's server management software with the backdoor.\r\n\r\nAll three backdoors use the same VMProtected launcher and the group's custom malware packer and, to top it all off, also share multiple other similarities with several other tools associated with the threat group's past operations.\r\n\r\nOnce dropped on an already compromised MSSQL server, the skip-2.0 backdoor proceeds to inject its malicious code within the sqlserv.exe process via the sqllang.dll, hooking multiple functions used for logging an authentication.\r\n\r\nThis allows the malware to bypass the server's built-in authentication mechanism and thus allow its operators to log in even though the account password they entered does not match.\r\n\r\nThis function's hook checks whether the password provided by the user matches the magic password, in that case, the original function will not be called and the hook will return 0, allowing the connection even though the correct password was not provided.\r\n\r\nSkip-2.0 was tested against multiple MSSQL Server versions and found that log in successfully using the special password only with MSSQL Server 11 and 12 was possible.\r\n\r\nWhile MSSQL Server 11 and 12 are not the most recently released versions - they were released in 2012 and 2014 - and they are the most common ones.\r\n\r\nThe skip-2.0 backdoor is an interesting addition to the Winnti Group's arsenal, sharing a great deal of similarities with the group's already known toolset, and allowing the attacker to achieve persistence on an MSSQL Server.\r\n\r\nConsidering that administrative privileges are required for installing the hooks, skip-2.0 must be used on already compromised MSSQL Servers to achieve persistence and stealthiness.",
            "Penetration_Vector": "",
            "Timestamp": "25/12/2019 15:01:29",
            "Related_URLS": "N/A",
            "Attack_Payload": "https://cym-files-download.s3.eu-west-1.amazonaws.com/hotfiles/manual_upload/chinesehackersusenewmalwaretobackdoormicrosoftsqlservers/Skip1Dll.dll?AWSAccessKeyId=AKIAJPJC2Q3D5GWFTK3Q&Expires=1577278973&Signature=0MA9Dw9GHPbOdlHhivQ7U5oKLGA%3D",
            "Module": "Immediate Threats Intelligence",
            "Attack_Vector": "Web Gateway",
            "Mitigation": "Verify that your AV, EPP, EDR, Email Gateway, Web Gateway are up to date.\r\nSearch for malicious traffic using your SIEM based on the IOC's provided.\r\nWhere applicable, block the relevant hashes.",
            "Related_Email_Addresses": "N/A",
            "Name": "Chinese Hackers Use New Malware to Backdoor Microsoft SQL Servers",
            "Sha256": "095785392b61011a861d1106d7e9bb9f34b86877c0fb075d05cca224132238cb",
            "ID": "dc2a1e9b835b5caf685960bb7d9bdfea",
            "Md5": "30d9ac12711d52a34f87cfa5cea0c85a"
        },
        {
            "Attack_Type": "Files",
            "Status": "Penetrated",
            "Sha1": "4af89296a15c1ea9068a279e05cc4a41b967c956",
            "Description": "New malware created by Chinese-backed Winnti Group has been discovered by researchers at ESET while being used to gain persistence on Microsoft SQL Server (MSSQL) systems.\r\n\r\nThe new malicious tool dubbed skip-2.0 can be used by the attackers to backdoor MSSQL Server 11 and 12 servers, enabling them to connect to any account on the server using a so-called \"magic password\" and hide their activity from the security logs.\r\n\r\nThis backdoor allows the attacker not only to gain persistence in the victim's MSSQL Server through the use of a special password, but also to remain undetected thanks to the multiple log and event publishing mechanisms that are disabled when that password is used.\r\n\r\nThe Winnti Group is an umbrella term used as the name of a collective of Chinese state-backed hacking groups (tracked as Blackfly and Suckfly by Symantec, Wicked Panda by CrowdStrike, BARIUM by Microsoft, APT41 by FireEye) sharing the same malicious tools that have been in use since around 2011.\r\n\r\nThat is when Kaspersky found the hackers' Winnti Trojan on a large number of compromised gaming systems after it got delivered via a game's official update server.\r\n\r\nThe new backdoor, skip-2.0 shares some traits with other Winnti Group malware, in particular, with the PortReuse and ShadowPad backdoors.\r\n\r\nPortReuse, a modular Windows backdoor, was used by the Winnti hackers in an attack targeting the servers of a high-profile Asian mobile software and hardware manufacturer.\r\n\r\nAlso, PortReuse is a network implant that injects itself into a process that is already listening on a network port and waits for an incoming magic packet to trigger the malicious code.\r\n\r\nShadowPad is another Winnti backdoor used by the group as part of a supply chain attack from 2017 that impacted NetSarang, a Soth Korean maker of network connectivity solutions, when the hacking group successfully infected the company's server management software with the backdoor.\r\n\r\nAll three backdoors use the same VMProtected launcher and the group's custom malware packer and, to top it all off, also share multiple other similarities with several other tools associated with the threat group's past operations.\r\n\r\nOnce dropped on an already compromised MSSQL server, the skip-2.0 backdoor proceeds to inject its malicious code within the sqlserv.exe process via the sqllang.dll, hooking multiple functions used for logging an authentication.\r\n\r\nThis allows the malware to bypass the server's built-in authentication mechanism and thus allow its operators to log in even though the account password they entered does not match.\r\n\r\nThis function's hook checks whether the password provided by the user matches the magic password, in that case, the original function will not be called and the hook will return 0, allowing the connection even though the correct password was not provided.\r\n\r\nSkip-2.0 was tested against multiple MSSQL Server versions and found that log in successfully using the special password only with MSSQL Server 11 and 12 was possible.\r\n\r\nWhile MSSQL Server 11 and 12 are not the most recently released versions - they were released in 2012 and 2014 - and they are the most common ones.\r\n\r\nThe skip-2.0 backdoor is an interesting addition to the Winnti Group's arsenal, sharing a great deal of similarities with the group's already known toolset, and allowing the attacker to achieve persistence on an MSSQL Server.\r\n\r\nConsidering that administrative privileges are required for installing the hooks, skip-2.0 must be used on already compromised MSSQL Servers to achieve persistence and stealthiness.",
            "Penetration_Vector": "",
            "Timestamp": "25/12/2019 15:01:29",
            "Related_URLS": "N/A",
            "Attack_Payload": "https://cym-files-download.s3.eu-west-1.amazonaws.com/hotfiles/manual_upload/chinesehackersusenewmalwaretobackdoormicrosoftsqlservers/Skip2Dll.dll?AWSAccessKeyId=AKIAJPJC2Q3D5GWFTK3Q&Expires=1577278969&Signature=s9U7QyaNvF%2Fpul0C6bkWc1srCsQ%3D",
            "Module": "Immediate Threats Intelligence",
            "Attack_Vector": "Web Gateway",
            "Mitigation": "Verify that your AV, EPP, EDR, Email Gateway, Web Gateway are up to date.\r\nSearch for malicious traffic using your SIEM based on the IOC's provided.\r\nWhere applicable, block the relevant hashes.",
            "Related_Email_Addresses": "N/A",
            "Name": "Chinese Hackers Use New Malware to Backdoor Microsoft SQL Servers",
            "Sha256": "2518457b6a4812af5084f1f8a3025df5ce3ca3b7721c08c628cab1af415b0c99",
            "ID": "b2aa30c32e06762d09bac485d7c490a5",
            "Md5": "64bba3f138d4956cfed166835ed8168f"
        }
    ]
}
Human Readable Output

Cymulate Resutls

ID Name Status Attack Type Attack Vector Timestamp
cd61447e5fc76ebd2a35de651f211ff9 Chinese Hackers Use New Malware to Backdoor Microsoft SQL Servers Penetrated Antivirus Endpoint Security 25/12/2019 15:03:15
1595f452a74e5743fae63c8063eed9e6 Chinese Hackers Use New Malware to Backdoor Microsoft SQL Servers Penetrated Antivirus Endpoint Security 25/12/2019 15:03:14
dc2a1e9b835b5caf685960bb7d9bdfea Chinese Hackers Use New Malware to Backdoor Microsoft SQL Servers Penetrated Files Web Gateway 25/12/2019 15:01:29
b2aa30c32e06762d09bac485d7c490a5 Chinese Hackers Use New Malware to Backdoor Microsoft SQL Servers Penetrated Files Web Gateway 25/12/2019 15:01:29

cymulate-get-incident-info


This commands return full cymulate’s incidents information

Base Command

cymulate-get-incident-info

Input

Argument Name Description Required
attack_id The attack unique identifier. Required
module_type The Cymulate module_type. Required
incident_id The incident unique identifier. Optional

Context Output

Path Type Description
Cymulate.Incident.Payload String The Cymulate payload that generated this incident
Cymulate.Incident.Name String The name of the incident
Cymulate.Incident.Status String The attack status (Enum Values- Penetrated, Blocked, Dead)
Cymulate.Incident.ID String The incident ID
Cymulate.Incident.Md5 String The Md5
Cymulate.Incident.Attack_Vector String The Attack Vector
Cymulate.Incident.Sha256 String The Sha256
Cymulate.Incident.Sha1 String The Sha1
Cymulate.Incident.Cymulate_ID String The cymulate’s ID of the incident
Cymulate.Incident.Attack_ID String The cymulate’s Attack ID of the incident

Configuration parameters

  • x-token — X-token (required)
  • isFetch — Fetch incidents
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • onlyPenatrated — Show only 'penatrated' incidents
  • useProxy — Use server proxy
  • insecure — Trust any certificate (not secure)
  • fetch_time — First fetch time range (<number> <time unit>, e.g., 1 hour, 30 minutes) - Proofpoint supports maximum 1 hour fetch back

Commands (1)

  • cymulate-get-incident-info

    This commands return full cymulate's incidents information.

from CommonServerPython import *

""" IMPORTS """
import enum
from datetime import datetime, timedelta

import dateparser
import urllib3

# disable insecure warnings
urllib3.disable_warnings()

""" CONSTANTS """
DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
BASE_URL = "https://api.cymulate.com/v1/"
DEFAULT_LIMIT = 20

""" Helper functions """


def get_now():
    """A wrapper function of datetime.now
    helps handle tests

    Returns:
        datetime: time right now
    """
    return datetime.now()


def ts_add_minutes(ts, minutes):
    return (datetime.strptime(ts, DATE_FORMAT) + timedelta(minutes=minutes)).strftime(DATE_FORMAT)


class CymulateModuleTypeEnum(enum.Enum):
    """
    Enum class of module types of cymulate attacks
    """

    APT = ("1",)
    IMMEDIATE_THREATS = ("2",)
    HOPPER = ("3",)
    PHISHING = ("4",)
    WAF = ("5",)
    DLP = ("6",)
    BROWSING = ("7",)
    EDR = ("8",)
    MITRE = ("9",)
    MAIL = "10"

    def __str__(self):
        return str(self.name)


class Client(BaseClient):
    """
    Client will implement the service API, and should not contain any Demisto logic.
    Should only do requests and return data.
    """

    def general_api_query(self, route):
        """
        initiates a general cymulate api http request
        """
        data = self._http_request(method="GET", verify=False, url_suffix=route)

        return data.get("result")

    def test_api(self):
        """
        send a test call to api
        """

        results = self._http_request(method="GET", url_suffix="user/modules")

        return results

    def get_attack_info(self, module_type, from_date):
        """Get Threats Results ID's by Module Type.
        Args:
            module_type (CymulateModuleTypeEnum): module_type enum
            from_date (dateparser.time): the time which retrieve incidents greater than, if it's None - return all

        Returns:
            JSON - https results struct of { 'success' : true/false, 'data' : [{'Id' : '', 'Name' : '',
            'Timestamp : '', 'InProgress: ''}...] }
        """

        get_ids_route = ""

        if module_type == CymulateModuleTypeEnum.APT:
            get_ids_route = "apt/ids"
        elif module_type == CymulateModuleTypeEnum.IMMEDIATE_THREATS:
            get_ids_route = "immediate-threats/ids"
        elif module_type == CymulateModuleTypeEnum.HOPPER:
            get_ids_route = "hopper/ids"
        elif module_type == CymulateModuleTypeEnum.PHISHING:
            get_ids_route = "phishing/ids"
        elif module_type == CymulateModuleTypeEnum.WAF:
            get_ids_route = "waf/ids"
        elif module_type == CymulateModuleTypeEnum.DLP:
            get_ids_route = "dlp/ids"
        elif module_type == CymulateModuleTypeEnum.BROWSING:
            get_ids_route = "browsing/ids"
        elif module_type == CymulateModuleTypeEnum.EDR:
            get_ids_route = "edr/ids"
        elif module_type == CymulateModuleTypeEnum.MITRE:
            get_ids_route = "mitre/ids"
        elif module_type == CymulateModuleTypeEnum.MAIL:
            get_ids_route = "mail/ids"

        demisto.debug(f"url of get ids: {get_ids_route}?from={from_date}")

        results = self._http_request(method="GET", url_suffix=get_ids_route, params={"from": from_date})

        return results["data"]

    def get_attack_technical_info(self, module_type, incident_id):
        """Get technical Data about incident.
        Args:
            module_type (CymulateModuleTypeEnum): module_type enum
            incident_id (string): The incident id

        Returns:
            JSON - https results struct of { 'success' : true/false, 'data' : [{'Id' : '', 'Name' : '',
            'Timestamp : '', 'InProgress: ''}...] }
        """

        technical_route = ""

        if module_type == CymulateModuleTypeEnum.APT:
            technical_route = "apt/attack/technical"
        elif module_type == CymulateModuleTypeEnum.IMMEDIATE_THREATS:
            technical_route = "immediate-threats/attack/technical"
        elif module_type == CymulateModuleTypeEnum.HOPPER:
            technical_route = "hopper/attack/technical"
        elif module_type == CymulateModuleTypeEnum.PHISHING:
            technical_route = "phishing/attack/technical"
        elif module_type == CymulateModuleTypeEnum.WAF:
            technical_route = "waf/attack/technical"
        elif module_type == CymulateModuleTypeEnum.DLP:
            technical_route = "dlp/attack/technical"
        elif module_type == CymulateModuleTypeEnum.BROWSING:
            technical_route = "browsing/attack/technical"
        elif module_type == CymulateModuleTypeEnum.EDR:
            technical_route = "edr/attack/technical"
        elif module_type == CymulateModuleTypeEnum.MITRE:
            technical_route = "mitre/attack/technical"
        elif module_type == CymulateModuleTypeEnum.MAIL:
            technical_route = "mail/attack/technical"

        results = self._http_request(
            method="GET",
            url_suffix=technical_route + "/" + incident_id,
        )

        return results["data"]


def cymulate_test(client, is_fetch):
    """
    Returning 'ok' indicates that the integration works like it is supposed to. Connection to the service is successful.

    Args:
        client: cymulate client
        is_fetch (bool): indicate if test also 'fetch' function
    Returns:
        'ok' if test passed, anything else will fail the test.
    """

    results = client.test_api()
    fetch_test = True

    # If 'is_fetch' selected - check also 'fetch_incidents'
    if is_fetch:
        next_run, incidents, remain_incidents = fetch_incidents(
            client=client,
            module_type=CymulateModuleTypeEnum.IMMEDIATE_THREATS,
            last_run={"last_fetch": "2020-12-02T16:32:37"},
            first_fetch_time={},
            only_penatrated=False,
            limit=20,
            integration_context=None,
        )

        fetch_test = next_run == {"last_fetch": "2020-12-02T16:32:37"}

    if results["success"] and fetch_test:
        return demisto.results("ok")
    else:
        return None


def fetch_incidents(
    client, module_type, last_run, first_fetch_time, only_penatrated, limit=DEFAULT_LIMIT, integration_context=None
):
    """
    This function will execute each interval (default is 1 minute).

    Args:
        client (Client): Cymulate client
        module_type (CymulateModuleTypeEnum): module_type enum
        last_run (dateparser.time): The greatest incident created_time we fetched from last fetch
        first_fetch_time (dateparser.time): If last_run is None then fetch all incidents since first_fetch_time
        only_penatrated (boolean): Indicate if fetch only 'penatrated' incidents or all incidents
        limit: (integer): The limit of the incidents to retrieve
        integration_context: The integration's context that store on demisto side

    Returns:
        next_run: This will be last_run in the next fetch-incidents
        incidents: Incidents that will be created in Demisto
    """

    # Check if there are remained incidents saved in context
    if integration_context:
        remained_incidents = integration_context.get("incidents")
        # return incidents if exists in context.
        if remained_incidents and len(remained_incidents) > 0:
            demisto.debug("there is remaines incidents and return them")
            return last_run, remained_incidents[:limit], remained_incidents[limit:]

    # Get the last fetch time, if exists
    start_query_time = last_run.get("last_fetch")

    # Handle first time fetch
    if not start_query_time:
        start_query_time, _ = parse_date_range(first_fetch_time, date_format=DATE_FORMAT, utc=True)
        start_query_time = ts_add_minutes(start_query_time, 2)

    incidents = []
    # Get the incident from server
    items = client.get_attack_info(module_type, start_query_time)

    for item in items:
        if not item["InProgress"]:
            technical_data = client.get_attack_technical_info(module_type, item["Id"])
            incident_created_time = dateparser.parse(item["Timestamp"])

            for incident in technical_data:
                # Manual add attack_id for mapping issue
                incident["Attack_ID"] = item["Id"]

                if not only_penatrated or incident["Status"] == "Penetrated":
                    assert incident_created_time is not None
                    incident_data = {
                        "name": item["Name"],
                        "occurred": incident_created_time.strftime(DATE_FORMAT),
                        "rawJSON": json.dumps(incident),
                    }

                    incidents.append(incident_data)

    if len(items) > 0 and len(incidents) > 0:
        demisto.debug("length of items is big than 0")
        last_incident_ts = incidents[len(incidents) - 1]["occurred"]
        next_run_ts = (datetime.strptime(last_incident_ts, DATE_FORMAT) + timedelta(seconds=1)).strftime(DATE_FORMAT)
    else:
        demisto.debug("length of items is 0")
        next_run_ts = start_query_time

    next_run = {"last_fetch": next_run_ts}

    demisto.debug(f"start_query_time:{start_query_time}")
    demisto.debug(f"len(items):{len(items)}")
    demisto.debug(f"len(incidents):{len(incidents)}")
    demisto.debug(f"next_run:{next_run}")

    return next_run, incidents[:limit], incidents[limit:]


def cymulate_get_incident_info(client, attack_id):
    """
    This function return technical info about incident

    Args:
        client (Client): Cymulate client
        attack_id (String): The attack id

    Returns:
        Incident contained details technical data
    """

    # Get module_type
    module_type = CymulateModuleTypeEnum[demisto.args().get("module_type")]

    # Execute command on API
    technical_data = client.get_attack_technical_info(module_type, attack_id)

    return technical_data


def main():
    """
    PARSE AND VALIDATE INTEGRATION PARAMS
    """
    session_token = demisto.params()["x-token"]
    header = {"x-token": session_token}

    # How many time before the first fetch to retrieve incidents
    fetch_time = demisto.params().get("fetch_time", "3 days").strip()

    # Get the module type
    module_type = demisto.params().get("module_type", CymulateModuleTypeEnum.IMMEDIATE_THREATS)

    # Fetch only 'penatrated'
    only_penatrated = demisto.params().get("onlyPenatrated", True)

    # Flag if use server proxy
    use_proxy = demisto.params().get("useProxy", False)

    # Flag if use server 'verification'
    insecure = demisto.params().get("insecure", False)

    # Flag if 'is_fetch'
    is_fetch = demisto.params().get("isFetch", False)

    # Amount limit of returned incidents
    fetch_limit = 25

    LOG(f"Command being called is: {demisto.command()}")
    demisto.debug(
        f"MAIN CALL , PARAMS session_token:{session_token} module_type:{module_type} "
        f"only_penatrated:{only_penatrated} use_proxy:{use_proxy} insecure:{insecure}"
        f" is_fetch:{is_fetch}"
    )

    try:
        client = Client(base_url=BASE_URL, headers=header, verify=insecure, proxy=use_proxy)

        if demisto.command() == "test-module":
            demisto.debug("******###CYMULATE-LOGS-START-TEST_MODULE!!!*******")

            # This is the call made when pressing the integration Test button.
            cymulate_test(client=client, is_fetch=is_fetch)

            demisto.debug("******###CYMULATE-LOGS-END-TEST_MODULE!!!*******")

        elif demisto.command() == "fetch-incidents":
            demisto.debug("******###CYMULATE-LOGS-START-FETCH_INCIDENTS!!!*******")

            # Get the context
            integration_context = demisto.getIntegrationContext()
            demisto.debug(f"initial integration_context:{integration_context}")
            demisto.debug(f"initial last_run:{demisto.getLastRun()}")

            # Set and define the fetch incidents command to run after activated via integration settings.
            next_run, incidents, remained_incidents = fetch_incidents(
                client=client,
                module_type=module_type,
                last_run=demisto.getLastRun(),
                first_fetch_time=fetch_time,
                only_penatrated=only_penatrated,
                limit=fetch_limit,
                integration_context=integration_context,
            )

            demisto.debug(f"updated next_run:{next_run}")
            demisto.debug(f"return incidents:{incidents}")
            demisto.debug(f"return remained_incidents:{remained_incidents}")

            # Store next_run, incidents, remained incidents into integration
            demisto.setLastRun(next_run)
            demisto.incidents(incidents)

            # Store integration context
            integration_context["incidents"] = remained_incidents
            demisto.setIntegrationContext(integration_context)
            demisto.debug(f"updated integration_context:{integration_context}")

            demisto.debug("******###CYMULATE-LOGS-END-FETCH_INCIDENTS!!!*******")

        elif demisto.command() == "cymulate-get-incident-info":
            demisto.debug("******###CYMULATE-LOGS-START-GET_INCIDENT_INFO!!!*******")

            # Get incident's parent id
            attack_id = demisto.args().get("attack_id")

            # Get incident_id
            incident_id = demisto.args().get("incident_id", None)

            demisto.debug(f"PARAMS attack_id:{attack_id} incident_id:{incident_id}")

            # Get technical data from server
            technical_data = cymulate_get_incident_info(client=client, attack_id=attack_id)

            demisto.debug(f"API RESULT technical_data_length:{len(technical_data)} technical_data:{technical_data}")

            if technical_data and len(technical_data) > 0:
                parsed_technical_data = []

                for incident in technical_data:
                    if incident_id is None or incident_id == incident["ID"]:
                        parsed_technical_data.append(
                            {
                                "ID": incident["ID"],
                                "Attack_ID": attack_id,
                                "Name": incident["Name"],
                                "Status": incident["Status"],
                                "Attack_Type": incident["Attack_Type"],
                                "Attack_Vector": incident["Attack_Vector"],
                                "Timestamp": incident["Timestamp"],
                                "Attack_Payload": incident["Attack_Payload"],
                                "Md5": incident["Md5"],
                                "Mitigation": incident["Mitigation"],
                                "Module": incident["Module"],
                                "Penetration_Vector": incident["Penetration_Vector"],
                                "Sha1": incident["Sha1"],
                                "Sha256": incident["Sha256"],
                            }
                        )

                # Convert to human reading format
                cymulate_output = tableToMarkdown(
                    "Cymulate Results",
                    parsed_technical_data,
                    [
                        "ID",
                        "Attack_ID",
                        "Name",
                        "Status",
                        "Attack_Type",
                        "Attack_Vector",
                        "Timestamp",
                        "Attack_Payload",
                        "Md5",
                        "Mitigation",
                        "Module",
                        "Penetration_Vector",
                        "Sha1",
                        "Sha256",
                    ],
                )
                outputs = {"Cymulate.Incident(val.ID == obj.ID)": parsed_technical_data}

                demisto.debug(f"outputs results: {outputs}")

                # Return output to client
                return_outputs(
                    cymulate_output,
                    outputs,
                    technical_data,  # raw response - the original response
                )
            else:
                # No Results format
                demisto.debug("NO Results")
                demisto.results("No results found.")

        demisto.debug("******###CYMULATE-LOGS-END-GET_INCIDENT_INFO!!!*******")

    # Log exceptions
    except Exception as e:
        return_error(f"Failed to execute {demisto.command()} command. Error: {e!s}")


if __name__ == "__builtin__" or __name__ == "builtins":
    main()