def put_file_command(api_client: CBCloudAPI, device_id: str, destination_path: str, file_id: str): session = api_client.select(platform.Device, device_id).lr_session() path = demisto.getFilePath(file_id) with open(path['path'], 'rb') as _file: session.put_file((path['name'], _file), destination_path) return f'File: {file_id} is successfully put to the remote destination {destination_path}'
def list_processes_command(api_client: CBCloudAPI, device_id: str, limit: Union[int, str]): session = api_client.select(platform.Device, device_id).lr_session() processes = session.list_processes() if not processes: return 'There is no active processes in the remote device' processes, partial_res_msg = get_limited_results( original_results=processes, limit=limit) headers = ['path', 'pid', 'command_line', 'username'] processes_readable = [ dict(path=process['process_path'], pid=process['process_pid'], command_line=process['process_cmdline'], user_name=process['process_username']) for process in processes ] context_entry = dict(device_id=device_id, processes=processes) readable_output = tableToMarkdown( f'Carbon Black Defense Live Response Processes{partial_res_msg}', headers=headers, t=processes_readable, headerTransform=string_to_table_header, removeNull=True) return CommandResults( 'CarbonBlackDefenseLR.Processes', outputs_key_field='device_id', outputs=context_entry, readable_output=readable_output, raw_response=processes, )
def get_reg_values_command(api_client: CBCloudAPI, device_id: str, reg_path: str, limit: Union[int, str]): """Get the values of the given registry key in the remote device""" session = api_client.select(platform.Device, device_id).lr_session() values = session.list_registry_values(reg_path) if not values: return f'The key: {reg_path} does not contain any value' values, partial_res_msg = get_limited_results(original_results=values, limit=limit) context_entry = dict(key=reg_path, values=values, device_id=device_id) human_readable = [ dict(name=val['registry_name'], type=val['registry_type'], data=val['registry_data']) for val in values ] readable_output = tableToMarkdown( f'Carbon Black Defense Live Response Registry key values{partial_res_msg}', human_readable, headers=['name', 'type', 'data'], headerTransform=string_to_table_header, removeNull=True) return CommandResults( outputs_prefix='CarbonBlackDefenseLR.RegistryValues', outputs_key_field=['device_id', 'key'], outputs=context_entry, readable_output=readable_output, raw_response=values, )
def list_directory_command(api_client: CBCloudAPI, device_id: str, directory_path: str, limit: Union[int, str]): """ Get list of directory entries in the remote device :param api_client: The API client :param device_id: The device id :param directory_path: Directory to list. This parameter should end with the path separator :param limit: Limit the result entries count to be the given limit :return: CommandResult represent the API command result :rtype: ``CommandResults`` """ session = api_client.select(platform.Device, device_id).lr_session() items = [ item for item in session.list_directory(directory_path) if item['filename'] not in IGNORED_FILES_IN_DIR ] items, partial_res_msg = get_limited_results(original_results=items, limit=limit) directories_readable = [] context_entry_items = [] headers = ['name', 'type', 'date_modified', 'size'] for item in items: context_entry_items.append(item) directories_readable.append({ 'name': item['filename'], 'type': 'Directory' if item['attributes'] and 'DIRECTORY' in item['attributes'] else 'File', 'date_modified': item['last_write_time'], 'size': item['size'], }) context_entry = dict(content=context_entry_items, device_id=device_id, directory_path=directory_path) readable_output = tableToMarkdown( f'Directory of {directory_path}{partial_res_msg}', t=directories_readable, headers=headers, headerTransform=string_to_table_header, removeNull=True) return CommandResults( outputs_prefix='CarbonBlackDefenseLR.Directory', outputs_key_field=['device_id', 'directory_path'], outputs=context_entry, readable_output=readable_output, raw_response=items, )
def kill_process_command(api_client: CBCloudAPI, device_id: str, pid: Union[int, str]): session = api_client.select(platform.Device, device_id).lr_session() success = session.kill_process(arg_to_number( pid)) # the API returns True if success, False if failure if not success: return_error(f'Can not kill the process: {pid}') return f'The process: {pid} was killed successfully.'
def _create_feed(auth_token): """Create a Feed to use for testing""" cb = CBCloudAPI(url="https://defense-eap01.conferdeploy.net", token=auth_token, org_key="WNEXFKQ7") # Feed Creation feedinfo = { "name": "Temporary BAT Load Test Feed", "owner": "DevRel", "provider_url": "https://developer.carbonblack.com", "summary": "BAT Load test feed", "category": "None", "access": "private" } feed_dict = {"feedinfo": feedinfo, "reports": []} feed = cb.create(Feed, feed_dict) feed.save() return feed._info
def _init_components(self): """ Initialize the components of the toolkit, injecting their dependencies as they're created. Returns: dict: A dict containing all the references to the top-level components. """ try: state_manager = StateManager(self.config) except: log.error( "Failed to create State Manager. Check your configuration") log.debug(traceback.format_exc()) state_manager = None cbc_api = self.cbc_api if cbc_api is None: cbc_api = CBCloudAPI( url=self.config.get("carbonblackcloud.url"), org_key=self.config.get("carbonblackcloud.org_key"), token=self.config.get("carbonblackcloud.api_token"), ssl_verify=self.config.get("carbonblackcloud.ssl_verify")) deduplicate = DeduplicationComponent(self.config, state_manager) ingest = IngestionComponent(self.config, cbc_api, state_manager) results_engine = EngineResults(self.config.get("engine.name"), state_manager, cbc_api) if self.config.get("engine.type") == "local": try: engine_manager = LocalEngineManager(self.config) except: log.error( "Failed to create Local Engine Manager. Check your configuration" ) log.debug(traceback.format_exc()) engine_manager = None else: engine_manager = None return { "deduplicate": deduplicate, "ingest": ingest, "engine_manager": engine_manager, "results_engine": results_engine, "state_manager": state_manager, "success": True if state_manager is not None and engine_manager is not None else False }
def set_reg_value_command(api_client: CBCloudAPI, device_id: str, reg_path: str, value_data: Any, value_type: str, overwrite: Union[bool, str]): session = api_client.select(platform.Device, device_id).lr_session() session.set_registry_value(reg_path, value_data, overwrite=argToBoolean(overwrite), value_type=value_type) return f'Value was set to the reg key: {reg_path} successfully.'
def delete_reg_key_command(api_client: CBCloudAPI, device_id: str, reg_path: str, force: Union[bool, str] = False): """Delete a registry key on the remote machine, the key must be without any sub keys""" session = api_client.select(platform.Device, device_id).lr_session() if argToBoolean(force): delete_reg_key_recursive(session, reg_path) else: session.delete_registry_key(reg_path) return f'Registry key: {reg_path} was deleted successfully.'
def get_file_command(api_client: CBCloudAPI, device_id: str, source_path: str, timeout: Union[int, str] = None, delay: Union[float, str] = None): session = api_client.select(platform.Device, device_id).lr_session() if delay: delay = float(delay) file_data = session.get_file(file_name=source_path, timeout=arg_to_number(timeout), delay=delay) file_name = ntpath.split(source_path)[1] return fileResult(file_name, file_data)
def get_cb_cloud_object(args): """ Based on parsed command line arguments, create and return a CBCloudAPI object. Args: args (Namespace): Arguments parsed from the command line. Returns: CBCloudAPI: The CBCloudAPI object. """ if args.verbose: logging.basicConfig() logging.getLogger("cbc_sdk").setLevel(logging.DEBUG) logging.getLogger("__main__").setLevel(logging.DEBUG) if args.cburl and args.apitoken and args.orgkey: cb = CBCloudAPI(url=args.cburl, token=args.apitoken, org_key=args.orgkey, ssl_verify=(not args.no_ssl_verify)) else: cb = CBCloudAPI(profile=args.profile) return cb
def main(): commands = { 'test-module': command_test_module, f'{CBD_LR_PREFIX}-file-put': put_file_command, f'{CBD_LR_PREFIX}-file-get': get_file_command, f'{CBD_LR_PREFIX}-file-delete': delete_file_command, f'{CBD_LR_PREFIX}-reg-key-create': create_reg_key_command, f'{CBD_LR_PREFIX}-reg-value-set': set_reg_value_command, f'{CBD_LR_PREFIX}-reg-sub-keys': list_reg_sub_keys_command, f'{CBD_LR_PREFIX}-reg-get-values': get_reg_values_command, f'{CBD_LR_PREFIX}-reg-value-delete': delete_reg_value_command, f'{CBD_LR_PREFIX}-reg-key-delete': delete_reg_key_command, f'{CBD_LR_PREFIX}-directory-listing': list_directory_command, f'{CBD_LR_PREFIX}-ps': list_processes_command, f'{CBD_LR_PREFIX}-kill': kill_process_command, f'{CBD_LR_PREFIX}-execute': create_process_command, f'{CBD_LR_PREFIX}-memdump': memdump_command } params = demisto.params() url = params.get('url') cb_custom_key = params.get('custom_key') cb_custom_id = params.get('custom_id') cb_org_key = params.get('org_key') verify_certificate = not params.get('insecure', True) handle_proxy() command = demisto.command() if command not in commands: raise NotImplementedError(f'Command: {command} not implemented') demisto.debug(f'Command being called is {command}') try: credentials = dict(url=url, ssl_verify=verify_certificate, token=f'{cb_custom_key}/{cb_custom_id}', org_key=cb_org_key) api = CBCloudAPI(**credentials) result = commands[command](api_client=api, **demisto.args()) # type: ignore return_results(result) # Log exceptions and return errors except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f'Failed to execute {command} command.\nError:\n{str(e)}')
def create_process_command(api_client: CBCloudAPI, device_id: str, command_string: str, wait_timeout: Union[int, str] = 30, wait_for_output: Union[bool, str] = True, wait_for_completion: Union[bool, str] = True, **additional_params): # additional_param may include: remote_output_file_name: str, working_directory: str session = api_client.select(platform.Device, device_id).lr_session() process_results_bytes = session.create_process( command_string=command_string, wait_timeout=arg_to_number(wait_timeout), wait_for_output=argToBoolean(wait_for_output), wait_for_completion=argToBoolean(wait_for_completion), **additional_params, ) process_results_str = None if wait_for_output and process_results_bytes: process_results_str = process_results_bytes.decode('utf-8') human_readable = process_results_str else: human_readable = f'Process: {command_string} was successfully executed.' context_output = dict( return_value=process_results_str, device_id=device_id, command_string=command_string, ) return CommandResults( outputs_prefix='CarbonBlackDefenseLR.ExecuteProcess', outputs_key_field=['device_id', 'command_string'], outputs=context_output, readable_output=human_readable, raw_response=process_results_str, )
def list_reg_sub_keys_command(api_client: CBCloudAPI, device_id: str, reg_path: str, limit: Union[int, str]): session = api_client.select(platform.Device, device_id).lr_session() sub_keys = session.list_registry_keys_and_values(reg_path).get( 'sub_keys', []) if not sub_keys: return f'The key: {reg_path} does not contain any sub keys' sub_keys, partial_res_msg = get_limited_results(original_results=sub_keys, limit=limit) context_entry = dict(sub_keys=sub_keys, device_id=device_id, key=reg_path) human_readable = tableToMarkdown( name= f'Carbon Black Defense Live Response Registry sub keys{partial_res_msg}', t=sub_keys, headers=['Sub keys']) return CommandResults( outputs_prefix='CarbonBlackDefenseLR.RegistrySubKeys', outputs_key_field=['device_id', 'key'], outputs=context_entry, readable_output=human_readable, raw_response=sub_keys, )
def cbc_cloud_api(): """Create CBCloudAPI singleton.""" return CBCloudAPI(url="https://example.com", org_key="test", token="abcd/1234", ssl_verify=False)
def delete_file_command(api_client: CBCloudAPI, device_id: str, source_path: str): session = api_client.select(platform.Device, device_id).lr_session() session.delete_file(filename=source_path) return f'The file: {source_path} was deleted successfully.'
def memdump_command(api_client: CBCloudAPI, device_id: str, target_path: str): session = api_client.select(platform.Device, device_id).lr_session() session.start_memdump(remote_filename=target_path).wait() return f'Memory was successfully dumped to {target_path}.'
from cbc_sdk import CBCloudAPI from cbapi.psc.defense import * ##### Call Yaml for configs ##### # Call yaml to pull in configs for proper hygiene with open('servicenow.yaml') as f: y = yaml.load(f) ###### Creds From Yaml ####### # Input your cbapi profile from yaml - make sure the connector type is 'SIEM' #!!! Use the below if using the new cb-sdk -- recommended !!!# cb = CBCloudAPI(profile=y['creds']['cb']['cb_profile']) #!!! Use the below profile, and comment out the above, if using the legacy cbapi !!!# #cb = CbDefenseAPI(profile=y['creds']['cb']['cb_profile']) # SN user and password user = y['creds']['sn']['sn_user'] pwd = y['creds']['sn']['sn_pwd'] ###### Variables ###### # SN inbound webservice api url sn_url = y['creds']['sn']['sn_url'] # Set proper headers headers = {"Content-Type":"application/json","Accept":"application/json"}
# CBC SDK Base from cbc_sdk import CBCloudAPI BOLD = "\033[1m" UNBOLD = "\033[0m" """Setup""" logging.basicConfig( filename="cloud_products_example_log.txt", format= '%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s', datefmt='%Y-%m-%d:%H:%M:%S', level=logging.INFO) # API keys with relevant permissions audit_remediation_api = CBCloudAPI(profile='audit_remediation') # Live Query live_response_api = CBCloudAPI(profile='live_response') # Live Response endpoint_standard_api = CBCloudAPI(profile='endpoint_standard') enterprise_edr_api = CBCloudAPI(profile='enterprise_edr') platform_api = CBCloudAPI(profile='platform') def platform(): """ Platform Alerts and Devices operations, using research from TAU. 1. Find Alerts matching Egregor ransomware, then 2. Find Alerts matching a harmless query (demonstration purposes). """ # Egregor ransomware tactics, techniques, and procedures (TTPs) identified by TAU egregor_ttps = (
def __init__(self): """Initialize the ThreatIntel class.""" self.cb = CBCloudAPI(timeout=200)
log.debug(json.dumps(res)) return res elif res["status"] == "error": raise LiveResponseError(res) else: time.sleep(delay) raise TimeoutError(uri=url, message="timeout polling for Live Response") if __name__ == "__main__": from cbc_sdk import CBCloudAPI from cbc_sdk.platform import Device import logging root = logging.getLogger() root.addHandler(logging.StreamHandler()) logging.getLogger("cbc_sdk").setLevel(logging.DEBUG) c = CBCloudAPI() j = GetFileJob(r"c:\test.txt") with c.select(Device, 3).lr_session() as lr_session: file_contents = lr_session.get_file(r"c:\test.txt") future = c.live_response.submit_job(j.run, 3) wait([ future, ]) print(future.result())
def create_reg_key_command(api_client: CBCloudAPI, device_id: str, reg_path: str): session = api_client.select(platform.Device, device_id).lr_session() session.create_registry_key(reg_path) return f'Reg key: {reg_path}, was created successfully.'
def main(): """Script entry point""" cb = CBCloudAPI(url=url, token=token, org_key=org_key, proxy=proxy, ssl_verify=False) assert type(cb.select(Device).first()) is Device print(f"Successfully fetched Device using proxy: {proxy}")
def delete_reg_value_command(api_client: CBCloudAPI, device_id: str, reg_path: str): session = api_client.select(platform.Device, device_id).lr_session() session.delete_registry_value(reg_path) return f'Registry value: {reg_path} was deleted successfully.'
class ThreatIntel: """Object handling Threat Intelligence.""" def __init__(self): """Initialize the ThreatIntel class.""" self.cb = CBCloudAPI(timeout=200) def verify_feed_exists(self, feed_id): """Verify that a Feed exists.""" try: feed = self.cb.select(Feed, feed_id) return feed except ApiError: raise ApiError def push_to_cb(self, feed_id, results): """Send result.AnalysisResult Reports or a Report dictionary to a Feed.""" feed = self.verify_feed_exists(feed_id) # will raise an ApiError if the feed cannot be found if not feed: return report_list_to_send = [] reports = [] malformed_reports = [] for result in results: report_dict = {} # convert to a dictionary if necessary if isinstance(result, AnalysisResult): try: report_dict = { "id": str(result.id), "timestamp": int(result.timestamp.timestamp()), "title": str(result.title), "description": str(result.description), "severity": int(result.severity), "iocs_v2": [ioc_v2.as_dict() for ioc_v2 in result.iocs_v2] } except Exception as e: log.error(f"Failed to create a report dictionary from result object. {e}") # no conversion to dictionary needed elif isinstance(result, dict): report_dict = result try: ReportSchema.validate(report_dict) # create Enterprise EDR Report object report = Report(self.cb, initial_data=report_dict, feed_id=feed_id) report_list_to_send.append(report) reports.append(report_dict) except SchemaError as e: log.warning(f"Report Validation failed. Saving report to file for reference. Error: {e}") malformed_reports.append(report_dict) log.debug(f"Num Reports: {len(report_list_to_send)}") try: with open('reports.json', 'w') as f: json.dump(reports, f, indent=4) except Exception as e: log.error(f"Failed to write reports to file: {e}") log.debug("Sending results to Carbon Black Cloud.") if report_list_to_send: try: feed.append_reports(report_list_to_send) log.info(f"Appended {len(report_list_to_send)} reports to Enterprise EDR Feed {feed_id}") except Exception as e: log.debug(f"Failed sending {len(report_list_to_send)} reports: {e}") if malformed_reports: log.warning("Some report(s) failed validation. See malformed_reports.json for reports that failed.") try: with open('malformed_reports.json', 'w') as f: json.dump(malformed_reports, f, indent=4) except Exception as e: log.error(f"Failed to write malformed_reports to file: {e}")