def __new__(mcs, name, bases, clsdict): swagger_meta_file = clsdict.pop("swagger_meta_file", None) model_data = {} if swagger_meta_file: model_data = yaml.load( open(os.path.join(mcs.model_base_directory, swagger_meta_file), 'rb').read()) clsdict["__doc__"] = "Represents a %s object in the Carbon Black server.\n\n" % (name,) for field_name, field_info in iteritems(model_data.get("properties", {})): docstring = field_info.get("description", None) if docstring: clsdict["__doc__"] += ":ivar %s: %s\n" % (field_name, docstring) foreign_keys = clsdict.pop("foreign_keys", {}) cls = super(CbMetaModel, mcs).__new__(mcs, name, bases, clsdict) mcs.model_classes.append(cls) cls._valid_fields = [] cls._required_fields = model_data.get("required", []) cls._default_value = {} for field_name, field_info in iteritems(model_data.get("properties", {})): cls._valid_fields.append(field_name) default_value = field_info.get("default", None) if default_value: cls._default_value[field_name] = default_value field_format = field_info.get("type", "string") field_format = field_info.get("format", field_format) if field_format.startswith('int'): setattr(cls, field_name, FieldDescriptor(field_name, coerce_to=int)) elif field_format == "date-time": setattr(cls, field_name, DateTimeFieldDescriptor(field_name)) elif field_format == "boolean": setattr(cls, field_name, FieldDescriptor(field_name, coerce_to=bool)) elif field_format == "array": setattr(cls, field_name, ArrayFieldDescriptor(field_name)) elif field_format == "object": setattr(cls, field_name, ObjectFieldDescriptor(field_name)) elif field_format == "double": setattr(cls, field_name, FieldDescriptor(field_name, coerce_to=float)) elif field_format == "byte": setattr(cls, field_name, BinaryFieldDescriptor(field_name)) else: setattr(cls, field_name, FieldDescriptor(field_name)) for fk_name, fk_info in iteritems(foreign_keys): setattr(cls, fk_name, ForeignKeyFieldDescriptor(fk_name, fk_info[0], fk_info[1])) return cls
def report_result(self, binary, scanResults): # We have results. Create our notification n = binary.create_notification(data={ "product": "VirusTotal", "malwareName": "", "malwareType": "" }) # Let's see if it is malicious. Use some fancy heuristics... positivesPerc = 100 * scanResults.get('positives') / scanResults.get( 'total') if positivesPerc > self.malicious_threshold: n.analysisResult = Notification.ResultMalicious n.severity = "critical" n.type = "malicious_file" elif positivesPerc > self.potential_threshold: n.analysisResult = Notification.ResultPotentialThreat n.severity = "high" n.type = "potential_risk_file" else: n.analysisResult = Notification.ResultClean n.severity = "low" n.type = "clean_file" n.externalUrl = scanResults.get('permalink') # Enumerate scan results that have detected the issue and build our # 'malwareName' string for the notification scans = scanResults.get("scans", {}) malware_type = [ k + ":" + v["result"] for k, v in iteritems(scans) if v["detected"] ] malware_name = [ v["result"] for k, v in iteritems(scans) if v["detected"] ] n.malwareType = "; ".join(malware_type[:4]) n.malwareName = "; ".join(malware_name[:4]) if len(malware_type) > 4: n.malwareName += "..." n.malwareType += "..." # Send notification n.save() if binary.fileHash in self.awaiting_results: del self.awaiting_results[binary.fileHash] log.info( "VT analysis for %s completed. VT result is %d%% malware (%s). Reporting status: %s" % (binary.fileHash, positivesPerc, n.malwareName, n.type))
def cleanup(self): marked_for_deletion = set() if self.expiration is None: return None t = int(time.time()) # Delete expired next_expire = None for k, v in iteritems(self.__expire_times): if v < t: marked_for_deletion.add(k) else: next_expire = v break for k in marked_for_deletion: self.__delete__(k) marked_for_deletion = set() # If we have more than self.max_size items, delete the oldest if len(self.__values) > self.max_size: number_to_delete = len(self.__values) - self.max_size marked_for_deletion = [k for k in islice(self.__access_times, number_to_delete)] for k in marked_for_deletion: self.__delete__(k) if not (next_expire is None): return next_expire - t else: return None
def main(): parser = build_cli_parser("Delete duplicate computers") parser.add_argument( "--dry-run", "-d", help="perform a dry run, don't actually delete the computers", action="store_true", dest="dry_run") args = parser.parse_args() p = get_cb_protection_object(args) computer_list = defaultdict(list) for computer in p.select(Computer).where("deleted:false"): computer_list[computer.name].append({ "id": computer.id, "offline": computer.daysOffline }) for computer_name, computer_ids in iteritems(computer_list): if len(computer_ids) > 1: sorted_computers = sorted(computer_ids, key=lambda x: x["offline"], reverse=True) for computer_id in sorted_computers[:-1]: if computer_id["offline"] > 0: print( "deleting computer id %d (offline %d days, hostname %s)" % (computer_id["id"], computer_id["offline"], computer_name)) if not args.dry_run: print("deleting from server...") p.select(Computer, computer_id["id"]).delete()
def cleanup(self): marked_for_deletion = set() if self.expiration is None: return None t = int(time.time()) # Delete expired next_expire = None for k, v in iteritems(self.__expire_times): if v < t: marked_for_deletion.add(k) else: next_expire = v break for k in marked_for_deletion: self.__delete__(k) marked_for_deletion = set() # If we have more than self.max_size items, delete the oldest if len(self.__values) > self.max_size: number_to_delete = len(self.__values) - self.max_size marked_for_deletion = [ k for k in islice(self.__access_times, number_to_delete) ] for k in marked_for_deletion: self.__delete__(k) if not (next_expire is None): return next_expire - t else: return None
def raise_unless_json(self, ret, expected): if ret.status_code == 200: message = ret.json() for k, v in iteritems(expected): if k not in message or message[k] != v: raise ServerError(ret.status_code, message) else: raise ServerError(ret.status_code, "".format(ret.content), )
def reset(self): for k, v in iteritems(self._dirty_attributes): if v is None: del self._info[k] else: self._info[k] = v self._dirty_attributes = {}
def raise_unless_json(self, ret, expected): if ret.status_code == 200: message = ret.json() for k, v in iteritems(expected): if k not in message or message[k] != v: raise ServerError(ret.status_code, message) else: raise ServerError(ret.status_code, "".format(ret.content), )
def convert_query_params(qd): o = [] for k, v in iteritems(qd): if type(v) == list: for item in v: o.append((k, item)) else: o.append((k, v)) return o
def convert_query_params(qd): o = [] for k, v in iteritems(qd): if type(v) == list: for item in v: o.append((k, item)) else: o.append((k, v)) return o
def _match_query(self, i): for k, v in iteritems(self._query): if isinstance(v, six.string_types): v = v.lower() target = getattr(i, k, None) if target is None: return False if str(target).lower() != v: return False return True
def _match_query(self, i): for k, v in iteritems(self._query): if isinstance(v, six.string_types): v = v.lower() target = getattr(i, k, None) if target is None: return False if str(target).lower() != v: return False return True
def report_result(self, binary, scanResults): # We have results. Create our notification n = binary.create_notification(data={"product": "VirusTotal", "malwareName": "", "malwareType": ""}) # Let's see if it is malicious. Use some fancy heuristics... positivesPerc = 100 * scanResults.get('positives') / scanResults.get('total') if positivesPerc > self.malicious_threshold: n.analysisResult = Notification.ResultMalicious n.severity = "critical" n.type = "malicious_file" elif positivesPerc > self.potential_threshold: n.analysisResult = Notification.ResultPotentialThreat n.severity = "high" n.type = "potential_risk_file" else: n.analysisResult = Notification.ResultClean n.severity = "low" n.type = "clean_file" n.externalUrl = scanResults.get('permalink') # Enumerate scan results that have detected the issue and build our # 'malwareName' string for the notification scans = scanResults.get("scans", {}) malware_type = [k + ":" + v["result"] for k, v in iteritems(scans) if v["detected"]] malware_name = [v["result"] for k, v in iteritems(scans) if v["detected"]] n.malwareType = "; ".join(malware_type[:4]) n.malwareName = "; ".join(malware_name[:4]) if len(malware_type) > 4: n.malwareName += "..." n.malwareType += "..." # Send notification n.save() if binary.fileHash in self.awaiting_results: del self.awaiting_results[binary.fileHash] log.info("VT analysis for %s completed. VT result is %d%% malware (%s). Reporting status: %s" % (binary.fileHash, positivesPerc, n.malwareName, n.type))
def main(args): parser = argparse.ArgumentParser() commands = parser.add_subparsers(dest="command_name", help="CbAPI subcommand") for cmd_name, cmd_config in iteritems(command_map): cmd_parser = commands.add_parser(cmd_name, help=cmd_config.get("help", None)) for cmd_arg_name, cmd_arg_config in iteritems(cmd_config.get("extra_args", {})): cmd_parser.add_argument(cmd_arg_name, **cmd_arg_config) opts = parser.parse_args(args) command = command_map.get(opts.command_name) if not command: parser.print_usage() return command_method = command.get("method", None) if command_method: return command_method(opts) else: parser.print_usage()
def main(): parser = build_cli_parser("VirusTotal Connector") parser.add_argument("--config", "-c", help="Path to configuration file", default="virustotal.ini") args = parser.parse_args() inifile = RawConfigParser({ "vt_api_key": None, "retrieve_files": "true", "upload_binaries_to_vt": "false", "connector_name": "VirusTotal", "log_file": None, }) inifile.read(args.config) config = {} config["vt_api_key"] = inifile.get("bridge", "vt_api_key") config["retrieve_files"] = inifile.getboolean("bridge", "retrieve_files") config["connector_name"] = inifile.get("bridge", "connector_name") config["upload_binaries_to_vt"] = inifile.getboolean( "bridge", "upload_binaries_to_vt") log_file = inifile.get("bridge", "log_file") if log_file: file_handler = logging.FileHandler(log_file) formatter = logging.Formatter('%(asctime)s %(levelname)s:%(message)s') file_handler.setFormatter(formatter) file_handler.setLevel(logging.DEBUG) logging.getLogger().addHandler(file_handler) if not config["vt_api_key"]: log.fatal("Cannot start without a valid VirusTotal API key, exiting") return 1 log.info("Configuration:") for k, v in iteritems(config): log.info(" %-20s: %s" % (k, v)) api = get_cb_protection_object(args) vt = VirusTotalConnector( api, vt_token=config["vt_api_key"], allow_uploads=config[ "upload_binaries_to_vt"], # Allow VT connector to upload binary files to VirusTotal connector_name=config["connector_name"], ) log.info("Starting VirusTotal processing loop") vt.run()
def get_credentials(self, profile=None): credential_profile = profile or "default" if credential_profile not in self.get_profiles(): raise CredentialError("Cannot find credential profile '%s' after searching in these files: %s." % (credential_profile, ", ".join(self.credential_search_path))) retval = {} for k, v in six.iteritems(default_profile): retval[k] = self.credentials.get(credential_profile, k) if not retval["url"] or not retval["token"]: raise CredentialError("Token and/or URL not available for profile %s" % credential_profile) return Credentials(retval)
def get_credentials(self, profile=None): credential_profile = profile or "default" if credential_profile not in self.get_profiles(): raise CredentialError("Cannot find credential profile '%s' after searching in these files: %s." % (credential_profile, ", ".join(self.credential_search_path))) retval = {} for k, v in six.iteritems(default_profile): retval[k] = self.credentials.get(credential_profile, k) if not retval["url"] or not retval["token"]: raise CredentialError("Token and/or URL not available for profile %s" % credential_profile) return Credentials(retval)
def main(): parser = build_cli_parser() args = parser.parse_args() c = get_cb_response_object(args) hostname_user_pairs = defaultdict(ItemCount) username_activity = defaultdict(ItemCount) for proc in c.select(Process).where("process_name:explorer.exe"): hostname_user_pairs[proc.hostname].add(proc.username) username_activity[proc.username].add(proc.hostname) for hostname, user_activity in iteritems(hostname_user_pairs): print("For host {0:s}:".format(hostname)) for username, count in user_activity.report(): print(" %-20s: logged in %d times" % (username, count))
def create(self, cls, data=None): """Creates a new object. :param class cls: The Model class (only some models can be created, for example, Feed, Notification, ...) :returns: An empty instance of the Model class :raises ApiError: if the Model cannot be created """ if issubclass(cls, CreatableModelMixin): n = cls(self) if type(data) is dict: for k, v in iteritems(data): setattr(n, k, v) return n else: raise ApiError("Cannot create object of type {0:s}".format(cls.__name__))
def create(self, cls, data=None): """Creates a new object. :param class cls: The Model class (only some models can be created, for example, Feed, Notification, ...) :returns: An empty instance of the Model class :raises ApiError: if the Model cannot be created """ if issubclass(cls, CreatableModelMixin): n = cls(self) if type(data) is dict: for k, v in iteritems(data): setattr(n, k, v) return n else: raise ApiError("Cannot create object of type {0:s}".format(cls.__name__))
def main(): parser = build_cli_parser() args = parser.parse_args() c = get_cb_response_object(args) hostname_user_pairs = defaultdict(ItemCount) username_activity = defaultdict(ItemCount) for proc in c.select(Process).where("process_name:explorer.exe"): hostname_user_pairs[proc.hostname].add(proc.username) username_activity[proc.username].add(proc.hostname) for hostname, user_activity in iteritems(hostname_user_pairs): print("For host {0:s}:".format(hostname)) for username, count in user_activity.report(): print(" %-20s: logged in %d times" % (username, count))
def main(): parser = build_cli_parser("VirusTotal Connector") parser.add_argument("--config", "-c", help="Path to configuration file", default="virustotal.ini") args = parser.parse_args() inifile = RawConfigParser({ "vt_api_key": None, "retrieve_files": "true", "upload_binaries_to_vt": "false", "connector_name": "VirusTotal", "log_file": None, }) inifile.read(args.config) config = {} config["vt_api_key"] = inifile.get("bridge", "vt_api_key") config["retrieve_files"] = inifile.getboolean("bridge", "retrieve_files") config["connector_name"] = inifile.get("bridge", "connector_name") config["upload_binaries_to_vt"] = inifile.getboolean("bridge", "upload_binaries_to_vt") log_file = inifile.get("bridge", "log_file") if log_file: file_handler = logging.FileHandler(log_file) formatter = logging.Formatter('%(asctime)s %(levelname)s:%(message)s') file_handler.setFormatter(formatter) file_handler.setLevel(logging.DEBUG) logging.getLogger().addHandler(file_handler) if not config["vt_api_key"]: log.fatal("Cannot start without a valid VirusTotal API key, exiting") return 1 log.info("Configuration:") for k, v in iteritems(config): log.info(" %-20s: %s" % (k,v)) api = get_cb_protection_object(args) vt = VirusTotalConnector( api, vt_token=config["vt_api_key"], allow_uploads=config["upload_binaries_to_vt"], # Allow VT connector to upload binary files to VirusTotal connector_name=config["connector_name"], ) log.info("Starting VirusTotal processing loop") vt.run()
def raise_unless_json(self, ret, expected): """ Raise a ServerError unless we got back an HTTP 200 response with JSON containing all the expected values. Args: ret (object): Return value to be checked. expected (dict): Expected keys and values that need to be found in the JSON response. Raises: ServerError: If the HTTP response is anything but 200, or if the expected values are not found. """ if ret.status_code == 200: message = ret.json() for k, v in iteritems(expected): if k not in message or message[k] != v: raise ServerError(ret.status_code, message) else: raise ServerError( ret.status_code, "{0}".format(ret.content), )
def main(): parser = build_cli_parser("Delete duplicate computers") parser.add_argument("--dry-run", "-d", help="perform a dry run, don't actually delete the computers", action="store_true", dest="dry_run") args = parser.parse_args() p = get_cb_protection_object(args) computer_list = defaultdict(list) for computer in p.select(Computer).where("deleted:false"): computer_list[computer.name].append({"id": computer.id, "offline": computer.daysOffline}) for computer_name, computer_ids in iteritems(computer_list): if len(computer_ids) > 1: sorted_computers = sorted(computer_ids, key=lambda x: x["offline"], reverse=True) for computer_id in sorted_computers[:-1]: if computer_id["offline"] > 0: print("deleting computer id %d (offline %d days, hostname %s)" % (computer_id["id"], computer_id["offline"], computer_name)) if not args.dry_run: print("deleting from server...") p.select(Computer, computer_id["id"]).delete()
def create(self, cls, data=None): """ Create a new object. Args: cls (class): The Model class (only some models can be created, for example, Feed, Notification, ...) data (object): The data used to initialize the new object Returns: Model: An empty instance of the model class. Raises: ApiError: If the Model cannot be created. """ if issubclass(cls, CreatableModelMixin): n = cls(self) if type(data) is dict: for k, v in iteritems(data): setattr(n, k, v) return n else: raise ApiError("Cannot create object of type {0:s}".format( cls.__name__))
def reset(self): """Reset all changes made to this object.""" for k, v in iteritems(self._dirty_attributes): self._info[k] = v self._dirty_attributes = {}
def reset(self): for k, v in iteritems(self._dirty_attributes): self._info[k] = v self._dirty_attributes = {}
def reset(self): for k, v in iteritems(self._dirty_attributes): self._info[k] = v self._dirty_attributes = {}