HYAS Protect

Use the HYAS Protect integration to get the verdict information for FQDN, IP Address and NameServer – either as playbook tasks or through API calls in the War Room.

Data Enrichment & Threat Intelligence · HYAS Protect

Details

IDHYAS Protect
ProviderthreatER
CategoryData Enrichment & Threat Intelligence
From Version6.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

HYAS Protect

HYAS Protect is a generational leap forward utilizing authoritative knowledge of attacker infrastructure including unrivaled domain-based intelligence to proactively protect enterprises from cyberattacks. HYAS Protect is deployed as a cloud-based DNS security solution or through API integration with existing solutions. HYAS Protect combines infrastructure expertise and multi-variant communication pattern analysis to deliver reputational verdicts for any domain and infrastructure, allowing enterprises to preempt attacks while proactively assessing risk in real-time. HYAS Protect can enforce security, block command and control (C2) communication used by malware, ransomware, and botnets, block phishing attacks, and deliver a high-fidelity threat signal that enhances an enterprise’s existing security and IT governance stack.

Use the HYAS Protect integration to get the verdict information for FQDN, IP Address and NameServer.
This integration was integrated and tested with version 1.0.0 of HYAS Protect.

Configure HYAS Protect in Cortex

Parameter Description Required
HYAS Protect Api Key HYAS Protect API Key. True
Trust any certificate (not secure) Trust any certificate (not secure). False
Use system proxy settings Use system proxy settings. False

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

hyas-get-domain-verdict


Returns verdict information for the provided Domain.

Base Command

hyas-get-domain-verdict

Input

Argument Name Description Required
domain Domain value to query. Required

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the indicator score.
HYAS.DomainVerdict.verdict String Verdict for the provided Domain.
HYAS.DomainVerdict.reasons Unknown Verdict Reasons the provided Domain.

Command Example

!hyas-get-domain-verdict domain="google.com"

Context Example

{
    "DBotScore": {
        "Indicator": "google.com",
        "Score": 1,
        "Type": "domain",
        "Vendor": "HYAS Protect"
    },
    "Domain": {
        "Name": "google.com"
    },
    "HYAS": {
        "DomainVerdict": [
            {
                "reasons": [
                    "This domain is trusted",
                    "This registrar is trusted"
                ],
                "verdict": "ALLOW"
            }
        ]
    }
}

Human Readable Output

HYAS Domain verdict for google.com

Verdict Reasons
ALLOW This domain is trusted,
This registrar is trusted

hyas-get-ip-verdict


Returns verdict information for the provided IP Address.

Base Command

hyas-get-ip-verdict

Input

Argument Name Description Required
ip IP value to query. Required

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the indicator score.
HYAS.IPVerdict.verdict String Verdict for the provided IP Address.
HYAS.IPVerdict.reasons Unknown Verdict Reasons for the provided IP Address.

Command Example

!hyas-get-ip-verdict ip="8.8.8.8"

Context Example

{
    "DBotScore": {
        "Indicator": "8.8.8.8",
        "Score": 1,
        "Type": "ip",
        "Vendor": "HYAS Protect"
    },
    "HYAS": {
        "IPVerdict": [
            {
                "reasons": [],
                "verdict": "ALLOW"
            }
        ]
    },
    "IP": {
        "Address": "8.8.8.8"
    }
}

Human Readable Output

HYAS IP verdict for 8.8.8.8

Verdict
ALLOW

hyas-get-fqdn-verdict


Returns verdict information for the provided FQDN.

Base Command

hyas-get-fqdn-verdict

Input

Argument Name Description Required
fqdn FQDN value to query. Required

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the indicator score.
HYAS.FQDNVerdict.verdict String Verdict for for the provided FQDN.
HYAS.FQDNVerdict.reasons Unknown Verdict Reasons for the provided FQDN.

Command Example

!hyas-get-fqdn-verdict fqdn="www.google.com"

Context Example

{
    "DBotScore": {
        "Indicator": "www.google.com",
        "Score": 1,
        "Type": "domain",
        "Vendor": "HYAS Protect"
    },
    "Domain": {
        "Name": "www.google.com"
    },
    "HYAS": {
        "FQDNVerdict": [
            {
                "reasons": [
                    "This domain is trusted",
                    "This registrar is trusted"
                ],
                "verdict": "ALLOW"
            }
        ]
    }
}

Human Readable Output

HYAS FQDN verdict for www.google.com

