Alexa Rank Indicator v2 Deprecated

Deprecated. Vendor has declared end of life for this product. No available replacement.

Data Enrichment & Threat Intelligence · Alexa Rank Indicator (Deprecated)

Details

IDAlexa Rank Indicator v2
ProviderAmazon
CategoryData Enrichment & Threat Intelligence
From Version5.5.0
Docker Imagedemisto/python3:3.10.9.42476
Supported ModulesAgentix

README

Alexa provides website ranking information that can be used to help determine if a domain has a strong web presence.
This integration was integrated and tested with Alexa Rank Indicator V2.

New: Alexa Rank Indicator v2
  • Use of the Alexa API rank.
  • Domains that are not in the Alexa database, are considered “Unknown” instead of “Suspicious”.
  • If the domain doesn’t exist, there is an error.
  • Default values changed: 1000 for Top Domain Threshold and unspecified for Suspicous Domain Threshold.

Configure Alexa Rank Indicator V2 in Cortex

Parameter Description Required
Source Reliability Reliability of the source providing the intelligence data. True
Rank threshold for suspicious domain If the domain’s Alexa rank is over this threshold, the domain is marked as suspicious. If the rank is between the threshold for suspicious domains and top domains, the domain is marked as unknown. True
Base API URL   True
Rank threshold for top domains If the domain’s Alexa rank is under this threshold, the domain is considered trusted and marked as good. If the rank is between the threshold for suspicious domains and top domains, the domain is marked as unknown. True
Use system proxy settings   False
Trust any certificate (not secure)   False
API Key   True

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.

domain


Provides the Alexa ranking of a domain.

Base Command

domain

Input

Argument Name Description Required
domain Domain(s) to search. Required

Context Output

Path Type Description
Domain.Name String The domain being checked.
DBotScore.Score number The actual score.
DBotScore.Vendor String The vendor used to calculate the score.
DBotScore.Type String The indicator type.
DBotScore.Indicator String The indicator that was tested.
Alexa.Domain.Indicator String The domain being checked.
Alexa.Domain.Name String The domain being checked.
Alexa.Domain.Rank String Alexa rank as determined by Amazon.

Command Example

