def statement_type_as_extension_properties(container, statement, property_name, id, is_list, is_literal, mapping): map = dict() if statement.descriptions: descriptions = [] for d in statement.descriptions: descriptions.append(str(d.value)) map["description"] = " ".join(descriptions) if statement.source is not None: # FIXME: Handle source info("Source property in STIX 1.x statement is not handled, yet.", 815) if statement.confidence: add_confidence_property_as_extension_property(map, statement.confidence, property_name, id) converted_value = None if statement.value: value_as_string = str(statement.value) if is_literal: if value_as_string in mapping: converted_value = mapping[value_as_string] else: converted_value = convert_to_stix_literal(value_as_string) else: converted_value = value_as_string if map: if converted_value: map["value"] = converted_value container[property_name] = [map] if is_list else map else: if converted_value: container[property_name] = [converted_value ] if is_list else converted_value
def add_statement_type_as_custom_or_extension_property(statement, is_literal, mapping={}): statement_json = {} if statement.value: value_as_string = str(statement.value) if is_literal: if value_as_string in mapping: statement_json["value"] = mapping[value_as_string] else: statement_json["value"] = convert_to_stix_literal( value_as_string) else: statement_json["value"] = value_as_string if statement.descriptions: descriptions = [] for d in statement.descriptions: descriptions.append(str(d.value)) statement_json["description"] = " ".join(descriptions) if statement.source is not None: # FIXME: Handle source info("Source property in STIX 1.x statement is not handled, yet.", 815) if statement.confidence: handle_missing_confidence_property(statement_json, statement.confidence, None) return statement_json
def fix_cybox_relationships(observed_data): for o in observed_data: objs_to_add = {} if not o["objects"]: continue next_id = int(max(o["objects"].keys())) + 1 for co in o["objects"].values(): if co["type"] == "email-message": if co["is_multipart"]: for mp in co["body_multipart"]: objs = get_object_id_value(mp["body_raw_ref"]) if objs: root_obj_index = find_index_of_type(objs, "file") if root_obj_index is not None: # 0 is a good value mp["content_type"] = "text/plain" info( "content_type for body_multipart of %s is assumed to be 'text/plain'", 722, o["id"]) root_data = objs[root_obj_index] if root_data: present_obj_index = find_index_of_contents( root_data, o["objects"]) if present_obj_index is None: # 0 is a good value next_id, number_mapping = do_renumbering( objs, next_id, root_obj_index, objs_to_add) mp["body_raw_ref"] = text_type( number_mapping[root_obj_index]) else: mp["body_raw_ref"] = text_type( present_obj_index) # TODO: warnings if objs_to_add: add_objects(o["objects"], objs_to_add)
def record_ids(stix_id, new_id): if stix_id in _IDS_TO_NEW_IDS: info("%s is already associated other ids: %s", 703, str(stix_id), tuple(_IDS_TO_NEW_IDS[stix_id])) if new_id is None: error("Can not associate %s with None", 611, stix_id) return add_id_value(stix_id, new_id)
def record_ids(stix_id, new_id): if stix_id in _IDS_TO_NEW_IDS: info("%s is already associated other ids: %s", 703, text_type(stix_id), tuple(_IDS_TO_NEW_IDS[stix_id])) # info("associating " + new_id + " with " + id) if new_id is None: error("Could not associate %s with None", 611, stix_id) return add_id_value(stix_id, new_id)
def statement_type_as_properties(sdo_instance, statement, property_name): if statement.value: sdo_instance[convert_to_custom_name(property_name)] = text_type(statement.value) if statement.descriptions: descriptions = [] for d in statement.descriptions: descriptions.append(text_type(d.value)) sdo_instance[convert_to_custom_name(property_name) + "_description"] = " ".join(descriptions) if statement.source is not None: # FIXME: Handle source info("Source property in STIX 1.x statement is not handled, yet.", 815) if statement.confidence: add_confidence_property_as_custom_property(sdo_instance, statement.confidence, property_name)
def add_statement_type_as_custom_property(statement): statement_json = {} if statement.value: statement_json["value"] = text_type(statement.value) if statement.descriptions: descriptions = [] for d in statement.descriptions: descriptions.append(text_type(d.value)) statement_json["description"] = " ".join(descriptions) if statement.source is not None: # FIXME: Handle source info("Source property in STIX 1.x statement is not handled, yet.", 815) if statement.confidence: add_confidence_property_as_custom_property(statement_json, statement.confidence) return statement_json
def convert_timestamp_to_string(timestamp, entity=None, parent_timestamp=None, milliseconds_only=False): if timestamp is not None: return strftime_with_appropriate_fractional_seconds( timestamp, milliseconds_only) elif parent_timestamp is not None: info("Using parent object timestamp on %s", 902, identifying_info(entity)) return strftime_with_appropriate_fractional_seconds( parent_timestamp, milliseconds_only) else: warn("Timestamp not available for %s, using current time", 905, identifying_info(entity)) return strftime_with_appropriate_fractional_seconds( datetime.now(), milliseconds_only)
def add_statement_type_to_description(sdo_instance, statement, property_name): sdo_instance["description"] += "\n\n" + property_name.upper() + ":" has_value = False if statement.value: sdo_instance["description"] += text_type(statement.value) has_value = True if statement.descriptions: descriptions = [] for d in statement.descriptions: descriptions.append(text_type(d.value)) sdo_instance["description"] += (": " if has_value else "") + "\n\n\t".join(descriptions) if statement.source is not None: # FIXME: Handle source info("Source in %s is not handled, yet.", 815, sdo_instance["id"]) if statement.confidence: add_confidence_property_to_description(sdo_instance, statement.confidence, property_name) warn("Appended Statement type content to description of %s", 305, sdo_instance["id"])
def convert_timestamp(entity, parent_timestamp=None, milliseconds_only=False): if entity and hasattr(entity, "timestamp"): if entity.timestamp is not None: return strftime_with_appropriate_fractional_seconds( entity.timestamp, milliseconds_only) if parent_timestamp is not None: info("Using parent object timestamp on %s", 902, identifying_info(entity)) # parent_timestamp might have already been converted to a string in a previous call if isinstance(parent_timestamp, text_type): return parent_timestamp else: return strftime_with_appropriate_fractional_seconds( parent_timestamp, milliseconds_only) warn("Timestamp not available for %s, using current time", 905, identifying_info(entity)) return strftime_with_appropriate_fractional_seconds( datetime.now(), milliseconds_only)
def statement_type_as_extension_properties(container, statement, property_name, id, is_list): map = dict() if statement.descriptions: descriptions = [] for d in statement.descriptions: descriptions.append(str(d.value)) map["description"] = " ".join(descriptions) if statement.source is not None: # FIXME: Handle source info("Source property in STIX 1.x statement is not handled, yet.", 815) if statement.confidence: add_confidence_property_as_extension_property(map, statement.confidence, property_name, id) if map: if statement.value: map["value"] = str(statement.value) container[property_name] = [map] if is_list else map else: container[property_name] = [str(statement.value)] if is_list else str( statement.value)
def statement_type_as_custom_properties(sdo_instance, statement, property_name, is_list): map = dict() if statement.descriptions: descriptions = [] for d in statement.descriptions: descriptions.append(str(d.value)) map["description"] = " ".join(descriptions) if statement.source is not None: # FIXME: Handle source info("Source property in STIX 1.x statement is not handled, yet.", 815) if statement.confidence: add_confidence_property_as_custom_property(map, statement.confidence, property_name) if map: if statement.value: map["value"] = str(statement.value) sdo_instance[convert_to_custom_name(property_name)] = [ map ] if is_list else map else: sdo_instance[convert_to_custom_name(property_name)] = [ str(statement.value) ] if is_list else str(statement.value)
def elevate(stix_package): global MESSAGES_GENERATED MESSAGES_GENERATED = False print( "Results produced by the stix2-elevator are not for production purposes." ) clear_globals() fn = None validator_options = get_validator_options() output.set_level(validator_options.verbose) output.set_silent(validator_options.silent) try: if isinstance(stix_package, MarkingContainer): # No need to re-parse the MarkingContainer. container = stix_package elif isinstance(stix_package, STIXPackage): bytes_obj = io.BytesIO(stix_package.to_xml()) container = stixmarx.parse(bytes_obj) elif isinstance(stix_package, str): if stix_package.endswith(".xml") or os.path.isfile(stix_package): # a path-like string was passed fn = stix_package if os.path.exists(fn) is False: raise IOError("The file '{}' was not found.".format(fn)) else: stix_package = io.StringIO(stix_package) container = stixmarx.parse(stix_package) elif isinstance(stix_package, bytes): if stix_package.endswith(b".xml") or os.path.isfile(stix_package): # a path-like string was passed fn = stix_package if os.path.exists(fn) is False: raise IOError("The file '{}' was not found.".format(fn)) else: stix_package = io.BytesIO(stix_package) container = stixmarx.parse(stix_package) else: raise RuntimeError("Unable to resolve object {} of type {}".format( stix_package, type(stix_package))) container_package = container.package set_option_value("marking_container", container) if not isinstance(container_package, STIXPackage): raise TypeError("Must be an instance of stix.core.STIXPackage") except (OSError, IOError, lxml.etree.Error) as ex: log.error("Error occurred: %s", ex) return None try: setup_logger(container_package.id_) info( "Results produced by the stix2-elevator may generate warning messages which should be investigated.", 201) env = Environment(get_option_value("package_created_by_id")) json_string = json.dumps(convert_package(container_package, env), ensure_ascii=False, indent=4, separators=(',', ': '), sort_keys=True) bundle_id = re.findall( r"bundle--[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}", json_string) validation_results = validate_stix2_string(json_string, validator_options, fn or bundle_id[0]) output.print_results([validation_results]) if get_option_value("policy") == "no_policy": return json_string else: if not MESSAGES_GENERATED and validation_results._is_valid: return json_string except ValidationError as ex: output.error("Validation error occurred: '{}'".format(ex)) output.error("Error Code: {}".format(codes.EXIT_VALIDATION_ERROR))