BitDam
BitDam secure email gateway protects from advanced content-borne threats with the most accurate prevention of known and unknown threats, at their source.
IT Services · BitDam
Details
| ID | BitDam |
|---|---|
| Provider | Kaseya |
| Category | IT Services |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.8.3296088 |
| Supported Modules | Agentix XSIAM |
README
Overview
BitDam cyber security blocks advanced content-borne attacks across all enterprise communication channels, empowering organisations to collaborate safely. Founded by elite intelligence professionals, BitDam proactively stops malware from running, pre-delivery, preventing hardware and logical exploits, ransomware, phishing, N-Day and Zero-Day attacks contained in any type of attachment or URL. BitDam ensures the highest attack detection rates and delivers the fastest protection from today’s email borne attacks making enterprise communications safe to click.
For more information, see the BitDam documentation.
Use cases
Scan any supported time in a short time. The BitDam scan file playbook enables you to scan a file and return the result as soon as the file scan completes. This provides a decisive verdict, stating whether the file is benign or malicious.
Configure BitDam on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for BitDam.
- Click Add instance to create and configure a new integration instance.
- Name: a textual name for the integration instance.
- BitDam API URL
- API Token
- Trust any certificate
- Use proxy settings
- 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. Upload a file
Uploads and submits a file sample to the BitDam service.
Supported types
- doc, dot, docx, docm, dotx, dotm
- rtf
- xls, xlt, xlsx, xlsm, xltx, xltm, xlsb, xlam
- csv
- ppt, pptx, pptm, potx, potm, ppam, ppsx, ppsm, pps
Base Command
bitdam-upload-file
Input
| Argument Name | Description | Required |
|---|---|---|
| entryId | File's entry ID from the War Room | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| BitDam.FileScan.SHA1 | string | SHA-1 |
Command Example
!bitdam-upload-file entryId=499@16
Context Example
root:{} 3 items
BitDam:{} 1 item
FileScan:{} 1 item
SHA1:68f009dc92a405d1015026e8e30e6d1598047124
Human Readable Output
2. Get the verdict of a file
Returns the verdict of a scanned file.
Base Command
bitdam-get-verdict
Input
| Argument Name | Description | Required |
|---|---|---|
| idValue | The value of the file's unique identifier. Example: the file SHA-1. | Required |
| idType | Identifier type. Default is SHA-1. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| BitDam.Analysis.Status | string | Status of the analysis ("DONE" or "IN_PROGRESS") |
| BitDam.Analysis.Verdict | string | Final verdict of the analysis ("Clean", "Malicious", or empty if the analysis is not finished. |
| BitDam.Analysis.ID | string | Unique identifier |
| DBotScore.Indicator | string | The Indicator |
| DBotScore.Score | number | The DBot score |
| DBotScore.Type | string | The indicator type |
| DBotScore.Vendor | string | The DBot score vendor |
| File.Malicious.Name | string | File name |
| File.Malicious.Vendor | string | For malicious files, the vendor that made the decision |
| File.Malicious.Description | string | For malicious files, the reason that the vendor made the decision |
Command Example
!bitdam-get-verdict idValue=68f009dc92a405d1015026e8e30e6d1598047124
Context Example
root:{} 4 items
BitDam:{} 2 items
Analysis:{} 3 items
ID:68f009dc92a405d1015026e8e30e6d1598047124
Status:DONE
Verdict:CLEAN
FileScan:{} 1 item
SHA1:68f009dc92a405d1015026e8e30e6d1598047124
DBotScore:{} 4 items
Indicator:68f009dc92a405d1015026e8e30e6d1598047124
Score:1
Type:File
Vendor:BitDam
Human Readable Output
Configuration parameters
url— BitDam API URL (required)apitoken— API Token (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (2)
-
bitdam-get-verdictReturns the verdict for a scanned file.
-
bitdam-upload-fileUploads a file sample to the BitDam service.
import demistomock as demisto from CommonServerPython import * """IMPORTS""" import requests import base64 import urllib3 urllib3.disable_warnings() """INTEGRATION PARAMS""" API_TOKEN = demisto.params().get("apitoken") URL_BASE = demisto.params().get("url") USE_PROXY = demisto.params().get("proxy", False) UNSECURE = not demisto.params().get("insecure", False) """CONSTANTS""" READ_BINARY_MODE = "rb" SLASH = "/" SCAN_FILE_URL = "direct/scan/file/" GET_FILE_VERDICT_URL = "direct/verdict/?hash={}" TOKEN_PREFIX = "Bearer" # guardrails-disable-line RESPONSE_CODE_OK = 200 STATUS_IN_PROGRESS = "IN_PROGRESS" STATUS_DONE = "DONE" AUTH_HEADERS = {"Authorization": f"{TOKEN_PREFIX} {API_TOKEN}"} VERDICT_SCANNING = "Scanning" VERDICT_MALICIOUS = "Malicious" VERDICT_APPROVED = "Approved" VERDICT_ERROR = "Error" VERDICT_BENIGN = "Benign" VERDICT_TIMEOUT = "Timeout" SCAN_ONGOING = "Still scanning..." BITDAM_COMMAND_PREFIX = "bitdam" DBOTSCORE_UNKNOWN = 0 DBOTSCORE_CLEAN = 1 DBOTSCORE_MALICIOUS = 3 """HANDLE PROXY""" handle_proxy() """HELPER FUNCTIONS""" def get_file_bytes(entry_id): get_file_path_res = demisto.getFilePath(entry_id) file_path = get_file_path_res["path"] with open(file_path, READ_BINARY_MODE) as fopen: bytes = fopen.read() return base64.b64encode(bytes) def get_url_base_with_trailing_slash(): """ Returns the intergation's base url parameter, making sure it contains an trailing slash """ url_base = URL_BASE return url_base if url_base.endswith(SLASH) else url_base + SLASH def build_json_response(content, context, human_readable): return { "Type": entryTypes["note"], "ContentsFormat": formats["json"], "Contents": content, "ReadableContentsFormat": formats["markdown"], "HumanReadable": tableToMarkdown(human_readable, content), "EntryContext": context, } def get_file_name(entry_id): get_file_path_res = demisto.getFilePath(entry_id) return get_file_path_res["name"] def verdict_to_dbotscore(verdict): if verdict == VERDICT_APPROVED: return DBOTSCORE_CLEAN elif verdict == VERDICT_MALICIOUS: return DBOTSCORE_MALICIOUS elif verdict == VERDICT_SCANNING: return DBOTSCORE_UNKNOWN else: return DBOTSCORE_UNKNOWN """API_IMPL""" def scan_file(): response = scan_file_command() returned_sha1 = parse_scan_file_response(response) # Build demisto reponse response_content = {"SHA1": returned_sha1} response_context = {"BitDam": {"FileScan": {"SHA1": returned_sha1}}} return build_json_response(response_content, response_context, "File was submitted successfully") def scan_file_command(): # Get data to build the request entry_id = demisto.args().get("entryId") file_name = get_file_name(entry_id) file_bytes = get_file_bytes(entry_id) json_data = {"file_name": file_name, "file_data_base64": base64.b64encode(file_bytes)} raw_json = json.dumps(json_data, ensure_ascii=False) url = f"{get_url_base_with_trailing_slash()}{SCAN_FILE_URL}" # Send the HTTP request response = requests.post(url, data=raw_json, headers=AUTH_HEADERS, verify=UNSECURE) return response def parse_scan_file_response(response): # Parse response if response.status_code != RESPONSE_CODE_OK: raise Exception(f"Scan file failed. Response code -{str(response.status_code)}, Data- '{response.content}'") response_json = json.loads(response.content) if "sha1" not in response_json: raise Exception(f"Scan file failed. Bad response json - {response.content}") returned_sha1 = response_json["sha1"] return returned_sha1 def get_file_verdict(): identifier_value = demisto.args().get("idValue") response = get_file_verdict_command(identifier_value) verdict, status = parse_get_file_verdict_response(response) response_content = {"STATUS": status, "VERDICT": verdict, "ID": identifier_value} context = {} context["BitDam.Analysis(val.ID && val.ID == obj.ID)"] = {"Status": status, "Verdict": verdict, "ID": identifier_value} if verdict == VERDICT_MALICIOUS: context[outputPaths["file"]] = {"SHA1": identifier_value} context[outputPaths["file"]]["Malicious"] = { "Vendor": "BitDam", "Description": "Process whitelist inconsistency by bitdam-get-file-verdict", "Name": identifier_value, } dbotscore = verdict_to_dbotscore(verdict) if dbotscore: context[outputPaths["dbotscore"]] = { "Indicator": identifier_value, "Type": "File", "Vendor": "BitDam", "Score": dbotscore, } response_context = context return build_json_response(response_content, response_context, "Get file verdict was performed successfully") def parse_get_file_verdict_response(response): # Parse results if response.status_code != RESPONSE_CODE_OK: raise Exception(f"Get file verdict failed. Response code -{str(response.status_code)}, Data- '{response.content}'") response_json = json.loads(response.content) status = "" verdict = "" if "scan_data" not in response_json or "verdict" not in response_json["scan_data"]: raise Exception(f"Get file verdict failed. Unknown response schema. Data- '{response.content}'") verdict = response_json["scan_data"]["verdict"] if verdict in (SCAN_ONGOING, VERDICT_SCANNING): # Still in progress verdict = VERDICT_SCANNING status = STATUS_IN_PROGRESS else: status = STATUS_DONE return verdict, status def get_file_verdict_command(identifier_value): # Get data to build the request scan_file_relative_url_formatted = GET_FILE_VERDICT_URL.format(identifier_value) url = f"{get_url_base_with_trailing_slash()}{scan_file_relative_url_formatted}" # Send the request response = requests.get(url, headers=AUTH_HEADERS, verify=UNSECURE) return response def upload_test_file_to_scan(): d = {"file_name": "demisto.txt", "file_data_base64": "ZGVtaXN0bw=="} url = f"{get_url_base_with_trailing_slash()}{SCAN_FILE_URL}" response = requests.post(url, headers=AUTH_HEADERS, json=d, verify=UNSECURE) return response def test_module(): response = upload_test_file_to_scan() if response.status_code == RESPONSE_CODE_OK: return True raise Exception(f"Status code - {str(response.status_code)}, Error- '{response.content}'") """COMMAND_CLASIFIER""" try: if demisto.command() == "test-module": # This is the call made when pressing the integration test button. if test_module(): demisto.results("ok") sys.exit(0) elif demisto.command() == "bitdam-upload-file": demisto.results(scan_file()) elif demisto.command() == "bitdam-get-verdict": demisto.results(get_file_verdict()) except Exception as e: LOG(e) return_error(f"Error: {str(e)}")