Verdict Reasons
ALLOW This domain is trusted,
This registrar is trusted

hyas-get-nameserver-verdict


Returns verdict information for the provided Nameserver.

Base Command

hyas-get-nameserver-verdict

Input

Argument Name Description Required
nameserver Nameserver value to query. Required

Context Output

Path Type Description
DBotScore.Indicator String The indicator that was tested.
DBotScore.Score Number The actual score.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the indicator score.
HYAS.NameserverVerdict.verdict String Verdict for the provided Nameserver.
HYAS.NameserverVerdict.reasons Unknown Verdict Reasons for the provided Nameserver.

Command Example

!hyas-get-nameserver-verdict nameserver="ns1.example.com"

Context Example

{
    "HYAS": {
        "NameserverVerdict": [
            {
                "reasons": [],
                "verdict": "ALLOW"
            }
        ]
    }
}

Human Readable Output

HYAS Nameserver verdict for ns1.example.com

Verdict
ALLOW

Configuration parameters

  • X-API-Key — HYAS Protect Api Key (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (4)

  • hyas-get-domain-verdict

    Returns verdict information for the provided Domain.

  • hyas-get-fqdn-verdict

    Returns verdict information for the provided FQDN.

  • hyas-get-ip-verdict

    Returns verdict information for the provided IP Address.

  • hyas-get-nameserver-verdict

    Returns verdict information for the provided Nameserver.

import urllib3
from CommonServerPython import *

# Disable insecure warnings
urllib3.disable_warnings()

# CORTEX XSOAR COMMAND CONSTANTS
INTEGRATION_NAME = "HYAS PROTECT"
INTEGRATION_COMMAND_NAME = "hyas"
INTEGRATION_CONTEXT_NAME = "HYAS"
DOMAIN_VERDICT_SUB_CONTEXT = "DomainVerdict"
IP_VERDICT_SUB_CONTEXT = "IPVerdict"
NAMESERVER_VERDICT_SUB_CONTEXT = "NameserverVerdict"
FQDN_VERDICT_SUB_CONTEXT = "FQDNVerdict"

# HYAS API BASE URL
HYAS_API_BASE_URL = "https://api.hyas.com/protect/"
TIMEOUT = 60

# HYAS API endpoints
DOMAIN_ENDPOINT = "domain"
IP_ENDPOINT = "ip"
FQDN_ENDPOINT = "fqdn"
NAMESERVER_ENDPOINT = "nameserver"

# HYAS API INPUT PARAMETERS
DOMAIN_PARAM = "domain"
IP_PARAM = "ip"
FQDN_PARAM = "fqdn"
NAMESERVER_PARAM = "nameserver"


def to_demisto_score(verdict: str):
    if verdict.lower() == "deny":
        return Common.DBotScore.BAD
    if verdict.lower() == "suspicious":
        return Common.DBotScore.SUSPICIOUS
    if verdict.lower() == "allow":
        return Common.DBotScore.GOOD
    return Common.DBotScore.NONE


class Client(BaseClient):
    def __init__(self, base_url: str, apikey: str, verify=None, proxy=None):
        BaseClient.__init__(
            self,
            base_url,
            verify=verify,
            headers={"Content-type": "application/json", "X-API-Key": apikey, "User-Agent": "Cortex XSOAR"},
            proxy=proxy,
            ok_codes=(200,),
        )
        self.apikey = apikey

    def fetch_data_from_hyas_api(self, end_point: str, ind_value: str) -> Dict:
        """
        :param end_point: HYAS endpoint
        :param ind_value: indicator_value provided in the command
        :return: return the raw api response from HYAS API.
        """
        return self.query(end_point, ind_value)

    def query(self, end_point: str, ind_value: str) -> Dict:
        """
        :param end_point: HYAS endpoint
        :param ind_value: indicator_value provided in the command
        :return: return the raw api response from HYAS API.
        """
        url_path = f"{end_point}/{ind_value}"
        response = self._http_request("GET", url_suffix=url_path, timeout=TIMEOUT)
        return response

    def test_module(self) -> str:
        """
        :return: connection ok

        """

        try:
            self.query(DOMAIN_ENDPOINT, "www.hyas.com")
        except DemistoException as e:
            if "401" in str(e):
                return "Authorization Error: Provided apikey is not valid"
            else:
                raise e
        return "ok"


def check_valid_indicator_value(indicator_type: str, indicator_value: str) -> bool:
    """

    :param indicator_type: Indicator type provided in the command
    :param indicator_value: Indicator value provided in the command
    :return: true if the indicator value provided for the indicator
     type is valid

    """
    # not using default urlRegex for domain validation
    # as it is failing in some cases, for example
    # 'fluber12.duckdns.org' is validated as invalid
    domain_regex = re.compile(
        r"^(?:[a-zA-Z0-9]"  # First character of the domain
        r"(?:[a-zA-Z0-9-_]{0,61}[A-Za-z0-9])?\.)"  # Sub domain + hostname
        r"+[A-Za-z0-9][A-Za-z0-9-_]{0,61}"  # First 61 characters of the gTLD
        r"[A-Za-z]$"  # Last character of the gTLD
    )

    if indicator_type == NAMESERVER_PARAM:
        if not re.match(domain_regex, indicator_value):
            raise ValueError(f"Invalid indicator_value: {indicator_value} for indicator_type {indicator_type}")
    elif indicator_type == FQDN_PARAM:
        if not re.match(domain_regex, indicator_value):
            raise ValueError(f"Invalid indicator_value: {indicator_value} for indicator_type {indicator_type}")
    elif indicator_type == DOMAIN_PARAM:
        if not re.match(domain_regex, indicator_value):
            raise ValueError(f"Invalid indicator_value: {indicator_value} for indicator_type {indicator_type}")
    elif indicator_type == IP_PARAM and not re.match(ipv4Regex, indicator_value):
        if not re.match(ipv6Regex, indicator_value):
            raise ValueError(f"Invalid indicator_value: {indicator_value} for indicator_type {indicator_type}")
        raise ValueError(f"Invalid indicator_value: {indicator_value} for indicator_type {indicator_type}")

    return True


def get_command_title_string(sub_context: str, indicator_type: str, indicator_value: str) -> str:
    """

    :param sub_context: Commands sub_context
    :param indicator_type: Indicator type provided in the command
    :param indicator_value: Indicator value provided in the command
    :return: returns the title for the readable output

    """
    return INTEGRATION_CONTEXT_NAME + " " + sub_context + " verdict for " + indicator_value


@logger
def indicator_verdict_result_context(results: Dict) -> Dict:
    ctx = {}
    for ckey, rkey, f in (
        ("verdict", "verdict", str),
        ("reasons", "reasons", list),
    ):
        if rkey in results:
            ctx[ckey] = f(results[rkey])  # type: ignore[operator]

    return ctx


@logger
def indicator_verdict_lookup_to_markdown(results: dict, title: str) -> str:
    out = []
    row = {"Verdict": results.get("verdict"), "Reasons": results.get("reasons")}
    out.append(row)

    return tableToMarkdown(title, out, headers=["Verdict", "Reasons"], removeNull=True)


@logger
def get_domain_verdict(client, args):
    indicator_type = DOMAIN_PARAM
    indicator_value = args.get("domain")

    check_valid_indicator_value(indicator_type, indicator_value)
    title = get_command_title_string("Domain", indicator_type, indicator_value)

    raw_api_response = client.fetch_data_from_hyas_api(DOMAIN_ENDPOINT, indicator_value)
    verdict = raw_api_response.get("verdict")
    db_score = ""
    if verdict:
        db_score = to_demisto_score(verdict)

    dbot_score = Common.DBotScore(
        indicator=indicator_value,
        indicator_type=DBotScoreType.DOMAIN,
        integration_name=INTEGRATION_CONTEXT_NAME,
        score=db_score,
        malicious_description=raw_api_response.get("reasons") if raw_api_response.get("reasons") else None,
    )
    domain = Common.Domain(domain=indicator_value, dbot_score=dbot_score)

    return CommandResults(
        readable_output=indicator_verdict_lookup_to_markdown(raw_api_response, title),
        outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.{DOMAIN_VERDICT_SUB_CONTEXT}",
        outputs_key_field="",
        outputs=[indicator_verdict_result_context(raw_api_response)],
        indicator=domain,
    )


@logger
def get_ip_verdict(client, args):
    indicator_type = IP_PARAM
    indicator_value = args.get("ip")

    check_valid_indicator_value(indicator_type, indicator_value)
    title = get_command_title_string("IP", indicator_type, indicator_value)

    raw_api_response = client.fetch_data_from_hyas_api(IP_ENDPOINT, indicator_value)
    verdict = raw_api_response.get("verdict")
    db_score = ""
    if verdict:
        db_score = to_demisto_score(verdict)

    dbot_score = Common.DBotScore(
        indicator=indicator_value,
        indicator_type=DBotScoreType.IP,
        integration_name=INTEGRATION_CONTEXT_NAME,
        score=db_score,
        malicious_description=raw_api_response.get("reasons") if raw_api_response.get("reasons") else None,
    )
    ip = Common.IP(ip=indicator_value, dbot_score=dbot_score)

    return CommandResults(
        readable_output=indicator_verdict_lookup_to_markdown(raw_api_response, title),
        outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.{IP_VERDICT_SUB_CONTEXT}",
        outputs_key_field="",
        outputs=[indicator_verdict_result_context(raw_api_response)],
        indicator=ip,
    )


@logger
def get_fqdn_verdict(client, args):
    indicator_type = FQDN_PARAM
    indicator_value = args.get("fqdn")

    check_valid_indicator_value(indicator_type, indicator_value)
    title = get_command_title_string("FQDN", indicator_type, indicator_value)

    raw_api_response = client.fetch_data_from_hyas_api(FQDN_ENDPOINT, indicator_value)
    verdict = raw_api_response.get("verdict")
    db_score = ""
    if verdict:
        db_score = to_demisto_score(verdict)

    dbot_score = Common.DBotScore(
        indicator=indicator_value,
        indicator_type=DBotScoreType.DOMAIN,
        integration_name=INTEGRATION_CONTEXT_NAME,
        score=db_score,
        malicious_description=raw_api_response.get("reasons") if raw_api_response.get("reasons") else None,
    )
    fqdn = Common.Domain(domain=indicator_value, dbot_score=dbot_score)
    return CommandResults(
        readable_output=indicator_verdict_lookup_to_markdown(raw_api_response, title),
        outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.{FQDN_VERDICT_SUB_CONTEXT}",
        outputs_key_field="",
        outputs=[indicator_verdict_result_context(raw_api_response)],
        indicator=fqdn,
    )


@logger
def get_nameserver_verdict(client, args):
    indicator_type = NAMESERVER_PARAM
    indicator_value = args.get("nameserver")

    check_valid_indicator_value(indicator_type, indicator_value)
    title = get_command_title_string("Nameserver", indicator_type, indicator_value)

    raw_api_response = client.fetch_data_from_hyas_api(NAMESERVER_ENDPOINT, indicator_value)
    return CommandResults(
        readable_output=indicator_verdict_lookup_to_markdown(raw_api_response, title),
        outputs_prefix=f"{INTEGRATION_CONTEXT_NAME}.{NAMESERVER_VERDICT_SUB_CONTEXT}",
        outputs_key_field="",
        outputs=[indicator_verdict_result_context(raw_api_response)],
    )


@logger
def test_module(client):
    return client.test_module()


def main():
    """
    PARSE AND VALIDATE INTEGRATION PARAMS
    """

    apikey = demisto.params().get("X-API-Key")
    verify_certificate = not demisto.params().get("insecure", False)
    proxy = demisto.params().get("proxy", False)

    try:
        client = Client(HYAS_API_BASE_URL, apikey, verify=verify_certificate, proxy=proxy)

        command = demisto.command()
        LOG(f"Command being called is {command}")
        if demisto.command() == "test-module":
            # This is the call made when pressing the integration Test button.
            return_results(test_module(client))
        elif command == f"{INTEGRATION_COMMAND_NAME}-get-domain-verdict":
            return_results(get_domain_verdict(client, demisto.args()))
        elif command == f"{INTEGRATION_COMMAND_NAME}-get-ip-verdict":
            return_results(get_ip_verdict(client, demisto.args()))
        elif command == f"{INTEGRATION_COMMAND_NAME}-get-fqdn-verdict":
            return_results(get_fqdn_verdict(client, demisto.args()))
        elif command == f"{INTEGRATION_COMMAND_NAME}-get-nameserver-verdict":
            return_results(get_nameserver_verdict(client, demisto.args()))
    # Log exceptions
    except Exception as e:
        demisto.error(traceback.format_exc())  # print the traceback
        err_msg = f"Error in {INTEGRATION_NAME} Integration [{e}]"
        return_error(err_msg, error=e)


if __name__ in ("__main__", "__builtin__", "builtins"):
    main()