Details
| ID | JARM |
|---|---|
| Provider | Salesforce |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.0.0 |
| Docker Image | demisto/py3-tools:1.0.0.10120494 |
| Supported Modules | Agentix XSIAM |
README
Active TLS fingerprinting using JARM
Configure JARM in Cortex
| Parameter | Required |
|---|---|
| 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.
jarm-fingerprint
Calculate JARM fingerprint by scanning host with multiple TLS packets.
Base Command
jarm-fingerprint
Input
| Argument Name | Description | Required |
|---|---|---|
| host | FQDN or IP address to fingerprint. Also supports [https://fqdn:port] format. | Required |
| port | Port to fingerprint. If provided overrides the port specified in the host parameter. Default is 443. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| JARM.FQDN | String | FQDN of the host. |
| JARM.IP | String | IP Address of the host. |
| JARM.Port | Number | TCP port |
| JARM.Target | String | The host in the format [IP or FQDN]:Port |
| JARM.Fingerprint | String | JARM fingerprint of the host. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
Command Example
!jarm-fingerprint host="google.com" port=443
Context Example
{
"DBotScore": [
{
"Indicator": "27d40d40d29d40d1dc42d43d00041d4689ee210389f4f6b4b5b1b93f92252d",
"Score": 0,
"Type": "jarm",
"Vendor": "JARM"
}
],
"JARM": {
"FQDN": "google.com",
"Fingerprint": "27d40d40d29d40d1dc42d43d00041d4689ee210389f4f6b4b5b1b93f92252d",
"Port": 443,
"Target": "google.com:443"
}
}
Human Readable Output
Results
FQDN Fingerprint Port Target google.com 27d40d40d29d40d1dc42d43d00041d4689ee210389f4f6b4b5b1b93f92252d 443 google.com:443
Configuration parameters
proxy— Use system proxy settings
Commands (1)
-
jarm-fingerprintCalculate JARM fingerprint by scanning host with multiple TLS packets.
import asyncio import traceback from ipaddress import ip_address from typing import Any from urllib.parse import urlparse import demistomock as demisto import urllib3 from CommonServerPython import * # noqa # pylint: disable=unused-wildcard-import from jarm.scanner.scanner import Scanner # pylint: disable=E0401,E0611 from CommonServerUserPython import * # noqa # Disable insecure warnings urllib3.disable_warnings() # pylint: disable=no-member DEFAULT_PORT = 443 """ CLIENT CLASS """ class Client: def jarm_fingerprint(self, host: str, port: int) -> tuple[str, str, int]: return asyncio.run(Scanner.scan_async(host, port, suppress=True)) """ HELPER FUNCTIONS """ def parse_hostname(hostname: str, port: Optional[int]) -> dict[str, Any]: """ Parses a target hostname. Supports multiple ipv4/fqdn with and without port formats. """ target: dict[str, Any] = {} if not hostname.startswith("https://"): hostname = "https://" + hostname parsed_url = urlparse(hostname) if port: target["port"] = port elif parsed_url.port: target["port"] = parsed_url.port else: target["port"] = DEFAULT_PORT try: ip = ip_address(parsed_url.hostname) # type: ignore[arg-type] target["target_host"] = str(ip) target["target_type"] = "ip" except ValueError: target["target_host"] = parsed_url.hostname target["target_type"] = "fqdn" return target """ COMMAND FUNCTIONS """ def test_module(client: Client) -> str: return "ok" def jarm_fingerprint_command(client: Client, args: dict[str, Any]) -> CommandResults: class JARMDBotScore(Common.Indicator): def __init__(self, output: dict[str, Any]): self._jarm = output.get("Fingerprint") def to_context(self) -> dict[str, Any]: return { "DBotScore": { "Indicator": self._jarm, "Type": "jarm", "Vendor": "JARM", "Score": Common.DBotScore.NONE, } } def to_minimum_context(self) -> dict[str, Any]: return { "Indicator": self._jarm, "Type": "jarm", } host = args.get("host") if not host: raise ValueError("Host name (IP or domain) not specified") port = arg_to_number(args.get("port")) target = parse_hostname(host, port) target_type = target.get("target_type") if not target_type: raise ValueError("Cannot determine scan target") target_host = target.get("target_host") if not target_host: raise ValueError("Cannot determine scan target") port = target.get("port") if not port: raise ValueError("Invalid port provided") result = client.jarm_fingerprint(target_host, port) output = {} output["Fingerprint"] = result[0] output["Target"] = f"{target_host}:{port}" output["Port"] = port if target_type == "ip": output["IP"] = target_host elif target_type == "fqdn": output["FQDN"] = target_host return CommandResults( outputs_prefix="JARM", outputs_key_field=["FQDN", "IP", "Port"], outputs=output, indicator=JARMDBotScore(output=output) ) """ MAIN FUNCTION """ def main() -> None: command = demisto.command() demisto.debug(f"Command being called is {command}") try: handle_proxy() client = Client() if command == "test-module": # This is the call made when pressing the integration Test button. return_results(test_module(client)) elif command == "jarm-fingerprint": return_results(jarm_fingerprint_command(client, demisto.args())) else: raise NotImplementedError(f"Command {command} is not implemented.") # Log exceptions and return errors except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f"Failed to execute {demisto.command()} command.\nError:\n{e!s}") """ ENTRY POINT """ if __name__ in ("__main__", "__builtin__", "builtins"): main()