WhatsMyBrowser

Parse user agents and determine if they are malicious as well as enrich information about the agent.

Data Enrichment & Threat Intelligence · WhatIsMyBrowser

Details

IDWhatsMyBrowser
ProviderWhatIsMyBrowserLimited
CategoryData Enrichment & Threat Intelligence
From Version5.0.0
Docker Imagedemisto/python3:3.12.13.10325753
Supported ModulesAgentix XSIAM

README

WhatIsMyBrowser parses user agent strings and gives insight into known user agents. For example, if the user agent string is malicious, WhatIsMyBrowser will indicate that the user agent is known to be malicious.

Configure WhatIsMyBrowser on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for WhatsMyBrowser.
  3. Click Add instance to create and configure a new integration instance.
    • Name: a textual name for the integration instance.
    • API Key: your API key
    • Use system proxy settings:
    • Trust any certificate (insecure)
    • URL for WhatIsMyBrowser: The URL endpoint for the WhatIsMyBrowser
  4. Click Test to validate the URLs, token, and connection.

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. Parse a User Agent string


Parses a User Agent string.

Base Command

ua-parse

Input
Argument Name Description Required
UserAgent User Agent string Required

 

Context Output
Path Type Description
UA.Parse.Software string Software extracted from UA string.
UA.Parse.SoftwareName string Software Name extracted from UA string.
UA.Parse.OperatingSystem string Operating System extracted from UA string.
UA.Parse.Abusive boolean Whether or not the UA has been identified as abusive.
UA.Parse.OperatingSystemName string Operating System Name extracted from UA string.
UA.Parse.UserAgent string User agent string.
UA.Parse.HardwareType string Hardware Type as extracted from UA string.
UA.Parse.HardwareSubType string Hardware Sub Type as extracted from UA string.

 

Command Example

!ua-parse UserAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36"

Context Example
{
    "DBotScore": {
        "Vendor": "WhatIsMyBrowser",
        "Indicator": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36",
        "Score": 1,
        "Type": "UserAgent"
    },
    "UA": {
        "Parse": {
            "Abusive": false,
            "HardwareType": "computer",
            "SoftwareName": "Chrome",
            "OperatingSystemName": "macOS",
            "UserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36",
            "OperatingSystem": "macOS (Mojave)",
            "Software": "Chrome 72"
        }
    }
}

Human Readable Output
screen shot 2019-02-11 at 15 19 29

Configuration parameters

  • url — URL for WhatIsMyBrowser (required)
  • api_key — API Key
  • credentials_api_key
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)

Commands (1)

  • ua-parse

    Parses a User Agent string.

import demistomock as demisto
from CommonServerPython import *

""" IMPORTS """
import json
from collections import defaultdict

import requests
import urllib3

# Disable insecure warnings
urllib3.disable_warnings()


"""GLOBAL VARS"""
API_URL = demisto.params().get("url")
USE_SSL = not demisto.params().get("insecure")
PROXY = demisto.params().get("proxy", False)


"""HELPER FUNCTIONS"""


def http_request(data):
    api_key = demisto.params().get("credentials_api_key", {}).get("password") or demisto.params().get("api_key")
    if not api_key:
        raise DemistoException("API key must be provided.")
    headers = {
        "X-API-KEY": api_key,
    }
    r = requests.request("POST", API_URL, data=data, headers=headers, verify=USE_SSL)
    if r.status_code != 200:
        return_error(f"Error in API call to WhatIsMyBrowser [{r.status_code}] - {r.reason}")
    return r.content


"""MAIN FUNCTIONS"""


def ua_parse(user_agent):
    post_data = {"user_agent": user_agent}
    post_json = json.dumps(post_data)
    r = http_request(post_json)
    return r


def ua_parse_command():
    user_agent = demisto.args().get("UserAgent")
    raw = ua_parse(user_agent)
    r = json.loads(raw)
    dbot_score = {}
    demisto.debug("Initializing dbot_score")
    if "success" in r["result"]["code"]:
        parsed = r["parse"]
        hr = defaultdict()  # type: dict
        ua_ec = defaultdict(lambda: defaultdict(int))  # type: dict
        if "software" in parsed:
            hr["Software"] = parsed["software"]
            ua_ec["Software"] = parsed["software"]
        if "software_name" in parsed:
            hr["Software Name"] = parsed["software_name"]
            ua_ec["SoftwareName"] = parsed["software_name"]
        if "operating_system" in parsed and parsed["operating_system"] is not None:
            hr["Operating System"] = parsed["operating_system"]
            ua_ec["OperatingSystem"] = parsed["operating_system"]
        if "is_abusive" in parsed:
            hr["Abusive"] = parsed["is_abusive"]
            ua_ec["Abusive"] = parsed["is_abusive"]
            if parsed["is_abusive"] is True:
                dbot_score = {
                    "Score": 3,
                    "Type": "UserAgent",
                    "Vendor": "WhatIsMyBrowser",  # disable-secrets-detection
                    "Indicator": parsed["user_agent"],
                }
            else:
                dbot_score = {
                    "Score": 1,
                    "Type": "UserAgent",
                    "Vendor": "WhatIsMyBrowser",  # disable-secrets-detection
                    "Indicator": parsed["user_agent"],
                }
        if "operating_system_name" in parsed and parsed["operating_system_name"] is not None:
            hr["Operating System Name"] = parsed["operating_system_name"]
            ua_ec["OperatingSystemName"] = parsed["operating_system_name"]
        if "user_agent" in parsed:
            hr["User Agent"] = parsed["user_agent"]
            ua_ec["UserAgent"] = parsed["user_agent"]
        if "hardware_type" in parsed and parsed["hardware_type"] is not None:
            hr["Hardware Type"] = parsed["hardware_type"]
            ua_ec["HardwareType"] = parsed["hardware_type"]
        if "hardware_sub_type" in parsed and parsed["hardware_sub_type"] is not None:
            hr["Hardware Sub Type"] = parsed["hardware_sub_type"]
            ua_ec["HardwareSubType"] = parsed["hardware_sub_type"]
        ec = {"UA.Parse(val.UserAgent && val.UserAgent == obj.UserAgent)": ua_ec, "DBotScore": dbot_score}
        demisto.results(
            {
                "Type": entryTypes["note"],
                "ContentsFormat": formats["json"],
                "Contents": r,
                "HumanReadable": tableToMarkdown(f"Parsed result for {user_agent}", hr),
                "EntryContext": ec,
            }
        )
    if r["result"]["code"] == "error":
        error_msg = r["result"]["message"]
        demisto.results(
            {"Type": entryTypes["note"], "ContentsFormat": formats["markdown"], "Contents": r, "HumanReadable": f"{error_msg}"}
        )


def test_command():
    post_data = {
        # disable-secrets-detection
        "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/64.0.3282.140 Safari/537.36"
    }
    post_json = json.dumps(post_data)
    http_request(post_json)
    demisto.results("ok")


"""EXECUTION BLOCK"""
try:
    handle_proxy()
    if demisto.command() == "ua-parse":
        ua_parse_command()
    if demisto.command() == "test-module":
        test_command()
except Exception as e:
    return_error(str(e))