```!domain domain=”google.com,xsoar.com”

Context Example

{
    "Alexa": {
        "Domain": [
            {
                "Indicator": "google.com",
                "Name": "google.com",
                "Rank": "1"
            },
            {
                "Indicator": "xsoar.com",
                "Name": "xsoar.com",
                "Rank": "Unknown"
            }
        ]
    },
    "DBotScore": [
        {
            "Indicator": "google.com",
            "Reliability": "A - Completely reliable",
            "Score": 0,
            "Type": "domain",
            "Vendor": "Alexa Rank Indicator V2"
        },
        {
            "Indicator": "xsoar.com",
            "Reliability": "A - Completely reliable",
            "Score": 2,
            "Type": "domain",
            "Vendor": "Alexa Rank Indicator V2"
        }
    ],
    "Domain": [
        {
            "Name": "google.com"
        },
        {
            "Name": "xsoar.com"
        }
    ]
}

Human Readable Output

Alexa Rank for xsoar.com

Domain Alexa Rank Reputation
xsoar.com   Suspicous

Configuration parameters

  • base_url — Base API URL (required)
  • credentials — (required)
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)
  • suspicious_domain_threshold — Rank Threshold For Suspicious Domain
  • top_domain_threshold — Rank Threshold For Top Domains (required)
  • integrationReliability — Source Reliability (required)

Commands (1)

  • domain

    Provides an Alexa ranking of the domain.

import demistomock as demisto
from CommonServerPython import *  # noqa # pylint: disable=unused-wildcard-import
from CommonServerUserPython import *  # noqa

import urllib3
from typing import Dict

# Disable insecure warnings
urllib3.disable_warnings()  # pylint: disable=no-member

''' CONSTANTS '''

DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ'  # ISO8601 format with UTC, default in XSOAR

''' CLIENT CLASS '''


class Client(BaseClient):
    def __init__(self, api_key: str,
                 base_url: str,
                 proxy: bool,
                 verify: bool,
                 reliability: str,
                 top_domain_threshold: int,
                 suspicious_domain_threshold: Optional[int]):
        super().__init__(base_url=base_url,
                         verify=verify,
                         proxy=proxy)
        if DBotScoreReliability.is_valid_type(reliability):
            self.reliability = DBotScoreReliability.get_dbot_score_reliability_from_str(reliability)
        else:
            raise DemistoException("AlexaV2 error: Please provide a valid"
                                   " value for the Source Reliability parameter.")
        self.top_domain_threshold = top_domain_threshold
        self.suspicious_domain_threshold = suspicious_domain_threshold
        self.api_key = api_key

    def http_request(self, params: Dict):
        return self._http_request(method='GET',
                                  headers={'x-api-key': self.api_key},
                                  params=params)

    def alexa_rank(self, domain: str) -> Dict:
        params = {'Action': 'UrlInfo',
                  'ResponseGroup': 'Rank',
                  'Url': domain,
                  'Output': 'json'}
        return self.http_request(params=params)


''' HELPER FUNCTIONS '''


def rank_to_context(domain: str,
                    rank: Optional[int],
                    top_domain_threshold: int,
                    suspicious_domain_threshold: Optional[int],
                    reliability: DBotScoreReliability):
    if rank is None:
        score = Common.DBotScore.NONE
    elif rank < 0:
        raise DemistoException(f'AlexaV2 error: {rank} is invalid. Rank should be positive')
    elif 0 < rank <= top_domain_threshold:
        score = Common.DBotScore.GOOD
    elif suspicious_domain_threshold and rank > suspicious_domain_threshold:
        score = Common.DBotScore.SUSPICIOUS
    else:  # alexa_rank < client.threshold:
        score = Common.DBotScore.NONE
    dbot_score = Common.DBotScore(
        indicator=domain,
        indicator_type=DBotScoreType.DOMAIN,
        reliability=reliability,
        score=score
    )
    domain_standard_context = Common.Domain(
        domain=domain,
        dbot_score=dbot_score
    )
    return domain_standard_context


''' COMMAND FUNCTIONS '''


def test_module(client: Client) -> str:
    """Tests API connectivity and authentication'

    Returning 'ok' indicates that the integration works like it is supposed to.
    Connection to the service is successful.
    Raises exceptions if something goes wrong.

    Args (Client): a client to use

    Return: 'ok' if test passed, anything else will fail the test.
    """

    try:
        client.alexa_rank('google.com')
        return 'ok'
    except DemistoException as e:
        if 'Forbidden' in str(e):
            return 'Authorization Error: make sure API Key is correctly set'
        raise e


def alexa_domain(client: Client, domains: List[str]) -> List[CommandResults]:
    if not domains:
        raise ValueError('AlexaV2 error: domain doesn\'t exists')
    command_results: List[CommandResults] = []
    for domain in domains:
        result = client.alexa_rank(domain)
        domain_res = demisto.get(result,
                                 'Awis.Results.Result.Alexa.TrafficData.DataUrl')
        if not domain_res or domain_res == '404':  # Not found on alexa
            raise DemistoException('AlexaV2 error: Domain cannot be found')
        domain_res = domain_res[:-1] if domain_res[-1] == '/' else domain_res
        rank = demisto.get(result,
                           'Awis.Results.Result.Alexa.TrafficData.Rank')
        domain_standard_context: Common.Domain = rank_to_context(domain=domain_res,
                                                                 rank=arg_to_number(rank),
                                                                 suspicious_domain_threshold=client.suspicious_domain_threshold,
                                                                 top_domain_threshold=client.top_domain_threshold,
                                                                 reliability=client.reliability)

        rank: str = rank if rank else 'Unknown'
        result = {'Name': domain_res,
                  'Indicator': domain_res,
                  'Rank': rank}
        table = {'Domain': domain_res,
                 'Alexa Rank': rank,
                 'Reputation': domain_standard_context.dbot_score.to_readable()}
        readable = tableToMarkdown(f'Alexa Rank for {domain_res}', table, headers=list(table.keys()))
        command_results.append(CommandResults(
            outputs_prefix='Alexa.Domain',
            outputs_key_field='Name',
            outputs=result,
            readable_output=readable,
            indicator=domain_standard_context
        ))
    return command_results


''' MAIN FUNCTION '''


def main() -> None:
    params = demisto.params()
    api_key = demisto.get(params, 'credentials.password')
    base_api = params.get('base_url')
    reliability = params.get('integrationReliability')
    verify_certificate = not params.get('insecure', False)
    proxy = params.get('proxy', False)
    demisto.debug(f'Command being called is {demisto.command()}')
    try:
        suspicious_domain_threshold = arg_to_number(params.get('suspicious_domain_threshold', None),
                                                    required=False,
                                                    arg_name='suspicious_domain_threshold')
        top_domain_threshold = arg_to_number(params.get('top_domain_threshold'),
                                             required=True,
                                             arg_name='top_domain_threshold')
        if (suspicious_domain_threshold and suspicious_domain_threshold < 0)\
                or top_domain_threshold < 0:  # type: ignore
            raise DemistoException(f'AlexaV2 error: All threshold values should be greater than 0.'
                                   f'Suspicious domain threshold is {suspicious_domain_threshold}. '
                                   f'Top domain threshold is {top_domain_threshold}.')
        client = Client(
            base_url=base_api,
            verify=verify_certificate,
            proxy=proxy,
            api_key=api_key,
            suspicious_domain_threshold=suspicious_domain_threshold,  # type: ignore
            top_domain_threshold=top_domain_threshold,  # type: ignore
            reliability=reliability)
        if demisto.command() == 'test-module':
            return_results(test_module(client))
        elif demisto.command() == 'domain':
            domains = demisto.args().get('domain')
            return_results(alexa_domain(client, argToList(domains)))
        else:
            raise NotImplementedError(f'Command {demisto.command()} is not implemented.')

    except Exception as e:
        return_error(f'Failed to execute {demisto.command()} command.\nError:\n{str(e)}')


''' ENTRY POINT '''

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