ThreatMiner
Data Mining for Threat Intelligence.
Data Enrichment & Threat Intelligence · ThreatMiner
Details
| ID | ThreatMiner |
|---|---|
| Provider | ThreatConnect |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Data Mining for Threat Intelligence
Configure ThreatMiner in Cortex
| Parameter | Description | Required |
|---|---|---|
| Maximum results per query, enter ‘all’ to get unlimited results | False | |
| Source Reliability | Reliability of the source providing the intelligence data. | True |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| ThreatMiner API URL | 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
Retrieves data from ThreatMiner about a specified domain.
Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.
Base Command
domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Domain name to get information for. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatMiner.Domain.Whois.Server | string | Whois server address. |
| ThreatMiner.Domain.Whois.CreateDate | date | Creation date. |
| ThreatMiner.Domain.Whois.UpdateDate | date | Last update date. |
| ThreatMiner.Domain.Whois.Expiration | date | Expiration date. |
| ThreatMiner.Domain.Whois.NameServers | string | Whois name servers. |
| ThreatMiner.Domain.PassiveDNS.IP | string | Passive DNS IP address. |
| ThreatMiner.Domain.PassiveDNS.FirstSeen | date | Passive DNS first seen date. |
| ThreatMiner.Domain.PassiveDNS.LastSeen | date | Passive DNS last seen date. |
| ThreatMiner.Domain.Subdomains | string | Subdomains. |
| ThreatMiner.Domain.URI.Address | string | Related URIs. |
| ThreatMiner.Domain.URI.LastSeen | string | URI last seen date. |
| ThreatMiner.Domain.MD5 | string | Related samples’ MD5 hash. |
| Domain.Name | string | Searched domain name |
| ThreatMiner.Domain.Whois.Domain | string | Domain name that was searched. |
| Domain.DNS | unknown | IPs resolved by DNS. |
| Domain.Whois.CreateDate | date | Creation date. |
| Domain.Whois.UpdateDate | date | Last update date. |
| Domain.Whois.Expiration | date | Expiration date. |
| Domain.Whois.Registrant.Name | string | Name of the registrant |
| Domain.Whois.Registrant.Email | string | Email of the registrant |
| 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. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
ip
Retrieves data from ThreatMiner about a specified IP address.
Base Command
ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | IP address to get information for. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatMiner.IP.Address | string | IP address that was searched. |
| ThreatMiner.IP.Whois.Reverse | string | Whois reverse name. |
| ThreatMiner.IP.Whois.Bgp | string | BGP prefix. |
| ThreatMiner.IP.Whois.Country | string | Related country. |
| ThreatMiner.IP.Whois.ASN | string | Related ASN. |
| ThreatMiner.IP.Whois.Org | string | Organization name. |
| ThreatMiner.IP.PassiveDNS.Domain | string | PassiveDNS domain. |
| ThreatMiner.IP.PassiveDNS.FirstSeen | date | Passive DNS first seen date. |
| ThreatMiner.IP.PassiveDNS.LastSeen | date | Passive DNS last seen date. |
| ThreatMiner.IP.URI.Address | string | Related URIs. |
| ThreatMiner.IP.URI.LastSeen | date | URI last seen date. |
| ThreatMiner.IP.MD5 | string | Related samples MD5 hash. |
| ThreatMiner.IP.SSL | string | SSL certificates. |
| 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. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| IP.Address | unknown | IP address that was searched. |
| IP.Geo.Country | unknown | Related country. |
| IP.ASN | unknown | Related ASN. |
file
Retrieves data from ThreatMiner about a specified file.
Base Command
file
Input
| Argument Name | Description | Required |
|---|---|---|
| file | File hash (md5, sha1, sha256). | Required |
| threshold | If ThreatScore is greater or equal than the threshold, then file will be considered malicious. Default is 10. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatMiner.File.MD5 | string | File MD5 hash. |
| ThreatMiner.File.SHA1 | string | File SHA1 hash. |
| ThreatMiner.File.SHA256 | string | File SHA256 hash. |
| ThreatMiner.File.Type | string | File type. |
| ThreatMiner.File.Name | string | File name. |
| ThreatMiner.File.Architecture | string | File architecture. |
| ThreatMiner.File.Size | string | File size. |
| ThreatMiner.File.Analyzed | date | File analyzed date. |
| ThreatMiner.File.HTTP.Domain | string | HTTP traffic to domain. |
| ThreatMiner.File.HTTP.URL | string | HTTP traffic to URL. |
| ThreatMiner.File.HTTP.Useragent | string | HTTP user agent. |
| ThreatMiner.File.Domains.IP | string | Related IP address. |
| ThreatMiner.File.Domains.Domain | string | Related domain name. |
| ThreatMiner.File.Mutants | string | Used mutexes. |
| ThreatMiner.File.Registry | string | Used registry keys. |
| ThreatMiner.File.AV.Name | string | Detected AV name. |
| ThreatMiner.File.AV.Detection | string | AV detection. |
| File.MD5 | string | File MD5 hash. |
| File.SHA1 | string | File SHA1 hash. |
| File.SHA256 | string | File SHA256 hash. |
| File.Malicious.Detections | number | For malicious files, the total number of detections. |
| File.Malicious.Vendor | string | For malicious files, the vendor that made the decision. |
| 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. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| File.Name | string | File name. |
Configuration parameters
limit_results— Maximum results per query, enter 'all' to get unlimited resultsintegrationReliability— Source Reliability (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settingsthreatminer_url— ThreatMiner API URL (required)
Commands (3)
-
domainRetrieves data from ThreatMiner about a specified domain.
-
fileRetrieves data from ThreatMiner about a specified file.
-
ipRetrieves data from ThreatMiner about a specified IP address.
import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 """ IMPORTS """ # disable insecure warnings urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) DEFAULT_HEADERS = {"Content-Type": "application/json"} """ HELPER FUNCTIONS """ def http_request(method, url, verify_certificates, headers): try: res = requests.request(method, url, verify=verify_certificates, headers=headers) if res.status_code == 200: return res.json() # 204 HTTP status code is returned when api rate limit has been exceeded elif res.status_code == 204: return_error("You've reached your API call quota.") elif res.status_code == 404: return {} res.raise_for_status() except Exception as e: demisto.results( { "Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": f"error has occured: {e}", } ) def get_domain_report_from_threat_miner(domain_name, threat_miner_url, verify_certificates): return { "raw_whois": get_domain_whois_rawdata(domain_name, threat_miner_url, verify_certificates), "raw_passive_dns": get_domain_passive_dns_rawdata(domain_name, threat_miner_url, verify_certificates), "raw_sub_domains": get_domain_subdomains_rawdata(domain_name, threat_miner_url, verify_certificates), "raw_domain_uris": get_domain_URI_rawdata(domain_name, threat_miner_url, verify_certificates), "raw_domain_md5": get_domain_MD5_rawdata(domain_name, threat_miner_url, verify_certificates), } def get_domain_whois_rawdata(domain_name, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"domain.php?q={domain_name}&rt={1}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) domain_whois = response.get("results", []) if len(domain_whois) == 0: return {} return domain_whois[0] def get_domain_passive_dns_rawdata(domain_name, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"domain.php?q={domain_name}&rt={2}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) threatminer_results_as_array = response.get("results", []) if len(threatminer_results_as_array) == 0: return [] return threatminer_results_as_array def get_domain_passive_dns(passive_dns, max_returned_array_size): if max_returned_array_size == -1: return passive_dns["raw_passive_dns"] return passive_dns["raw_passive_dns"][:max_returned_array_size] def get_domain_subdomains_rawdata(domain_name, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"domain.php?q={domain_name}&rt={5}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) sub_domains_array = response.get("results", []) return sub_domains_array def get_domain_URI_rawdata(domain_name, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"domain.php?q={domain_name}&rt={3}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) uris_full_result = response.get("results", []) return uris_full_result def get_domain_URI(uris_raw_data, max_returned_array_size): uri_counter = 0 uris = [] for uri_info in uris_raw_data["raw_domain_uris"]: if max_returned_array_size == -1 or uri_counter < max_returned_array_size: uris.append({"Address": uri_info["uri"], "LastSeen": uri_info["last_seen"]}) uri_counter += 1 else: break return uris def get_domain_MD5_rawdata(domain_name, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"domain.php?q={domain_name}&rt={4}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) md5s = response.get("results", []) return md5s def create_domain_command_markdown(domain, context): md = f"## Threat_miner Domain report for: {domain}\n" threat_miner_found_results = False if len(context.get("Whois", "")) != 0: md += tableToMarkdown( f"Whois for {domain} domain", context["Whois"], ["Domain", "Server", "CreateDate", "UpdateDate", "Expiration", "NameServers"], ) threat_miner_found_results = True if len(context.get("PassiveDNS", "")) != 0: md += tableToMarkdown(f"PassiveDNS for {domain} domain", context["PassiveDNS"], ["IP", "FirstSeen", "LastSeen"]) threat_miner_found_results = True if len(context.get("Subdomains", "")) != 0: md += tableToMarkdown(f"{domain} Subdomains", context["Subdomains"], ["Subdomains"]) threat_miner_found_results = True if len(context.get("URI", "")) != 0: md += tableToMarkdown(f"{domain} URIs", context["URI"], ["Address", "LastSeen"]) threat_miner_found_results = True if len(context.get("MD5", "")) != 0: md += tableToMarkdown(f"{domain} Related Samples(hash only)", context["MD5"], ["hashes"]) threat_miner_found_results = True if not threat_miner_found_results: md += "No results found" return md def domain_command(**kwargs): domains_names = demisto.args().get("domain") domains_names_list = argToList(domains_names) domains_results = [] for domain_name in domains_names_list: threat_miner_raw_results = get_domain_report_from_threat_miner( domain_name, kwargs.get("threat_miner_url"), kwargs.get("verify_certificates") ) passive_dns = {} subdomains = {} md5s = {} max_returned_array_size = kwargs.get("max_array_size") if max_returned_array_size == -1: passive_dnses = threat_miner_raw_results["raw_passive_dns"] subdomains = threat_miner_raw_results["raw_sub_domains"] md5s = threat_miner_raw_results["raw_domain_md5"] else: passive_dnses = threat_miner_raw_results["raw_passive_dns"][:max_returned_array_size] subdomains = threat_miner_raw_results["raw_sub_domains"][:max_returned_array_size] md5s = threat_miner_raw_results["raw_domain_md5"][:max_returned_array_size] context_passive_dnses = [] for passive_dns in passive_dnses: context_passive_dnses.append( {"IP": passive_dns["ip"], "FirstSeen": passive_dns["first_seen"], "LastSeen": passive_dns["last_seen"]} ) threat_miner_context = { "Name": domain_name, "Whois": { "Server": threat_miner_raw_results["raw_whois"]["whois"]["whois_server"], "CreateDate": threat_miner_raw_results["raw_whois"]["whois"]["creation_date"], "UpdateDate": threat_miner_raw_results["raw_whois"]["whois"]["updated_date"], "Expiration": threat_miner_raw_results["raw_whois"]["whois"]["expiration_date"], "NameServers": threat_miner_raw_results["raw_whois"]["whois"]["nameservers"], }, "PassiveDNS": context_passive_dnses, "Subdomains": subdomains, "URI": get_domain_URI(threat_miner_raw_results, max_returned_array_size), "MD5": md5s, } passive_dnses_ips = [] for passive_dns in passive_dnses: passive_dnses_ips.append(passive_dns["ip"]) domain_context = { "Name": threat_miner_context["Name"], "DNS": passive_dnses_ips, "Whois": { "UpdateDate": threat_miner_context["Whois"]["UpdateDate"], "CreateDate": threat_miner_context["Whois"]["CreateDate"], "Expiration": threat_miner_context["Whois"]["Expiration"], "Registrant": { "Name": threat_miner_raw_results["raw_whois"]["whois"]["tech_info"]["Organization"], "Email": threat_miner_raw_results["raw_whois"]["whois"]["emails"]["registrant"], }, }, } context = { "ThreatMiner.Domain(val.Name && val.Name == obj.Name)": threat_miner_context, "Domain(val.Name && val.Name == obj.Name)": domain_context, } markdown = create_domain_command_markdown(domain_name, threat_miner_context) result = { "Type": entryTypes["note"], "Contents": threat_miner_raw_results, "HumanReadable": markdown, "EntryContext": context, "ContentsFormat": formats["json"], } domains_results.append(result) demisto.results(domains_results) def get_ip_whois_rawdata(ip_address, threat_miner_url, verify_certificates): threat_miner_ip_url_postfix = f"host.php?q={ip_address}&rt={1}" response = http_request("GET", threat_miner_url + threat_miner_ip_url_postfix, verify_certificates, DEFAULT_HEADERS) whois_rawdata = response.get("results", []) if len(whois_rawdata) > 0: return whois_rawdata[0] return {} def get_ip_whois(whois_rawdata, ip_address): ip_whois_results = {} ip_whois_results["Address"] = ip_address ip_whois_results["Reverse"] = whois_rawdata["raw_whois"]["reverse_name"] ip_whois_results["Bgp"] = whois_rawdata["raw_whois"]["bgp_prefix"] ip_whois_results["Country"] = whois_rawdata["raw_whois"]["cc"] ip_whois_results["ASN"] = whois_rawdata["raw_whois"]["asn"] ip_whois_results["Org"] = whois_rawdata["raw_whois"]["org_name"] return ip_whois_results def get_ip_passiveDNS_rawdata(ip_address, threat_miner_url, verify_certificates): threat_miner_ip_url_postfix = f"host.php?q={ip_address}&rt={2}" response = http_request("GET", threat_miner_url + threat_miner_ip_url_postfix, verify_certificates, DEFAULT_HEADERS) passiveDNSArray = response.get("results", []) return passiveDNSArray def get_ip_URI_rawdata(ip_address, threat_miner_url, verify_certificates): threat_miner_ip_url_postfix = f"host.php?q={ip_address}&rt={3}" response = http_request("GET", threat_miner_url + threat_miner_ip_url_postfix, verify_certificates, DEFAULT_HEADERS) uris_rawdata = response.get("results", []) return uris_rawdata def get_ip_URI(threatminer_results_as_array, max_returned_array_size): uri_counter = 0 URIs = [] for _ in threatminer_results_as_array["raw_ip_uris"]: if max_returned_array_size == -1 or uri_counter < max_returned_array_size: URIs.append( { "Address": threatminer_results_as_array["raw_ip_uris"][uri_counter]["uri"], "LastSeen": threatminer_results_as_array["raw_ip_uris"][uri_counter]["last_seen"], } ) uri_counter += 1 else: break return URIs def get_ip_MD5_rawdata(ip_address, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"host.php?q={ip_address}&rt={4}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) md5s = response.get("results", []) if len(md5s) == 0: return [] return md5s def get_ip_SSL_rawdata(ip_address, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"host.php?q={ip_address}&rt={5}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) ssls_raw_data = response.get("results", []) return ssls_raw_data def create_ip_command_markdown(ip_address, context): md = f"## Threat_miner IP report for: {ip_address}\n" threat_miner_found_results = False if len(context["Whois"]) != 0: md += tableToMarkdown(f"Whois for {ip_address}", context["Whois"], ["Address", "Country", "Org", "Bgp", "Reverse", "ASN"]) threat_miner_found_results = True if len(context["PassiveDNS"]) != 0: md += tableToMarkdown(f"PassiveDNS for {ip_address}", context["PassiveDNS"], ["Domain", "FirstSeen", "LastSeen"]) threat_miner_found_results = True if len(context["URI"]) != 0: md += tableToMarkdown(f"{ip_address} URIs", context["URI"], ["Address", "LastSeen"]) threat_miner_found_results = True if len(context["MD5"]) != 0: md += tableToMarkdown(f"{ip_address} MD5s", context["MD5"], ["MD5"]) threat_miner_found_results = True if len(context["SSL"]) != 0: md += tableToMarkdown(f"{ip_address} SSLs", context["SSL"], ["SSL"]) threat_miner_found_results = True if not threat_miner_found_results: md += "No results found" return md def get_ip_report_from_threat_miner(ip_address, threat_miner_url, verify_certificates): return { "raw_whois": get_ip_whois_rawdata(ip_address, threat_miner_url, verify_certificates), "raw_passive_dns": get_ip_passiveDNS_rawdata(ip_address, threat_miner_url, verify_certificates), "raw_ip_md5": get_ip_MD5_rawdata(ip_address, threat_miner_url, verify_certificates), "raw_ip_uris": get_ip_URI_rawdata(ip_address, threat_miner_url, verify_certificates), "raw_ip_ssl": get_ip_SSL_rawdata(ip_address, threat_miner_url, verify_certificates), } def get_passive_dns(threat_miner_raw_results): passive_dnses = [] for passive_dns in threat_miner_raw_results["raw_passive_dns"]: passive_dnses.append( {"Domain": passive_dns["domain"], "FirstSeen": passive_dns["first_seen"], "LastSeen": passive_dns["last_seen"]} ) return passive_dnses def validate_ips(ips): invalid_ips = [] for ip in ips: if not is_ip_valid(ip): invalid_ips.append(ip) if invalid_ips: return_error(f"An invalid IP(s) was specified: {invalid_ips}") def ip_command(**kwargs): ips_address = demisto.args().get("ip") ips_address_list = argToList(ips_address) validate_ips(ips_address_list) ips_address_results = [] for ip_address in ips_address_list: threat_miner_raw_results = get_ip_report_from_threat_miner( ip_address, kwargs.get("threat_miner_url"), kwargs.get("verify_certificates") ) passiveDnses = get_passive_dns(threat_miner_raw_results) md5s = {} ssls = {} max_returned_array_size = kwargs.get("max_array_size") if max_returned_array_size == -1: passiveDns = passiveDnses md5s = threat_miner_raw_results["raw_ip_md5"] ssls = threat_miner_raw_results["raw_ip_ssl"] else: ssls = threat_miner_raw_results["raw_ip_ssl"][:max_returned_array_size] passiveDns = passiveDnses[:max_returned_array_size] md5s = threat_miner_raw_results["raw_ip_md5"][:max_returned_array_size] threat_miner_context = { "Address": ip_address, "Whois": { "Address": ip_address, "Reverse": threat_miner_raw_results["raw_whois"].get("reverse_name"), "Bgp": threat_miner_raw_results["raw_whois"].get("bgp_prefix"), "Country": threat_miner_raw_results["raw_whois"].get("cc"), "ASN": threat_miner_raw_results["raw_whois"].get("asn"), "Org": threat_miner_raw_results["raw_whois"].get("org_name"), }, "PassiveDNS": passiveDns, "MD5": md5s, "URI": get_ip_URI(threat_miner_raw_results, max_returned_array_size), "SSL": ssls, } markdown = create_ip_command_markdown(ip_address, threat_miner_context) ipcontext = { "IP.Address": threat_miner_context["Address"], "IP.Geo.Country": threat_miner_context["Whois"]["Country"], "IP.ASN": threat_miner_context["Whois"]["ASN"], } context = { "ThreatMiner.IP(val.Address && val.Address == obj.Address)": threat_miner_context, "IP(val.Address && val.Address == obj.Address)": ipcontext, } result = { "Type": entryTypes["note"], "Contents": threat_miner_raw_results, "HumanReadable": markdown, "EntryContext": context, "ContentsFormat": formats["json"], } ips_address_results.append(result) demisto.results(ips_address_results) def get_file_whois_rawdata(hashed_file, threat_miner_url, verify_certificates): threat_miner_ip_url_postfix = f"sample.php?q={hashed_file}&rt={1}" response = http_request("GET", threat_miner_url + threat_miner_ip_url_postfix, verify_certificates, DEFAULT_HEADERS) threatminer_results_as_array = response.get("results", []) if len(threatminer_results_as_array) == 0: return {} return threatminer_results_as_array[0] def get_file_http_rawdata(hashed_file, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"sample.php?q={hashed_file}&rt={2}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) file_http_raw_data = response.get("results", []) return file_http_raw_data def get_file_http(file_http_raw_data, max_returned_array_size): if len(file_http_raw_data["raw_file_https"]) == 0: return [] file_http = file_http_raw_data["raw_file_https"][0] http_traffics = file_http["http_traffic"] http_traffic_counter = 0 http_traffics_info = [] for _ in http_traffics: if max_returned_array_size == -1 or http_traffic_counter < max_returned_array_size: http_traffics_info.append( { "Domain": http_traffics[http_traffic_counter]["domain"], "URL": http_traffics[http_traffic_counter]["url"], "Useragent": http_traffics[http_traffic_counter]["user_agent"], } ) http_traffic_counter += 1 else: break return http_traffics_info def get_file_domains_and_ip_rawdata(hashed_file, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"sample.php?q={hashed_file}&rt={3}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) domain_and_ip_raw_data = response.get("results", []) return domain_and_ip_raw_data def get_file_domains_and_ip(domain_and_ip_raw_data, max_returned_array_size): if len(domain_and_ip_raw_data["raw_file_domains"]) == 0: return {} counter = 0 domains_and_ips = [] for domain_and_ip in domain_and_ip_raw_data["raw_file_domains"][0]["domains"]: if max_returned_array_size == -1 or counter < max_returned_array_size: domains_and_ips.append({"Domain": domain_and_ip["domain"], "IP": domain_and_ip["ip"]}) else: break return domains_and_ips def get_file_mutants_rawdata(hashed_file, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"sample.php?q={hashed_file}&rt={4}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) mutants_rawdata = response.get("results", []) return mutants_rawdata def get_file_mutants(mutants_rawdata, max_returned_array_size): if len(mutants_rawdata["raw_file_mutants"]) == 0: return {} file_mutants = mutants_rawdata["raw_file_mutants"][0] if max_returned_array_size == -1: return file_mutants["mutants"] return file_mutants["mutants"][:max_returned_array_size] def get_file_registry_keys_rawdata(hashed_file, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"sample.php?q={hashed_file}&rt={5}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) threatminer_results_as_array = response.get("results", []) if len(threatminer_results_as_array) == 0: return {} return threatminer_results_as_array[0] def get_file_registry_keys(file_registry_keys, max_returned_array_size): if len(file_registry_keys["raw_file_registry"]) == 0: return {} if max_returned_array_size == -1: return file_registry_keys["raw_file_registry"]["registry_keys"] return file_registry_keys["raw_file_registry"]["registry_keys"][:max_returned_array_size] def get_file_AV_detection_rawdata(hashed_file, threat_miner_url, verify_certificates): threat_miner_domain_url_postfix = f"sample.php?q={hashed_file}&rt={6}" response = http_request("GET", threat_miner_url + threat_miner_domain_url_postfix, verify_certificates, DEFAULT_HEADERS) raw_file_av_dectection = response.get("results", {}) return raw_file_av_dectection def get_file_AV_detection(raw_file_av_dectection): if len(raw_file_av_dectection["raw_file_av"]) == 0: return {} av_detections = [] for av_detection in raw_file_av_dectection["raw_file_av"][0]["av_detections"]: av_detections.append({"Name": av_detection["av"], "Detection": av_detection["detection"]}) return av_detections def get_file_report_from_threat_miner(hashed_file, threat_miner_url, verify_certificates): return { "raw_whois": get_file_whois_rawdata(hashed_file, threat_miner_url, verify_certificates), "raw_file_https": get_file_http_rawdata(hashed_file, threat_miner_url, verify_certificates), "raw_file_domains": get_file_domains_and_ip_rawdata(hashed_file, threat_miner_url, verify_certificates), "raw_file_mutants": get_file_mutants_rawdata(hashed_file, threat_miner_url, verify_certificates), "raw_file_registry": get_file_registry_keys_rawdata(hashed_file, threat_miner_url, verify_certificates), "raw_file_av": get_file_AV_detection_rawdata(hashed_file, threat_miner_url, verify_certificates), } def get_dbot_scores_context(threat_miner_raw_results, file_context, hashed_file, reliability): amount_of_detections = len(threat_miner_raw_results.get("AV", "")) dbot_scores = get_dbot_score_report(amount_of_detections, hashed_file, file_context, reliability) return dbot_scores def file_command(**kwargs): hashed_files = demisto.args().get("file") hashed_files_list = argToList(hashed_files) hashed_files_results = [] for hashed_file in hashed_files_list: threat_miner_raw_results = get_file_report_from_threat_miner( hashed_file, kwargs.get("threat_miner_url"), kwargs.get("verify_certificates") ) max_returned_array_size = kwargs.get("max_array_size") threat_miner_context = { "MD5": threat_miner_raw_results["raw_whois"].get("md5", ""), "Architecture": threat_miner_raw_results["raw_whois"].get("architecture", ""), "SHA1": threat_miner_raw_results["raw_whois"].get("sha1", ""), "SHA256": threat_miner_raw_results["raw_whois"].get("sha256", ""), "Type": threat_miner_raw_results["raw_whois"].get("file_type", ""), "Name": threat_miner_raw_results["raw_whois"].get("file_name", ""), "Size": threat_miner_raw_results["raw_whois"].get("file_size", ""), "Analyzed": threat_miner_raw_results["raw_whois"].get("date_analysed", ""), "HTTP": get_file_http(threat_miner_raw_results, max_returned_array_size), "Domains": get_file_domains_and_ip(threat_miner_raw_results, max_returned_array_size), "Mutants": get_file_mutants(threat_miner_raw_results, max_returned_array_size), "Registry": get_file_registry_keys(threat_miner_raw_results, max_returned_array_size), "AV": get_file_AV_detection(threat_miner_raw_results), } markdown = create_file_command_markdown(hashed_file, threat_miner_context) file_context = { "MD5": threat_miner_raw_results["raw_whois"].get("md5", ""), "Architecture": threat_miner_raw_results["raw_whois"].get("architecture", ""), "SHA1": threat_miner_raw_results["raw_whois"].get("sha1", ""), "SHA256": threat_miner_raw_results["raw_whois"].get("sha256", ""), "Type": threat_miner_raw_results["raw_whois"].get("file_type", ""), "Name": threat_miner_raw_results["raw_whois"].get("file_name", ""), "Size": threat_miner_raw_results["raw_whois"].get("file_size", ""), "Analyzed": threat_miner_raw_results["raw_whois"].get("date_analysed", ""), } dbot_scores = get_dbot_scores_context(threat_miner_context, file_context, hashed_file, kwargs.get("reliability")) context = { "ThreatMiner.File(val.MD5 && val.MD5 == obj.MD5)": threat_miner_context, "File(val.MD5 && val.MD5 == obj.MD5)": file_context, "DBotScore": dbot_scores, } result = { "Type": entryTypes["note"], "Contents": threat_miner_raw_results, "HumanReadable": markdown, "EntryContext": context, "ContentsFormat": formats["json"], } hashed_files_results.append(result) demisto.results(hashed_files_results) def get_dbot_score_report(amount_of_detections, hashed_file, file_context, reliability): dbot = {} dbot_score = get_dbot_score(amount_of_detections) dbot["Score"] = dbot_score dbot["Indicator"] = hashed_file dbot["Type"] = "File" dbot["Vendor"] = "ThreatMiner" dbot["Reliability"] = reliability if dbot_score == 3: file_context["Malicious"] = {} file_context["Malicious"]["Vendor"] = "ThreatMiner" file_context["Malicious"]["Detections"] = amount_of_detections return dbot def get_dbot_score(amount_of_detections): malicious_threshold = int(demisto.args().get("threshold")) if amount_of_detections == 0: return 0 if amount_of_detections > 0 and amount_of_detections < malicious_threshold: return 2 if amount_of_detections >= malicious_threshold: # noqa: RET503 return 3 def create_file_command_markdown(hashed_file, File_context): md = f"## Threat_miner file report for hashed file: {hashed_file}\n" threat_miner_found_results = False md += "\n" md += f"**File MD5:** {hashed_file}" md += "\n" md += "**File Architecture:** {}".format(File_context.get("Architecture", "Unkown")) md += "\n" md += "**File SHA1:** {}".format(File_context.get("Sha1", "Unknown")) md += "\n" md += "**File SHA256:** {}".format(File_context.get("Sha256", "Unkown")) md += "\n" md += "**File Type:** {}".format(File_context.get("Type", "Unkown")) md += "\n" md += "**File Name:** {}".format(File_context.get("Name", "Unkown")) md += "\n" md += "**File Size:** {}".format(File_context.get("Size", "Unkown")) md += "\n" md += "**File Analyzed:** {}".format(File_context.get("Analyzed", "Unkown")) if len(File_context.get("HTTP", "")) != 0: md += tableToMarkdown(f"HTTP for hashed file {hashed_file}", File_context["HTTP"], ["Domain", "URL", "Useragent"]) threat_miner_found_results = True if len(File_context.get("Domains", "")) != 0: md += tableToMarkdown(f"Hashed file: {hashed_file} Domains", File_context["Domains"], ["Domain", "IP"]) threat_miner_found_results = True if len(File_context.get("Mutants", "")) != 0: md += tableToMarkdown(f"Hashed file: {hashed_file} Mutants", File_context["Mutants"], ["Mutants"]) threat_miner_found_results = True if len(File_context.get("Registry", "")) != 0: md += tableToMarkdown(f"Hashed file: {hashed_file} Registry keys", File_context["Registry"], ["Registry"]) threat_miner_found_results = True if len(File_context.get("AV", "")) != 0: md += tableToMarkdown(f"Hashed file: {hashed_file} Anti Virus detections", File_context["AV"], ["Name", "Detection"]) threat_miner_found_results = True if not threat_miner_found_results: md += "No results found" return md def delete_proxy_if_asked(): if not demisto.params()["proxy"]: # Remove proxy environment variables if they exist for proxy_var in ["HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"]: os.environ.pop(proxy_var, None) """ EXECUTION CODE """ def main(): try: demisto_params = demisto.params() params = { "threat_miner_url": demisto_params.get("threatminer_url"), "verify_certificates": not demisto_params.get("insecure"), } reliability = demisto_params.get("integrationReliability") reliability = reliability if reliability else DBotScoreReliability.C if DBotScoreReliability.is_valid_type(reliability): params["reliability"] = DBotScoreReliability.get_dbot_score_reliability_from_str(reliability) else: Exception("Please provide a valid value for the Source Reliability parameter.") delete_proxy_if_asked() demisto_command = demisto.command() if demisto_command == "test-module": report = get_ip_whois_rawdata("8.8.8.8", params["threat_miner_url"], params["verify_certificates"]) if "asn" in report: demisto.results("ok") else: demisto.results("test failed") if demisto_params.get("limit_results").lower() == "all": params["max_array_size"] = -1 else: params["max_array_size"] = int(demisto_params.get("limit_results", 30)) if demisto_command == "domain": domain_command(**params) if demisto_command == "ip": ip_command(**params) if demisto_command == "file": file_command(**params) except Exception as e: return_error(f"An error has occurred: {e}") if __name__ in ["__main__", "__builtin__", "builtins"]: main()